{
  "markdown": "# Claude Code iMessage MCP & Connector\n\nConnect iMessage to your Claude Code session with an MCP server.\n\nThe Claude iMessage MCP server connects to the Linq iMessage API and provides tools to Claude to reply, react, or edit iMessages. When you text the Linq number, the server forwards the message to your Claude Code session.\n\n## Prerequisites\n\n- [Claude Code](https://claude.ai/code) v2.1.80+\n- [Node.js](https://nodejs.org) >= 22\n\n## Quick Setup\n\nDefault pairing flow for a single-user setup. See [Access Control](#access--delivery) for multi-user and policy options.\n\n### 1. Get a Linq number\n\nYou need a Linq API token and phone number. Two options:\n\n**Option A: Free sandbox (recommended for trying it out)**\n\nInstall the [Linq CLI](https://github.com/linq-team/linq-cli) and sign up for a sandbox number (3hr expiry, authenticates via GitHub):\n\n```bash\n# Install the CLI\ncurl -fsSL https://raw.githubusercontent.com/linq-team/linq-cli/main/install.sh | sh\n\n# Sign up — opens browser for GitHub auth, provisions a sandbox number\nlinq signup\n\n# See your token and phone number\nlinq profile\n```\n\n**Option B: Existing Linq account**\n\nGet your token from the [Linq dashboard](https://zero.linqapp.com/api-tooling/). Your phone number is listed under your account.\n\n### 2. Install the plugin\n\nThese are Claude Code commands — run `claude` to start a session first.\n\n```\n/plugin marketplace add linq-team/claude-code-imessage-channel\n/plugin install imessage@linq\n```\n\n### 3. Give the server your credentials\n\n```\n/imessage:configure <your-linq-token>\n/imessage:configure <your-linq-phone-number>\n```\n\nWrites `LINQ_TOKEN=...` and `LINQ_FROM_PHONE=...` to `~/.claude/channels/imessage/.env`. You can also write that file by hand, or set the variables in your shell environment — shell takes precedence.\n\n### 4. Relaunch with the channel flag\n\nThe server won't connect without this — exit your session and start a new one:\n\n```bash\nclaude --dangerously-load-development-channels plugin:imessage@linq\n```\n\n> **Note:** Don't launch from the plugin repo directory — the local `.mcp.json` will conflict. Launch from any other directory (e.g. `~/Desktop`, your project folder, etc.).\n\n### 5. Pair\n\nWith Claude Code running from the previous step, text your Linq number from iMessage — you'll get a 6-character pairing code back. In your Claude Code session:\n\n```\n/imessage:access pair <code>\n```\n\nYour next text reaches the assistant.\n\n### 6. Lock it down\n\nPairing is for capturing phone numbers. Once you're in, switch to allowlist so strangers don't get pairing-code replies:\n\n```\n/imessage:access policy allowlist\n```\n\n### Optional: Set a startup greeting\n\nSo Claude texts you automatically when it starts:\n\n```\n/imessage:access recipient +1XXXXXXXXXX\n```\n\nRestart Claude Code with the channel flag. Claude texts you on startup.\n\n## Access & Delivery\n\nA Linq number is publicly addressable via iMessage. Anyone who knows the number can text it, and without a gate those messages flow straight into your assistant session. The access model decides who gets through.\n\nBy default, a text from an unknown sender triggers **pairing**: the server replies with a 6-character code and drops the message. You run `/imessage:access pair <code>` from your assistant session to approve them. Once approved, their messages pass through.\n\nAll state lives in `~/.claude/channels/imessage/access.json`. The `/imessage:access` skill commands edit this file; the server re-reads it on every inbound message, so changes take effect without a restart.\n\n### At a glance\n\n| | |\n|-|-|\n| Default policy | `pairing` |\n| Sender ID | Phone number in E.164 format (e.g. `+1XXXXXXXXXX`) |\n| Config file | `~/.claude/channels/imessage/access.json` |\n\n### DM policies\n\n`dmPolicy` controls how messages from senders not on the allowlist are handled.\n\n| Policy | Behavior |\n|--------|----------|\n| `pairing` (default) | Reply with a pairing code, drop the message. Approve with `/imessage:access pair <code>`. |\n| `allowlist` | Drop silently. No reply. Useful if your number is shared and pairing replies would attract spam. |\n| `open` | Anyone can message. No filtering. |\n| `disabled` | Drop everything, including allowlisted senders. |\n\n```\n/imessage:access policy allowlist\n```\n\n### Phone numbers\n\niMessage uses phone numbers as identifiers. The allowlist stores E.164 format numbers (e.g. `+1XXXXXXXXXX`). Pairing captures the number automatically.\n\n```\n/imessage:access allow +1XXXXXXXXXX\n/imessage:access remove +1XXXXXXXXXX\n```\n\n### Delivery\n\nConfigure inbound behavior with `/imessage:access set <key> <value>`.\n\n**ackReaction** — tapback sent on message receipt. iMessage supports: `like`, `love`, `laugh`, `dislike`, `emphasize`, `question`. Empty string disables.\n\n```\n/imessage:access set ackReaction love\n/imessage:access set ackReaction \"\"\n```\n\n**pollInterval** — how often the server checks for new messages, in milliseconds. Default `3000`.\n\n```\n/imessage:access set pollInterval 5000\n```\n\n### Skill reference\n\n| Command | Effect |\n|---------|--------|\n| `/imessage:access` | Print current state: policy, allowlist, pending pairings. |\n| `/imessage:access pair a4f91c` | Approve pairing code. Adds sender to `allowFrom`. |\n| `/imessage:access deny a4f91c` | Discard pending code. Sender not notified. |\n| `/imessage:access allow +1XXXXXXXXXX` | Add a phone number directly. |\n| `/imessage:access remove +1XXXXXXXXXX` | Remove from allowlist. |\n| `/imessage:access policy allowlist` | Set dmPolicy. Values: `pairing`, `allowlist`, `open`, `disabled`. |\n| `/imessage:access recipient +1XXXXXXXXXX` | Set default recipient for startup greeting. |\n| `/imessage:access set ackReaction love` | Set a config key: `ackReaction`, `pollInterval`. |\n| `/imessage:access clear` | Delete access.json, reset to defaults. |\n\n### Config file\n\n`~/.claude/channels/imessage/access.json`. Absent file is equivalent to `pairing` policy with empty lists, so the first text triggers pairing.\n\n```json\n{\n  \"dmPolicy\": \"pairing\",\n  \"allowFrom\": [\"+1XXXXXXXXXX\"],\n  \"defaultRecipient\": \"+1XXXXXXXXXX\",\n  \"pendingPairings\": {\n    \"a4f91c\": { \"phone\": \"+1XXXXXXXXXX\", \"createdAt\": \"2026-03-20T...\" }\n  },\n  \"ackReaction\": \"love\",\n  \"pollInterval\": 3000\n}\n```\n\n## Configuration\n\nCredentials are stored in `~/.claude/channels/imessage/.env`:\n\n```\nLINQ_TOKEN=your-api-token\nLINQ_FROM_PHONE=+1XXXXXXXXXX\n```\n\nManage with `/imessage:configure`:\n\n| Command | Effect |\n|---------|--------|\n| `/imessage:configure` | Show current status (token set? phone set?). |\n| `/imessage:configure <token>` | Save token to `.env`. |\n| `/imessage:configure +1XXXXXXXXXX` | Save phone number to `.env`. |\n| `/imessage:configure clear` | Remove all credentials. |\n\nEnvironment variables (`LINQ_TOKEN`, `LINQ_FROM_PHONE`, etc.) override the `.env` file.\n\n## Tools exposed to the assistant\n\n| Tool | Purpose |\n|------|---------|\n| `reply` | Reply to an inbound iMessage. Takes `chat_id` + `text`. Optional: `effect`, `reply_to`, `files`, `text_decorations`. Returns the sent message ID. |\n| `send` | Send to any phone number. Takes `to` + `text`. Optional: `effect`, `files`, `text_decorations`. Returns `chat_id` + `message_id`. |\n| `react` | Tapback reaction to a message by ID. Values: `like`, `love`, `laugh`, `dislike`, `emphasize`, `question`. |\n| `edit_message` | Edit a previously sent message. Useful for \"working…\" → result progress updates. |\n| `send_link` | Send a URL with a rich link preview card. Takes `chat_id` + `url`. Link must be the only content. |\n| `check_capability` | Check if a phone number supports iMessage or RCS. Takes `phone`, optional `service` (`imessage` or `rcs`). |\n\nInbound messages trigger a typing indicator automatically — iMessage shows typing while the assistant works on a response.\n\n## No history or search\n\nThe Linq API polls for recent messages but does not expose full chat history or search. The server only sees messages as they arrive — if the assistant needs earlier context, it will ask you to paste or summarize.\n\n## How It Works\n\n```\nYour phone → iMessage → Linq API → poller → Claude Code session\nClaude reply → Linq API → iMessage → your phone\n```\n\nThe channel server polls the Linq API every 3 seconds for new messages (configurable via `pollInterval`). No webhook URL, no ngrok, no port forwarding needed. A webhook listener on port 9998 is available as fallback if you prefer real-time delivery.\n\nWhen Claude starts, it automatically sets a contact card (\"Claude Code\" with logo) so recipients see a friendly name in iMessage.\n\n## Photos\n\nInbound photos are downloaded to `~/.claude/channels/imessage/inbox/` and the local path is included in the channel notification so the assistant can `Read` it. iMessage compresses photos — if you need the original file, send it as a document instead.\n\n## Effects\n\nAdd iMessage effects to any outgoing message with the optional `effect` parameter:\n\n- **Screen effects:** `confetti`, `fireworks`, `lasers`, `sparkles`, `celebration`, `hearts`, `love`, `balloons`, `happy_birthday`, `echo`, `spotlight`\n- **Bubble effects:** `slam`, `loud`, `gentle`, `invisible`\n\nOnly one effect per message. Effects are visible on iOS/macOS only.\n\n## Text Decorations\n\nStyle text with the `text_decorations` parameter on reply or send. Each decoration specifies a character range and a style or animation.\n\n- **Styles:** `bold`, `italic`, `strikethrough`, `underline`\n- **Animations:** `big`, `small`, `shake`, `nod`, `explode`, `ripple`, `bloom`, `jitter`\n\nExample: send \"hello world\" with \"hello\" bold → `text_decorations: [{\"range\": [0, 5], \"style\": \"bold\"}]`\n\nStyle ranges can overlap, but animations cannot overlap with other animations or styles. Text decorations only render for iMessage recipients.\n\n## Features\n\n- **Two-way iMessage** — text in, get replies back as iMessages\n- **File attachments** — send images, videos, audio, documents via local file paths\n- **Inbound photos** — downloaded to `~/.claude/channels/imessage/inbox/`, Claude can view them\n- **iMessage effects** — confetti, fireworks, lasers, slam, gentle, and 10 more screen/bubble effects\n- **Threaded replies** — reply to a specific message with `reply_to`\n- **SMS/RCS fallback** — messages try iMessage first, fall back automatically\n- **Access control** — pairing flow, allowlist, open, or disabled policy\n- **Read receipts** — auto-sent when your message is received\n- **Typing indicators** — shows typing while Claude processes\n- **Tapback reactions** — Claude can react with like, love, laugh, etc.\n- **Ack reactions** — configurable tapback sent on message receipt\n- **Streaming edits** — send \"working...\" then update in-place (iOS 16+)\n- **Text decorations** — bold, italic, strikethrough, underline + animations (shake, explode, ripple, etc.)\n- **Rich link previews** — send URLs with preview cards via `send_link`\n- **Capability check** — verify iMessage/RCS support before sending\n- **Contact card** — auto-sets name to \"Claude Code\" with logo\n- **No ngrok needed** — polling-based, works behind any firewall\n\n## Plugin Structure\n\n```\nclaude-code-imessage-channel/\n├── .claude-plugin/\n│   ├── plugin.json          # Plugin manifest\n│   └── marketplace.json     # Marketplace catalog\n├── .mcp.json                # MCP server config\n├── skills/\n│   ├── access/\n│   │   └── SKILL.md         # Access control skill\n│   ├── configure/\n│   │   └── SKILL.md         # Configuration skill\n│   └── imessage/\n│       └── SKILL.md         # Usage hints skill\n├── src/\n│   └── channel.ts           # Channel server\n├── CLAUDE.md\n├── package.json\n└── tsconfig.json\n```\n\n## Requirements\n\n- Node.js >= 22\n- Claude Code v2.1.80+ with channels support\n- A [Linq](https://linqapp.com) account with an API token and phone number\n\n## Contributing\n\nWe use a PR workflow with `dev` as the working branch.\n\n```bash\n# Clone and set up\ngit clone https://github.com/linq-team/claude-code-imessage-channel.git\ncd claude-code-imessage-channel\ngit checkout dev\nnpm install\n\n# Create a feature branch\ngit checkout -b feat/my-feature\n\n# Make changes, build, test\nnpm run build\n\n# Push and open PR against dev\ngit push origin feat/my-feature\n# Then open PR on GitHub: base=dev\n```\n\n### Branch strategy\n\n| Branch | Purpose |\n|--------|---------|\n| `main` | Production. Protected - requires 1 review. Only merged from `dev`. |\n| `dev` | Working branch. PRs merge here first. |\n| `feat/*` | Feature branches off `dev`. |\n| `fix/*` | Bug fixes off `dev`. |\n\n### Commit messages\n\nUse conventional commits: `feat:`, `fix:`, `docs:`, `chore:`, `refactor:`, `test:`\n\n### Before submitting a PR\n\n1. `npm run build` passes\n2. No secrets or PII in the diff\n3. README updated if you added/changed config or features\n\n## License\n\nMIT\n",
  "bytes": 12691,
  "sha": "e9d19d731e5c709863640d61d405e72d527ef82d5b5e5feae7cd398207b7e436",
  "repo_slug": "linq-team/claude-code-imessage-channel",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/plg_linq_team_claude_code_imessage_channel_i_66b63675/readme"
}