Install
$ npx skills add more-io/claude-apple-bridgesREADME
# GitHub Repository: more-io/claude-apple-bridges
**URL:** https://github.com/more-io/claude-apple-bridges
**Author:** more-io
**Description:** Swift CLI bridges giving Claude Code native access to Apple Reminders, Calendar, Contacts, Notes, Mail and tmux — includes Claude Code skill with full command reference
**Homepage:** https://github.com/more-io/claude-apple-bridges
**Language:** Swift
## Stats
- Stars: 24
- Forks: 2
- Open Issues: 0
- Commits: 53
- Created: 2026-02-22T14:17:20Z
- Updated: 2026-06-10T21:35:32Z
- Pushed: 2026-05-27T07:46:31Z
## README
# Claude Apple Bridges



Swift CLI tools that give [Claude Code](https://claude.ai/claude-code) native access to Apple apps — Reminders, Calendar, Contacts, Notes, Mail, and tmux. Includes a [Claude Code skill](#skills) (`/apple-bridges`) with complete command reference for all bridges.
## Usage Examples with Claude Code
Once set up, you can ask Claude naturally in any Claude Code session. Here are real-world examples:
---
### Task & Project Management
> *"What's on my todo list for today?"*
Claude checks your Reminders and summarizes open items with due dates and priorities.
> *"I just finished the login bug fix — mark the GitHub issue and the reminder as done."*
Claude closes the GitHub issue and calls `reminders-bridge complete` in one step.
> *"Add a reminder to my 'Work' list to review the PR tomorrow morning."*
Claude creates the reminder with a due date set to tomorrow at 9:00.
---
### Calendar-Aware Scheduling
> *"I want to work on the Android release tomorrow — find a free slot and set a reminder."*
Claude checks `calendar-bridge tomorrow`, finds a free window, and sets the reminder due date accordingly — no double-booking.
> *"What do I have going on this week? Block some time for code review."*
Claude reads your calendar for each day, spots gaps, and adds events or reminders where they fit.
> *"Schedule our next planning session for next Monday at 10am in my Work calendar."*
Claude calls `calendar-bridge add` directly without you having to open Calendar.
---
### Contacts Lookup
> *"What's Rob's phone number?"*
Claude searches your Contacts and returns the number directly — no need to open the Contacts app.
> *"Add Alex to my contacts: +49 123 456789, [email protected]"*
Claude calls `contacts-bridge add` and confirms once saved.
> *"Show me all details for my contact Thomas."*
Claude returns name, phone, email, address and birthday in one view.
---
### Development Workflow Integration
> *"Start working on issue #42 — create a reminder to track it and add the 'in progress' label."*
Claude adds a GitHub label, creates a Reminders entry with the issue number in the notes, and sets a due date.
> *"We finished the feature — close the issue, complete the reminder, and write the release note."*
Claude handles all three in one go.
> *"What are my open todos related to this project?"*
Claude reads your Reminders list and cross-references with open GitHub issues for a full picture.
---
### End-of-Day / Planning
> *"Summarize what we did today and create reminders for anything we didn't finish."*
Claude reviews the session, identifies incomplete work, and adds follow-up reminders with appropriate due dates.
> *"Set reminders for all open todos so they show up in my Calendar tomorrow after my meetings."*
Claude reads tomorrow's calendar first to avoid conflicts, then sets due times in the free slots.
---
## Bridges
### reminders-bridge
Access and manage Apple Reminders from Claude Code.
```
reminders-bridge lists List all reminder lists
reminders-bridge create-list <name> Create a new list
reminders-bridge rename-list <old> <new> Rename an existing list
reminders-bridge delete-list <name> Delete a list (and all its reminders)
reminders-bridge items <list> Show all reminders in a list
reminders-bridge incomplete <list> Show only incomplete reminders
reminders-bridge today Show reminders due today (all lists)
reminders-bridge overdue Show all overdue reminders (all lists)
reminders-bridge search <query> Search by title/notes across all lists
reminders-bridge add <list> <title> [notes] Add a new reminder
reminders-bridge set-due <list> <title> <datetime> Set due date (YYYY-MM-DD HH:mm)
reminders-bridge set-notes <list> <title> <notes> Set or update notes
reminders-bridge rename <list> <oldTitle> <newTitle> Rename a reminder (title only, preserves notes/due)
reminders-bridge complete <list> <title> Mark a reminder as complete
reminders-bridge delete <list> <title> [--force] Delete a reminder (dry-run without --force)
```
### calendar-bridge
Read and write Apple Calendar events from Claude Code.
```
calendar-bridge calendars List all calendars
calendar-bridge today Show today's events
calendar-bridge tomorrow Show tomorrow's events
calendar-bridge week Show this week's events
calendar-bridge events <YYYY-MM-DD> Show events for a date
calendar-bridge free-slots <YYYY-MM-DD> Show free time slots (08:00–20:00)
calendar-bridge search <query> Search events by title (next 365 days)
calendar-bridge add <cal> <title> <start> <end> Add event (YYYY-MM-DD HH:mm)
calendar-bridge add-all-day <cal> <title> <YYYY-MM-DD> Add all-day event
calendar-bridge delete <cal> <title> <YYYY-MM-DD> [--force] Delete event (dry-run without --force)
```
### contacts-bridge
Search and manage Apple Contacts from Claude Code.
```
contacts-bridge search <query> Search by name, email or phone
contacts-bridge show <name> Show full details for a contact
contacts-bridge add <firstName> <lastName> [phone] [email] Add a new contact
contacts-bridge update <name> phone <value> Update phone number
contacts-bridge update <name> email <value> Update email address
contacts-bridge delete <name> [--force] Delete a contact (dry-run without --force)
contacts-bridge birthdays-today Contacts with birthday today
contacts-bridge birthdays-upcoming <days> Upcoming birthdays in next N days
```
### notes-bridge
Read and write Apple Notes from Claude Code.
```
notes-bridge accounts List all accounts
notes-bridge folders [account] List folders (default: iCloud)
notes-bridge list [folder] [account] List notes with modification date
notes-bridge search <query> Search by title and content across all accounts
notes-bridge read <title> [account] Read note content as plain text
notes-bridge add <folder> <title> <body> [account] Create a new note
notes-bridge append <title> <text> [account] Append text to an existing note
notes-bridge delete <title> [--force] [account] Delete a note (dry-run without --force)
```
**Formatting:** The `body` and `text` parameters support HTML — Notes.app renders it natively.
```bash
# Plain text note
notes-bridge add "Ideas" "Shopping" "Milk, Bread, Eggs"
# Rich note with HTML formatting
notes-bridge add "Work" "Meeting Notes" "<b>Attendees:</b> Tobias, Heiko<br><br><ul><li>Discussed Q1 roadmap</li><li>Next steps: review PR</li></ul>"
# Append a formatted section
notes-bridge append "Meeting Notes" "<br><b>Follow-up:</b><br><ul><li>Send report by Friday</li></ul>"
```
Supported HTML tags: `<b>`, `<i>`, `<u>`, `<br>`, `<ul>`, `<ol>`, `<li>`, `<h1>`–`<h3>`, `<a href="...">`, `<p>`
### mail-bridge
Read and send Apple Mail messages from Claude Code.
```
mail-bridge accounts List all email accounts
mail-bridge mailboxes [account] List mailboxes (default: first account)
mail-bridge list [mailbox|account] [account] [count] List recent messages (auto-detects account names)
mail-bridge unread [mailbox|account] [account] [--all] [--max N] [--since X] List unread — fast (server-side filter); --all = every account
mail-bridge search <query> [max_results] [account] [--unread] [--since X] Search subject/sender — output includes <mid:...> for each hit
mail-bridge read <index> [mailbox] [account] Read message (unread status preserved)
mail-bridge read <index> [mailbox] [account] --mark-read Read message and mark as read
mail-bridge read <index> [mailbox] [account] --raw Read raw RFC822 source (HTML + MIME attachments)
mail-bridge read --mid <message-id> [account] [--mark-read] [--raw] Read by RFC822 message-id (no listing needed) — fetches full body
mail-bridge send <to> <subject> <body> [/attachment] [--from <email>] Opens compose window — user reviews and sends manually
mail-bridge send <to> <subject> <body> [/attachment] [--from <email>] --force Sends directly without UI
mail-bridge delete <index> [mailbox] [account] [--force] Move to Trash (dry-run without --force)
```
**`--since` accepts** `Nd` / `Nw` / `Nm` (days/weeks/months), a bare integer (days), or `YYYY-MM-DD`.
**Unread / search performance:** both commands push the filter into Mail.app via a `whose` clause, so Mail scans the mailbox internally instead of the bridge fetching every message's properties over IPC. On a 50k-message INBOX the old behaviour took minutes; the filtered variant returns in ~1s per account. Use `--since 7d` to narrow further on servers that index slowly.
```bash
# All unread across every account, last 7 days, cap at 20
mail-bridge unread --all --since 7d --max 20
# Only unread results when searching
mail-bridge search "invoice" --unread --since 30d
```
**`--mid` example — fetch a specific message without knowing its INBOX index:**
`search` now prints an `<mid:...>` token for every hit (RFC822 Message-ID).
Pass it to `read --mid` to fetch the full message directly — no expensive
`list` walk required, and Mail.app downloads the body if it was only
partially cached.
```bash
mail-bridge search "invoice" 50 [email protected] --since 90d
# Found 7 message(s) (last 90d):
# <mid:[email protected]> Invoice #4711 — [email protected] (3/15)
# ...
mail-bridge read --mid "[email protected]" [email protected] --raw > /tmp/mail.eml
```
**`--raw` example — extract PDF attachments from invoice emails:**
```bash
# Dump the raw message source (RFC822, includes HTML body + MIME attachments)
mail-bridge read 42 INBOX [email protected] --raw > /tmp/mail.eml
# Then parse with Python to save any PDF attachment
python3 <<'EOF'
import email
raw = open('/tmp/mail.eml').read().split('\n---\n', 1)[1]
msg = email.message_from_string(raw)
for part in msg.walk():
fn = part.get_filename() or ''
if fn.endswith('.pdf'):
open(f'/tmp/{fn}', 'wb').write(part.get_payload(decode=True))
print('Saved', fn)
EOF
```
Use `--raw` when the default plain-text body strips URLs, images, or attachments you need (e.g. Stripe invoice links, PDF receipts, ticket attachments).
**Send examples:**
```bash
# Ask Claude to draft a reply → compose window opens in Mail.app for review:
mail-bridge send [email protected] "Betreff" "Hallo Heiko, ..."
# Claude sends automatically without user interaction (explicit intent required):
mail-bridge send [email protected] "Betreff" "Hallo Heiko, ..." --force
# With attachment and explicit sender:
mail-bridge send [email protected] "Report" "See attached." /tmp/report.pdf --from [email protected] --force
```
### tmux-bridge
Read and write tmux session contents from Claude Code — great for end-of-day summaries and interactive terminal control.
```
tmux-bridge sessions List all running sessions
tmux-bridge windows [session] List windows in a session
tmux-bridge panes [session] List all panes with path and command
tmux-bridge read <target> [lines] Read pane content (e.g. main:1.1, default: 1000 lines)
tmux-bridge write <target> <text> [--no-enter] Send keystrokes to a pane
tmux-bridge snapshot [session] [lines] Capture all panes at once (default: 5000 lines)
```
**Write examples:**
```bash
# Send a command (text + Enter)
tmux-bridge write main:0.0 "ls -la"
# Send text without pressing Enter
tmux-bridge write main:0.0 "partial input" --no-enter
```
Typical workflow: run your work in named tmux sessions, then ask Claude at the end of the day:
> *"Read tmux-bridge snapshot and summarize what I worked on today."*
---
## Setup
### 1. Compile
```bash
# Install all bridges at once (recommended)
git clone https://github.com/more-io/claude-apple-bridges.git
cd claude-apple-bridges
make install
```
**Optional: Persistent TCC permissions with a Developer certificate**
By default, bridges are ad-hoc signed. macOS TCC may re-prompt for permissions in new terminal sessions (especially remote/SSH). If you have an Apple Developer certificate, pass `CODESIGN_IDENTITY` for persistent grants:
```bash
make install CODESIGN_IDENTITY="Apple Development: Your Name (TEAMID)"
```
Or install individually:
```bash
make install-reminders
make install-calendar
make install-contacts
make install-notes
make install-mail
```
<details>
<summary>Manual compile (without make)</summary>
```bash
# reminders-bridge
cat > /tmp/reminders-info.plist << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSRemindersUsageDescription</key>
<string>Claude Code needs access to Reminders to manage tasks.</string>
</dict>
</plist>
EOF
swiftc reminders-bridge.swift -o ~/.claude/reminders-bridge \
-framework EventKit \
-Xlinker -sectcreate -Xlinker __TEXT -Xlinker __info_plist -Xlinker /tmp/reminders-info.plist
codesign --force --sign - --identifier com.claude.reminders-bridge ~/.claude/reminders-bridge
# contacts-bridge
cat > /tmp/contacts-info.plist << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSContactsUsageDescription</key>
<string>Claude Code needs access to Contacts to look up and manage contacts.</string>
</dict>
</plist>
EOF
swiftc contacts-bridge.swift -o ~/.claude/contacts-bridge \
-framework Contacts \
-Xlinker -sectcreate -Xlinker __TEXT -Xlinker __info_plist -Xlinker /tmp/contacts-info.plist
codesign --force --sign - --identifier com.claude.contacts-bridge ~/.claude/contacts-bridge
# calendar-bridge
cat > /tmp/calendar-info.plist << 'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSCalendarsFullAccessUsageDescription</key>
<string>Claude Code needs access to Calendar to schedule and view events.</string>
</dict>
</plist>
EOF
swiftc calendar-bridge.swift -o ~/.claude/calendar-bridge \
-framework EventKit \
-Xlinker -sectcreate -Xlinker __TEXT -Xlinker __info_plist -Xlinker /tmp/calendar-info.plist
codesign --force --sign - --identifier com.claude.calendar-bridge ~/.claude/calendar-bridge
# notes-bridge
swiftc notes-bridge.swift -o ~/.claude/notes-bridge
codesign --force --sign - --identifier com.claude.notes-bridge ~/.claude/notes-bridge
# mail-bridge
swiftc mail-bridge.swift -o ~/.claude/mail-bridge
codesign --force --sign - --identifier com.claude.mail-bridge ~/.claude/mail-bridge
```
</details>
### 2. Grant permissions
Run each binary once from Terminal to trigger the macOS permission dialog:
```bash
~/.claude/reminders-bridge lists
~/.claude/calendar-bridge today
~/.claude/contacts-bridge search "test"
~/.claude/notes-bridge accounts
~/.claude/mail-bridge accounts
```
Then approve in **System Settings → Privacy & Security → Reminders / Calendars / Contacts / Automation**. Notes and Mail access is granted automatically via AppleScript on first use.
### 3. Add to Claude Code allowed tools
Add the bridges to your **global** `~/.claude/settings.json` so they work across all projects without confirmation prompts:
```json
{
"permissions": {
"allow": [
"Bash(~/.claude/reminders-bridge*)",
"Bash(~/.claude/calendar-bridge*)",
"Bash(~/.claude/contacts-bridge*)",
"Bash(~/.claude/notes-bridge*)",
"Bash(~/.claude/mail-bridge*)",
"Bash(~/.claude/tmux-bridge*)"
]
}
}
```
---
## Requirements
- macOS 13+
- Swift (comes with Xcode or `xcode-select --install`)
- Claude Code
---
## Testing
After installing, run the integration test suite to verify everything works:
```bash
make test
```
35 tests cover all commands across all three bridges — exit codes, output validation, and argument handling. No data is modified during tests.
---
## Skills
Skills are structured prompt templates that Claude Code can load automatically when a bridge topic comes up. Instead of relying solely on CLAUDE.md for bridge documentation, the skill provides complete command syntax, parameters, and usage examples on demand.
### What Skills Do
When you type `/apple-bridges` in Claude Code (or when Claude detects you're asking about Reminders, Calendar, Contacts, Notes, Mail, or tmux), the skill loads:
1. **SKILL.md** — Overview of all bridges with a quick reference table
2. **Detail files** — Full documentation per bridge, loaded only when needed
This keeps context usage minimal while giving Claude complete knowledge of every command.
### Install Skills
Skills are included with `make install`:
```bash
make install # Installs bridges AND skills
make install-skills # Install skills only
```
This copies the skill files to `~/.claude/skills/apple-bridges/`.
### Manual Install
```bash
cp -r skills/apple-bridges ~/.claude/skills/
```
### Verify
Start a new Claude Code session and type `/apple-bridges` — it should be available as a slash command.
---
## Contributing
Pull requests are welcome! When adding a new bridge:
1. Create `<name>-bridge.swift` in the repo root
2. Add compile instructions to `README.md` and `CLAUDE.md`
3. Add the permission grant step to `README.md`
4. Add usage examples to `README.md`
See `CLAUDE.md` for developer notes and the branching workflow.
---
## License
MIT — see [LICENSE](LICENSE) for details.
Information
Repository
Language
Swift
Created
2026/6/18
Updated
2026/6/18