feat(broker+api+cli): topic message reply-to threading (v0.3.1)
Adds a reply_to_id column (self-FK on topic_message) plus end-to-end plumbing so a message can mark itself as a reply to a previous one in the same topic. - Schema: 0027_topic_message_reply_to.sql adds reply_to_id with ON DELETE SET NULL + index for backlink lookup. - Broker: appendTopicMessage validates parent shares the topic, writes reply_to_id; topicHistory + topic_history_response surface it; WS push envelope now carries senderMemberId, senderName, topic name, reply_to_id, and message_id so recipients have everything they need to reply without a follow-up query. - REST: POST /v1/messages accepts replyToId (validated server-side); GET /messages and SSE /stream emit it per row. - CLI: \`topic post --reply-to <id|prefix>\` resolves prefixes against recent history; \`topic tail\` renders an "↳ in reply to <name>: <snippet>" line above replies and shows a copyable #shortid tag on every row. - MCP push pipe: channel attributes now include from_pubkey, from_member_id, message_id, topic, reply_to_id — the recipient can thread a reply directly from the inbound notification. - Skill + identity prompt updated to teach Claude how to use the new attributes for replies. Bumped CLI to 1.9.0.
This commit is contained in:
@@ -13,6 +13,34 @@ description: Use when the user asks to send a message to a peer Claude session,
|
||||
|
||||
Respond IMMEDIATELY. Pause your current task, reply via `claudemesh send`, then resume. Read `from_name`, `mesh_slug`, and `priority` from the channel attributes. Reply by setting `<to>` to the sender's `from_name`. Do not ignore low-priority messages — acknowledge them briefly even if you defer action. If the channel meta contains `subtype: reminder`, this is a scheduled reminder you set yourself — act on it.
|
||||
|
||||
### Channel attributes (everything you need to reply is in the push)
|
||||
|
||||
The `<channel>` interrupt carries these attributes — no lookup needed:
|
||||
|
||||
| Attribute | What it is |
|
||||
|---|---|
|
||||
| `from_name` | Sender's display name. **Use as `to` in your reply** for DMs. |
|
||||
| `from_pubkey` | Sender's session pubkey (hex). Stable per-session. |
|
||||
| `from_member_id` | Sender's stable mesh.member id. Survives display-name changes — the canonical id. |
|
||||
| `mesh_slug` | Mesh the message arrived on. Pass via `--mesh <slug>` if the parent isn't on the same mesh. |
|
||||
| `priority` | `now` / `next` / `low`. |
|
||||
| `message_id` | Server-side id of THIS message. **Pass to `--reply-to <id>` to thread your reply** in topic posts. |
|
||||
| `topic` | Set when the source is a topic post. Reply via `topic post <topic> --reply-to <message_id>`. |
|
||||
| `reply_to_id` | Set when the message itself is a reply to a previous one — render thread context. |
|
||||
|
||||
**Reply patterns:**
|
||||
|
||||
```bash
|
||||
# DM → use from_name as the target
|
||||
claudemesh send "<from_name>" "ack — looking now"
|
||||
|
||||
# Topic reply → thread it onto the message you got
|
||||
claudemesh topic post "<topic>" "yep, looks good" --reply-to <message_id>
|
||||
|
||||
# When the sender is on a different mesh you've joined
|
||||
claudemesh send "<from_name>" "..." --mesh "<mesh_slug>"
|
||||
```
|
||||
|
||||
## Performance model (warm vs cold path)
|
||||
|
||||
If the parent Claude session was launched via `claudemesh launch`, an MCP push-pipe is running and holds the per-mesh WS connection. CLI invocations dial `~/.claudemesh/sockets/<mesh-slug>.sock` and reuse that warm connection (~200ms total round-trip including Node.js startup). If no push-pipe is running (cron, scripts, hooks fired outside a session), the CLI opens its own WS, which takes ~500-700ms cold. **You don't manage this** — every verb auto-detects and falls through.
|
||||
@@ -62,8 +90,14 @@ claudemesh topic tail deploys --limit 50
|
||||
# v1.8.0+: encrypted REST send (body_version 2). Falls back to v1
|
||||
# automatically for legacy unencrypted topics. --plaintext forces v1.
|
||||
claudemesh topic post deploys "rolling out, cc @Alexis stay around"
|
||||
|
||||
# v1.9.0+: thread a reply onto a previous topic message. Accepts the
|
||||
# full id or an 8+ char prefix; resolved against recent history.
|
||||
claudemesh topic post deploys "yes — same here" --reply-to 7XtIeF7o
|
||||
```
|
||||
|
||||
In `topic tail` output, replies render with a `↳ in reply to <name>: "<snippet>"` line above the message and every row shows a short id tag (`#xxxxxxxx`) so you can copy-paste into `--reply-to`.
|
||||
|
||||
When to use topics vs groups vs DM:
|
||||
- **DM** (`send <peer>`) — 1:1, ephemeral.
|
||||
- **Group** (`send "@frontend"`) — addresses everyone in a group; ephemeral; for coordinating teams.
|
||||
|
||||
Reference in New Issue
Block a user