Per-feature pages (install, quickstart, permissions, chats, history, watch, send, groups, attachments, json, rpc, completions, advanced-imcore, troubleshooting) plus an Apple-styled static-site builder rendering them to dist/docs-site. GitHub Pages workflow deploys on every docs/ change to imsg.sh.
169 lines
4.6 KiB
Markdown
169 lines
4.6 KiB
Markdown
---
|
|
title: JSON-RPC
|
|
description: "Long-running JSON-RPC 2.0 over stdio for chats, history, watch, and send — same surfaces as the CLI, one process."
|
|
---
|
|
|
|
`imsg rpc` exposes the read and send surfaces over JSON-RPC 2.0 on stdin/stdout. It's designed for agents and gateways that want a single long-lived process for chats, history, send, and watch — without a TCP port, daemon, or system service.
|
|
|
|
## Transport
|
|
|
|
- One JSON object per line on stdin (request) and stdout (response/notification).
|
|
- JSON-RPC 2.0 framing: `jsonrpc`, `id`, `method`, `params`.
|
|
- Notifications omit `id`.
|
|
- Stderr is reserved for human-readable diagnostics.
|
|
|
|
## Lifecycle
|
|
|
|
- The host process spawns one `imsg rpc` child.
|
|
- The child stays alive across many requests and one-or-more watch subscriptions.
|
|
- No TCP port. No launch agent. No `imsg` daemon to install.
|
|
|
|
The pattern intentionally mirrors language servers and the way `imsg`'s parent gateway (Clawdis) supervises subprocesses — a single signal-style child that exits cleanly when stdin closes.
|
|
|
|
## Methods
|
|
|
|
### `chats.list`
|
|
|
|
Params:
|
|
|
|
- `limit` (int, default 20)
|
|
|
|
Result:
|
|
|
|
```json
|
|
{ "chats": [Chat] }
|
|
```
|
|
|
|
### `messages.history`
|
|
|
|
Params:
|
|
|
|
- `chat_id` (int, required) — preferred identifier.
|
|
- `limit` (int, default 50)
|
|
- `participants` (array of handle strings, optional)
|
|
- `start` / `end` (ISO 8601, optional)
|
|
- `attachments` (bool, default `false`)
|
|
|
|
Result:
|
|
|
|
```json
|
|
{ "messages": [Message] }
|
|
```
|
|
|
|
### `watch.subscribe`
|
|
|
|
Params:
|
|
|
|
- `chat_id` (int, optional) — omit for all-chat stream.
|
|
- `since_rowid` (int, optional) — exclusive cursor.
|
|
- `participants` (array, optional)
|
|
- `start` / `end` (ISO 8601, optional)
|
|
- `attachments` (bool, default `false`)
|
|
- `include_reactions` (bool, default `false`)
|
|
- `debounce_ms` (int, default `500`)
|
|
|
|
Result:
|
|
|
|
```json
|
|
{ "subscription": 1 }
|
|
```
|
|
|
|
Notifications (one per emitted message):
|
|
|
|
```json
|
|
{
|
|
"jsonrpc": "2.0",
|
|
"method": "message",
|
|
"params": {
|
|
"subscription": 1,
|
|
"message": { ... }
|
|
}
|
|
}
|
|
```
|
|
|
|
The RPC default debounce (`500ms`) is intentionally higher than the CLI default (`250ms`). RPC's typical caller is an agent that just sent a message and is waiting for the inbound echo to settle (`is_from_me` correction, attachment metadata, …). 500ms is enough for those follow-ups to land before the message is emitted.
|
|
|
|
Like the CLI watch, RPC watch backs filesystem events with a low-frequency poll so a missed event or a rotated SQLite sidecar doesn't leave the subscription silent.
|
|
|
|
### `watch.unsubscribe`
|
|
|
|
Params:
|
|
|
|
- `subscription` (int, required)
|
|
|
|
Result:
|
|
|
|
```json
|
|
{ "ok": true }
|
|
```
|
|
|
|
### `send`
|
|
|
|
Params (direct send):
|
|
|
|
- `to` (string, required)
|
|
- `text` (string, optional)
|
|
- `file` (string, optional)
|
|
- `service` (`imessage` | `sms` | `auto`, optional)
|
|
- `region` (string, optional)
|
|
|
|
Params (chat target):
|
|
|
|
- `chat_id` *or* `chat_identifier` *or* `chat_guid` — exactly one. `chat_id` is preferred.
|
|
- `text` / `file` as above.
|
|
|
|
Result:
|
|
|
|
```json
|
|
{ "ok": true, "id": 1979, "guid": "8DF..." }
|
|
```
|
|
|
|
`id` and `guid` are best-effort. `send` returns them when the inserted row can be observed in `chat.db` after Messages accepts the send. Attachment-only sends, delayed database writes, or ambiguous direct sends may return only `{"ok": true}`.
|
|
|
|
For chat-target sends, `send` also performs the [Tahoe ghost-row check](send.md#tahoe-ghost-row-protection): if Messages writes an empty unjoined SMS row instead of delivering, the call returns an error rather than `{"ok": true}`.
|
|
|
|
## Objects
|
|
|
|
### Chat
|
|
|
|
See [JSON output → Chat](json.md#chat). Every field documented there appears in the RPC `chats.list` response.
|
|
|
|
### Message
|
|
|
|
See [JSON output → Message](json.md#message). When `include_reactions: true`, message notifications also include the reaction extension fields (`is_reaction`, `reaction_type`, `reaction_emoji`, `is_reaction_add`, `reacted_to_guid`).
|
|
|
|
`account_id`, `account_login`, `last_addressed_handle`, and outgoing `destination_caller_id` are read-only routing diagnostics; the AppleScript send API does not expose a `from` selector.
|
|
|
|
## Examples
|
|
|
|
Request `chats.list`:
|
|
|
|
```json
|
|
{"jsonrpc":"2.0","id":"1","method":"chats.list","params":{"limit":10}}
|
|
```
|
|
|
|
Response:
|
|
|
|
```json
|
|
{"jsonrpc":"2.0","id":"1","result":{"chats":[...]}}
|
|
```
|
|
|
|
Subscribe to a chat:
|
|
|
|
```json
|
|
{"jsonrpc":"2.0","id":"2","method":"watch.subscribe","params":{"chat_id":1}}
|
|
```
|
|
|
|
Notification on each new message:
|
|
|
|
```json
|
|
{"jsonrpc":"2.0","method":"message","params":{"subscription":2,"message":{...}}}
|
|
```
|
|
|
|
Send and receive verification:
|
|
|
|
```json
|
|
{"jsonrpc":"2.0","id":"3","method":"send","params":{"to":"+14155551212","text":"hi"}}
|
|
{"jsonrpc":"2.0","id":"3","result":{"ok":true,"id":1979,"guid":"8DF..."}}
|
|
```
|