Sandbox
@more-io/claude-apple-bridges

Claude Code bridges for Apple apps and tmux

This repo provides command-line bridges that Claude Code can call to read and write Apple Reminders, Calendar, Contacts, Notes, Mail, Messages, and tmux sessions. Each bridge exposes plain commands for listing, searching, creating, updating, and deleting items, so Claude can handle planning, inbox work, scheduling, and terminal follow-up from one session.

45 stars4 forksSwiftUpdated 12d ago
Who it's for

Builders who want Claude Code to manage Apple apps, message threads, and terminal sessions as part of their workflow.

What it delivers

You can ask Claude to look up information, draft updates, schedule work, and make changes in Apple apps without leaving the session.

What it does

Reminders bridge

Lists, searches, creates, updates, completes, and deletes reminders, including due dates and notes.

Calendar bridge

Reads calendars and events, finds free slots, and adds or deletes events and all-day events.

Contacts bridge

Searches contacts, shows full contact details, and adds, updates, or deletes contact entries.

Notes bridge

Lists, reads, searches, creates, appends to, and deletes Apple Notes, with HTML formatting support.

Mail bridge

Lists, searches, reads, and sends Apple Mail messages, including raw message output and attachments.

Messages bridge

Reads and sends iMessage and SMS conversations, including attachments and unread threads.

Tmux bridge

Lists tmux sessions, windows, and panes, reads pane output, writes keystrokes, and captures snapshots.

Claude Code skill

Installs a `/apple-bridges` skill with a quick reference and per-bridge command docs.

How to get it

  1. 1Run
    # Install all bridges at once (recommended)
    git clone https://github.com/more-io/claude-apple-bridges.git
    cd claude-apple-bridges
    make install
  2. 2By default, bridges are ad-hoc signed. macOS TCC may re-prompt for permissions in new…
    make install CODESIGN_IDENTITY="Apple Development: Your Name (TEAMID)"
  3. 3Or install individually
    make install-reminders
    make install-calendar
    make install-contacts
    make install-notes
    make install-mail
    make install-messages
  4. 4Run each binary once from Terminal to trigger the macOS permission dialog
    ~/.claude/reminders-bridge lists
    ~/.claude/calendar-bridge today
    ~/.claude/contacts-bridge search "test"
    ~/.claude/notes-bridge accounts
    ~/.claude/mail-bridge accounts
    ~/.claude/messages-bridge chats
  5. 5Skills are included with make install
    make install          # Installs bridges AND skills
    make install-skills   # Install skills only
  6. 6Run
    cp -r skills/apple-bridges ~/.claude/skills/

README

Claude Apple Bridges

License: MIT Platform: macOS 13+ Swift

Swift CLI tools that give Claude Code native access to Apple apps — Reminders, Calendar, Contacts, Notes, Mail, and tmux. Includes a Claude Code skill (/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, alex@example.com"

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> [label]           Add a phone (append, keeps existing)
contacts-bridge update <name> email <value> [label]           Add an email (append, keeps existing)
contacts-bridge remove <name> phone|email <value>             Remove a matching phone/email
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.

# 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.

# 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.

mail-bridge search "invoice" 50 work@company.com --since 90d
# Found 7 message(s) (last 90d):
#   <mid:abc123@example.com> Invoice #4711 — billing@vendor.com (3/15)
#   ...

mail-bridge read --mid "abc123@example.com" work@company.com --raw > /tmp/mail.eml

--raw example — extract PDF attachments from invoice emails:

# Dump the raw message source (RFC822, includes HTML body + MIME attachments)
mail-bridge read 42 INBOX work@company.com --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:

# Ask Claude to draft a reply → compose window opens in Mail.app for review:
mail-bridge send heiko@web.de "Betreff" "Hallo Heiko, ..."

# Claude sends automatically without user interaction (explicit intent required):
mail-bridge send heiko@web.de "Betreff" "Hallo Heiko, ..." --force

# With attachment and explicit sender:
mail-bridge send heiko@web.de "Report" "See attached." /tmp/report.pdf --from work@company.com --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:

# 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."

messages-bridge

Read and send Apple Messages (iMessage / SMS) from Claude Code.

messages-bridge chats [count]               List recent conversations (default: 20)
messages-bridge unread [count]              List unread incoming messages (default: 20)
messages-bridge list <chat|handle> [count]  List messages of a conversation (default: 20)
messages-bridge search <query> [count]      Search message bodies (default: 20)
messages-bridge read <chat|handle> [count]  Full untruncated messages (default: 10)
messages-bridge send <handle> <text> [/path/to/attachment ...]
                                            Send a message, optionally with files

A conversation can be addressed by phone number, email address, group name, or contact name:

messages-bridge list "Anna Muller" 10
messages-bridge send "+491701234567" "On my way"

# with files — each is delivered as its own message after the text
messages-bridge send "+491701234567" "Here are the documents" ~/Documents/offer.pdf ~/Documents/terms.pdf

# files only, no text
messages-bridge send "ben@example.com" "" ~/Pictures/floorplan.png

How it reads: straight from ~/Library/Messages/chat.db, opened read-only. Apple stores the body of many newer messages only as an archived NSAttributedString in attributedBody and leaves text empty — about a quarter of the rows here. The bridge decodes that typedstream, so those messages do not come back blank. Sender names are resolved through Contacts; unknown handles are shown as-is.

Permissions: reading needs Full Disk Access for the terminal; sending needs Automation -> Messages. The Automation prompt appears on first send, but Full Disk Access must be granted manually in System Settings before the first read.

Note: send delivers immediately and asks nothing. Any "confirm before sending" rule belongs in your Claude Code instructions, not in the tool.

If send fails with AppleEvent timed out (-1712): Messages.app's scripting interface is wedged, not missing. The giveaway is that even a trivial script such as tell application "Messages" to get name of every account hangs. Quit Messages.app and reopen it — sending works again immediately.


Setup

1. Compile

# 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:

make install CODESIGN_IDENTITY="Apple Development: Your Name (TEAMID)"

Or install individually:

make install-reminders
make install-calendar
make install-contacts
make install-notes
make install-mail
make install-messages
Manual compile (without make)
# 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>NSRemindersFullAccessUsageDescription</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

2. Grant permissions

Run each binary once from Terminal to trigger the macOS permission dialog:

~/.claude/reminders-bridge lists
~/.claude/calendar-bridge today
~/.claude/contacts-bridge search "test"
~/.claude/notes-bridge accounts
~/.claude/mail-bridge accounts
~/.claude/messages-bridge chats

Then approve in System Settings → Privacy & Security → Reminders / Calendars / Contacts / Automation. Notes and Mail access is granted automatically via AppleScript on first use.

messages-bridge additionally needs Full Disk Access for your terminal (to read chat.db) — that one is not prompted for, grant it in System Settings → Privacy & Security → Full Disk Access and restart the terminal.

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:

{
  "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*)",
      "Bash(~/.claude/messages-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:

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:

make install          # Installs bridges AND skills
make install-skills   # Install skills only

This copies the skill files to ~/.claude/skills/apple-bridges/.

Manual Install

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 for details.

Files in the repo

Repository payload14 top-level entries
  • skills
  • .gitignore
  • calendar-bridge.swift
  • CLAUDE.md
  • contacts-bridge.swift
  • LICENSE
  • mail-bridge.swift
  • Makefile
  • messages-bridge.swift
  • notes-bridge.swift
  • README.md
  • reminders-bridge.swift
  • test.sh
  • tmux-bridge.swift

Discussion (0)

Ask about usage, or say what you built with it

Sign in to join the discussion.

No comments yet. Be the first to say what this is good for.

More connectors

Real-time global intelligence dashboard. AI-powered news aggregation, geopolitical monitoring, and infrastructure tracking in a unified situational awareness interface

86k

High-performance code intelligence MCP server. Indexes codebases into a persistent knowledge graph — average repo in milliseconds. 158 languages, sub-ms queries, 99% fewer tokens. Single static binary, zero dependencies.

43k

Universal provider proxy for OpenAI Codex & Claude Code — use any LLM (Claude, Gemini, Grok, DeepSeek, Ollama…) with Codex CLI, App, SDK, and Claude Code

14k
okf-memory/
okf-agent-memory

Git-native persistent memory for AI coding agents. Implements Google OKF v0.2 with sub-300µs in-memory BM25 search, embedded MCP server, and progressive disclosure. Slashes token bloat by 80% with zero external databases or dependencies. Built in pure Go.

547
tirth8205/
code-review-graph

Local-first code intelligence graph for MCP and CLI. Builds a persistent map of your codebase so AI coding tools read only what matters, with benchmarked context reductions on reviews and large-repo workflows.

31k
2akouwu/
reverify

Stop your AI from making things up — it proposes, deterministic tools decide, every claim checked against ground truth with evidence. Grounded facts and context survive resets. Reverse engineering is the proving ground. MCP server + CLI.

1.1k