{"id":46150095,"url":"https://github.com/photon-hq/vercel-chat-adapter-imessage","last_synced_at":"2026-03-08T14:00:33.895Z","repository":{"id":341444435,"uuid":"1170125537","full_name":"photon-hq/vercel-chat-adapter-imessage","owner":"photon-hq","description":"iMessage adapter for Chat SDK. Supports both local (on-device) and Photon iMessage integration.","archived":false,"fork":false,"pushed_at":"2026-03-06T06:46:47.000Z","size":69,"stargazers_count":7,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-06T14:34:08.120Z","etag":null,"topics":["agent","ai","chat","chat-sdk","imessage","vercel"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/photon-hq.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-01T18:30:58.000Z","updated_at":"2026-03-06T10:59:02.000Z","dependencies_parsed_at":"2026-03-05T11:00:44.094Z","dependency_job_id":null,"html_url":"https://github.com/photon-hq/vercel-chat-adapter-imessage","commit_stats":null,"previous_names":["photon-hq/vercel-chat-adapter-imessage"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/photon-hq/vercel-chat-adapter-imessage","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/photon-hq%2Fvercel-chat-adapter-imessage","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/photon-hq%2Fvercel-chat-adapter-imessage/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/photon-hq%2Fvercel-chat-adapter-imessage/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/photon-hq%2Fvercel-chat-adapter-imessage/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/photon-hq","download_url":"https://codeload.github.com/photon-hq/vercel-chat-adapter-imessage/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/photon-hq%2Fvercel-chat-adapter-imessage/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30214578,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-07T12:15:00.571Z","status":"ssl_error","status_checked_at":"2026-03-07T12:15:00.217Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agent","ai","chat","chat-sdk","imessage","vercel"],"created_at":"2026-03-02T08:34:46.184Z","updated_at":"2026-03-07T13:01:05.600Z","avatar_url":"https://github.com/photon-hq.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# chat-adapter-imessage\n\niMessage community adapter for [Chat SDK](https://chat-sdk.dev/docs). Supports both local (on-device) and remote ([Photon](https://photon.codes)-based) iMessage integration.\n\n## Installation\n\n```bash\npnpm add chat chat-adapter-imessage\n```\n\n## Usage\n\nThe adapter supports two modes: **local** (running directly on a Mac with iMessage) and **remote** (connecting to a [Photon](https://photon.codes) iMessage server). The mode is auto-detected from the `IMESSAGE_LOCAL` environment variable.\n\n### Remote mode\n\nRecommended for production. Connects to [Photon](https://photon.codes)'s managed iMessage service over HTTP and Socket.IO, so your bot can run on any platform.\n\n```typescript\nimport { Chat } from \"chat\";\nimport { createiMessageAdapter } from \"chat-adapter-imessage\";\n\nconst bot = new Chat({\n  userName: \"mybot\",\n  adapters: {\n    imessage: createiMessageAdapter({\n      local: false,\n    }),\n  },\n});\n\nbot.onNewMention(async (thread, message) =\u003e {\n  await thread.post(\"Hello from iMessage!\");\n});\n```\n\n### Local mode\n\nFor development or self-hosted deployments using [imessage-kit](https://github.com/photon-hq/imessage-kit). Reads from the local iMessage database and sends via AppleScript. Must run on macOS with **Full Disk Access** granted.\n\n```typescript\nimport { Chat } from \"chat\";\nimport { createiMessageAdapter } from \"chat-adapter-imessage\";\n\nconst bot = new Chat({\n  userName: \"mybot\",\n  adapters: {\n    imessage: createiMessageAdapter({\n      local: true,\n    }),\n  },\n});\n\nbot.onNewMention(async (thread, message) =\u003e {\n  await thread.post(\"Hello from iMessage!\");\n});\n```\n\n## Setup\n\n### Remote mode\n\nRemote mode connects to a [Photon](https://photon.codes) iMessage server, which handles the macOS-side integration on your behalf. You'll need an active Photon subscription to get your server credentials.\n\n1. [Request access](https://photon.codes) from Photon to get your server credentials\n2. Copy your **server URL** and **API key** from the Photon dashboard\n3. Set `IMESSAGE_SERVER_URL` and `IMESSAGE_API_KEY` environment variables\n4. Set `IMESSAGE_LOCAL=false`\n\n### Local mode\n\nLocal mode requires the adapter to run directly on a macOS machine with iMessage. It uses Apple's native APIs — reading from the local `chat.db` database and sending messages via AppleScript — with no external server required.\n\n1. Grant **Full Disk Access** to your terminal or application in **System Settings \u003e Privacy \u0026 Security \u003e Full Disk Access**\n2. Ensure iMessage is signed in and working on the Mac\n3. No additional environment variables are required — local mode is the default\n\n## Receiving messages\n\nCall `startGatewayListener()` to listen for new messages in real-time. In remote mode, this uses Socket.IO push events. In local mode, it polls the iMessage database.\n\nIn serverless environments, use a cron job to maintain the connection.\n\n## Gateway setup for serverless\n\n### 1. Create Gateway route\n\n```typescript\n// app/api/imessage/gateway/route.ts\nimport { after } from \"next/server\";\nimport { bot } from \"@/lib/bot\";\n\nexport const maxDuration = 800;\n\nexport async function GET(request: Request): Promise\u003cResponse\u003e {\n  const cronSecret = process.env.CRON_SECRET;\n  if (!cronSecret) {\n    return new Response(\"CRON_SECRET not configured\", { status: 500 });\n  }\n\n  const authHeader = request.headers.get(\"authorization\");\n  if (authHeader !== `Bearer ${cronSecret}`) {\n    return new Response(\"Unauthorized\", { status: 401 });\n  }\n\n  const durationMs = 600 * 1000;\n\n  return bot.adapters.imessage.startGatewayListener(\n    { waitUntil: (task) =\u003e after(() =\u003e task) },\n    durationMs\n  );\n}\n```\n\n### 2. Configure Vercel Cron\n\n```json\n// vercel.json\n{\n  \"crons\": [\n    {\n      \"path\": \"/api/imessage/gateway\",\n      \"schedule\": \"*/9 * * * *\"\n    }\n  ]\n}\n```\n\nThis runs every 9 minutes, ensuring overlap with the 10-minute listener duration.\n\n### 3. Environment variables\n\n`CRON_SECRET` is automatically added by Vercel when you configure cron jobs.\n\n## Configuration\n\n| Option | Required | Description |\n|--------|----------|-------------|\n| `local` | No | `true` for local mode, `false` for remote. Auto-detected from `IMESSAGE_LOCAL` (default: `true`) |\n| `serverUrl` | Remote only | URL of the remote iMessage server. Auto-detected from `IMESSAGE_SERVER_URL` |\n| `apiKey` | Remote only | API key for remote server authentication. Auto-detected from `IMESSAGE_API_KEY` |\n| `logger` | No | Logger instance (defaults to `ConsoleLogger(\"info\")`) |\n\n## Environment variables\n\n```bash\n# .env.local\nIMESSAGE_LOCAL=false                 # Set to \"false\" for remote mode (default: true)\nIMESSAGE_SERVER_URL=https://...       # Required for remote mode\nIMESSAGE_API_KEY=...                 # Required for remote mode\n```\n\n## Features\n\n| Feature | Supported |\n|---------|-----------|\n| Mentions | DMs only |\n| Reactions (add/remove) | Remote only |\n| Modals | Limited (Remote only) |\n| Cards | No |\n| Streaming | No |\n| DMs | Yes |\n| Ephemeral messages | No |\n| File uploads | Yes |\n| Typing indicator | Remote only |\n| Message history | Yes |\n| Message editing | Remote only |\n\n## Modals (Limited)\n\nRemote mode supports limited modal functionality by mapping the Chat SDK's `openModal()` to iMessage native polls via the Photon SDK. Only `Select` children are supported — the first `Select` in the modal is used to create a poll.\n\n- `Modal.title` becomes the poll question\n- `Select.options` become the poll choices\n- Votes trigger `onModalSubmit` with the selected option's `value`\n\n```typescript\nimport { Chat, Modal, Select, SelectOption } from \"chat\";\nimport { createiMessageAdapter } from \"chat-adapter-imessage\";\n\nconst bot = new Chat({\n  userName: \"mybot\",\n  adapters: {\n    imessage: createiMessageAdapter({ local: false }),\n  },\n});\n\nbot.onNewMention(async (thread, message) =\u003e {\n  await message.openModal(\n    Modal({\n      callbackId: \"fav-color\",\n      title: \"What is your favorite color?\",\n      children: [\n        Select({\n          id: \"color\",\n          label: \"Pick a color\",\n          options: [\n            SelectOption({ label: \"Red\", value: \"red\" }),\n            SelectOption({ label: \"Blue\", value: \"blue\" }),\n            SelectOption({ label: \"Green\", value: \"green\" }),\n          ],\n        }),\n      ],\n    })\n  );\n});\n\nbot.onModalSubmit(\"fav-color\", async (event) =\u003e {\n  const color = event.values.color;\n  // color will be \"red\", \"blue\", or \"green\"\n});\n```\n\n**Not supported:**\n\n- `Select.placeholder` and `Select.label` — iMessage polls don't have these fields\n- `TextInput`, `RadioSelect`, and other modal children — silently ignored\n- `Modal.submitLabel` and `Modal.closeLabel` — not applicable to polls\n- Only the **first** `Select` child is used; other children are ignored\n- Local mode — `openModal()` throws `NotImplementedError`\n\n## Tapback reactions\n\niMessage uses tapbacks instead of emoji reactions. The adapter maps standard emoji names to iMessage tapbacks:\n\n| Emoji | Tapback |\n|-------|---------|\n| `love` / `heart` | Love |\n| `like` / `thumbs_up` | Like |\n| `dislike` / `thumbs_down` | Dislike |\n| `laugh` | Laugh |\n| `emphasize` / `exclamation` | Emphasize |\n| `question` | Question |\n\n## Limitations\n\n- **Local mode**: Only supports sending/receiving messages, message history, and file uploads. Reactions, typing indicators, message editing, modals, and thread fetching require remote mode.\n- **Formatting**: iMessage is plain-text only. Markdown formatting (bold, italic, etc.) is stripped when sending messages, preserving only the text content.\n- **Platform**: Local mode requires macOS. Remote mode can run on any platform — [Photon](https://photon.codes) manages the iMessage infrastructure for you.\n- **Cards**: iMessage has no support for structured card layouts.\n- **Modals**: Limited to `Select`-based modals mapped to iMessage native polls. Only the first `Select` child is used; `placeholder`, `label`, `TextInput`, `RadioSelect`, and other fields are not supported. Remote mode only.\n\n## Troubleshooting\n\n### \"serverUrl is required\" error\n\n- Set `IMESSAGE_SERVER_URL` or pass `serverUrl` in config when using remote mode\n- This error occurs when `IMESSAGE_LOCAL=false` but no server URL is provided\n\n### \"apiKey is required\" error\n\n- Set `IMESSAGE_API_KEY` or pass `apiKey` in config when using remote mode\n\n### Local mode not receiving messages\n\n- Verify **Full Disk Access** is granted to your terminal or application\n- Check that iMessage is signed in and working\n- Messages are polled from the local database — there may be a short delay\n\n### Remote mode connection issues\n\n- Verify the server URL is correct and accessible\n- Check that the API key matches your Photon iMessage service credentials\n- Confirm your Photon subscription is active\n\n## License\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphoton-hq%2Fvercel-chat-adapter-imessage","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphoton-hq%2Fvercel-chat-adapter-imessage","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphoton-hq%2Fvercel-chat-adapter-imessage/lists"}