Skip to content

iviraa/echo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Echo

A macOS menu-bar daemon that lets you drive Claude Code by texting iMessage from your iPhone, Apple Watch, iPad, or CarPlay.

Uses your existing Claude Code subscription via the Claude CLI.

How it works

  1. You iMessage yourself (from iPhone, Watch, Mac, wherever).
  2. Apple's sync replicates the message to your Mac's chat.db.
  3. Echo notices via FSEvents, picks up the new row.
  4. Echo shells out to claude -p <prompt> --resume <session_id> — Claude Code handles everything: conversation state, tools, file edits, permissions, git, all of it.
  5. Echo streams the response back as iMessage(s).
  6. Apple syncs the replies to every device you own.

No servers, no webhooks, no open ports, no API keys. Your Mac + your Claude Code subscription.

Setup

1. Prerequisites

  • macOS 13+ (Ventura or later)
  • Claude Code installed and logged in
  • Swift toolchain (comes with Xcode Command Line Tools)

2. Build

swift build -c release

Binary: .build/release/echo

3. Configure

.build/release/echo run

First run writes a template to ~/.echo/config.json and exits. Fill it in:

{
  "chat_identifier": "+15551234567",
  "chat_db_path": "/Users/you/Library/Messages/chat.db",
  "claude_binary": "claude",
  "project_dir": "/Users/you/Documents/Projects",
  "permission_mode": "bypassPermissions",
  "model": null,
  "daily_budget_usd": 10.00
}
  • chat_identifier — handle Echo listens on and replies to. Typically your own phone number or email. Find with:
    sqlite3 ~/Library/Messages/chat.db "SELECT chat_identifier, display_name FROM chat ORDER BY ROWID DESC LIMIT 10"
  • project_dir — working directory claude runs in. Pick the project you want Echo to operate on. Claude can always cd elsewhere via bash.
  • permission_mode — one of default, acceptEdits, plan, bypassPermissions. For unattended iMessage use, bypassPermissions is what you want (otherwise Claude will hang waiting for a prompt that never comes).
  • modelnull uses Claude Code's default. Set a specific id if you want.
  • daily_budget_usd — soft cap. Warns at 80%, pauses at 100%.

4. Grant permissions

  • Full Disk Access — System Settings → Privacy & Security → Full Disk Access → add the echo binary. Required to read chat.db.
  • Automation → Messages — granted on first send; you'll see a prompt.

5. Run

.build/release/echo run

Menu bar shows ◎. Text the configured number from any Apple device. Expect a reply in 3–10 seconds depending on the task.

6. (Optional) Install as login agent

.build/release/echo install

Writes a launchd plist and bootstraps it. Echo starts automatically at login.

.build/release/echo uninstall   # to remove

Slash commands

/help              list commands
/new <text>        force a new session
/end               close the current session
/budget            show today's spend
/remember <text>   append to ~/.echo/memory.md
/forget            wipe memory (backed up)

User-defined macros: drop ~/.echo/macros.json like

{ "standup": "What did I work on yesterday? Summarize git activity from the last 24h." }

Then text /standup to expand to that prompt.

Sessions

Every top-level (non-reply) iMessage starts a new Claude Code session. Reply-to any message in a thread from your phone → Echo resumes that session via claude --resume. Claude Code owns the conversation state; Echo just stores the opaque session id.

Memory

~/.echo/memory.md is passed to Claude on every call via --append-system-prompt. Edit freely, or use /remember and /forget over iMessage. Useful for "I prefer terse replies" or "when I say 'the app', I mean the Swift project at …".

Logs

tail -f ~/.echo/logs/echo.log

About

iMessage bridge to Claude Code

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors