Adds a Push delivery (watch) section to the root README with exit-code table, cross-process semantics, and the active-vs-idle latency caveat that came out of the empirical Claude Code BashOutput test. Adds a brief reference + cross-link in node/README.md, and notes the SessionStart bootstrap behavior in plugin/README.md alongside the existing hook table. Adds /v1/watch to the REST surface table and the watch verb to the CLI listing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
95 lines
5.7 KiB
Markdown
95 lines
5.7 KiB
Markdown
# claude-mailbox plugin
|
|
|
|
Lets Claude Code pull unread messages from a local `claude-mailbox` daemon before every prompt and inject them into the conversation context. Each Claude session gets a **unique mailbox identity** auto-derived from its session id, so two sessions in the same project never collide.
|
|
|
|
## Setup (three prompts, all inside Claude Code)
|
|
|
|
```
|
|
/plugin marketplace add https://git.kuns.dev/releases/ClaudeMailbox.git
|
|
/plugin install claude-mailbox@claude-mailbox
|
|
/claude-mailbox:mailbox-doctor
|
|
```
|
|
|
|
The doctor walks the rest:
|
|
|
|
1. installs the `claude-mailbox` binary via `npm install -g @kuns/claude-mailbox` if missing (asks first)
|
|
2. registers the daemon for autostart and starts it if needed
|
|
3. health-probes `http://127.0.0.1:37849/health`
|
|
4. runs a self → self smoke test
|
|
|
|
After that, every prompt auto-pulls unread messages.
|
|
|
|
## Mailbox identity (the important bit)
|
|
|
|
Each Claude Code session gets its own mailbox name, automatically derived as `<project>-<session-short>`:
|
|
|
|
| Where the session runs | Resulting mailbox name |
|
|
|---|---|
|
|
| Inside a git repo | `<repo-basename>-a8b3c1d2` (e.g. `claude-mailbox-a8b3c1d2`) |
|
|
| Outside a git repo | `<cwd-basename>-a8b3c1d2` |
|
|
| No cwd in stdin (rare) | `claude-a8b3c1d2` |
|
|
|
|
So if you open two Claude Code sessions in the same project, they'll share the project prefix but differ in the session-short — e.g. `claude-mailbox-a8b3c1d2` and `claude-mailbox-d4e5f6a7`. No env-var, no manual prefix step.
|
|
|
|
If a session focuses on a sub-area (frontend, backend, …), Claude can call `mcp__mailbox__rename(current_name="…", new_name="claude-mailbox-frontend-a8b3c1d2")` to tag itself; pending messages are transferred. Peers using the old name re-discover via `list_mailboxes`.
|
|
|
|
The `SessionStart` hook announces the current session's mailbox name in the conversation context on startup. Peers discover each other via `claude-mailbox list` or the `mcp__mailbox__list_mailboxes` MCP tool.
|
|
|
|
## What the hooks do
|
|
|
|
| Hook | Command | Effect |
|
|
|---|---|---|
|
|
| `SessionStart` | `claude-mailbox session-announce` | Registers the session with the daemon, then prints (a) this session's mailbox name, (b) the exact `from` / `name` args to pass to MCP tools, and (c) a list of other mailboxes active in the last hour — so Claude knows who's around without needing to call `list_mailboxes` first. |
|
|
| `UserPromptSubmit` | `claude-mailbox check --hook` | Pulls unread messages for the session's mailbox and injects them as context. Silent on empty inbox; emits a one-line setup hint when the daemon is unreachable. |
|
|
| `SubagentStop` | `claude-mailbox check --hook` | Same as `UserPromptSubmit`, but fires when a subagent finishes (Task tool). Lets the parent see peer messages that arrived during a long-running subagent run, instead of waiting until the next user prompt. |
|
|
|
|
Cost: one local HTTP round-trip per prompt and per subagent stop + Node coldstart (~100ms on Windows).
|
|
|
|
The SessionStart announcement also instructs Claude to start `claude-mailbox watch --block --name <derived-name>` as a background bash task on its first turn. While that watcher is alive, peers can `mcp__mailbox__send(...)` and Claude reacts mid-turn — no user prompt needed. After processing each completion (delivery, timeout, rename, or daemon-down), Claude relaunches the watcher in the background. The pull hook (`UserPromptSubmit`) remains as a fallback for any messages that arrive while no watcher is running.
|
|
|
|
## MCP tools
|
|
|
|
The plugin ships a `.mcp.json` that spawns a **stdio MCP wrapper** (`claude-mailbox mcp-stdio`) so the daemon URL is configurable per machine via the `CLAUDE_MAILBOX_URL` env var (Claude Code doesn't yet support env substitution in HTTP MCP URLs — see issue #46889). The wrapper proxies tool calls to the daemon's REST API.
|
|
|
|
Each MCP tool takes the caller's mailbox name as an explicit argument (from the SessionStart announcement):
|
|
|
|
| Tool | Required args | Purpose |
|
|
|---|---|---|
|
|
| `mcp__mailbox__send` | `from`, `to`, `body` | Send a message to another mailbox. |
|
|
| `mcp__mailbox__check_inbox` | `name` | Pull all undelivered messages for your mailbox (marks delivered). |
|
|
| `mcp__mailbox__peek_inbox` | `name` | Non-consuming count of pending messages. |
|
|
| `mcp__mailbox__list_mailboxes` | `name` | Discover known mailboxes and `pendingForYou` counts. |
|
|
| `mcp__mailbox__rename` | `current_name`, `new_name` | Rename your own mailbox (e.g. add an area tag). Pending messages are transferred. Use the new name afterward. |
|
|
|
|
The SessionStart announcement spells out the exact args to pass, so Claude picks them up automatically.
|
|
|
|
## Slash commands
|
|
|
|
| Command | What it does |
|
|
|---|---|
|
|
| `/claude-mailbox:mailbox-doctor` | Diagnose + auto-fix the full setup. |
|
|
| `/claude-mailbox:mailbox-status` | Read-only health check. No changes. |
|
|
| `/claude-mailbox:mailbox-update` | Update the daemon to the latest npm version and restart it. |
|
|
|
|
## Coordinating two Claude Code sessions
|
|
|
|
1. Open two Claude Code sessions in the same (or different) project.
|
|
2. Each session's SessionStart hook registers itself with the daemon and prints both its own mailbox name and the **list of currently active peers** into context.
|
|
3. In session A you can simply say: *"I started a second session, coordinate with it."* Because the peer's mailbox name is already in context, Claude can call `mcp__mailbox__send(from="<my-name>", to="<peer-name>", body="...")` straight away — no manual `list_mailboxes` step needed.
|
|
4. Session B's `UserPromptSubmit` hook pulls the message on its next prompt and injects it as context.
|
|
|
|
You can also send from any shell:
|
|
|
|
```sh
|
|
claude-mailbox list
|
|
claude-mailbox send --from probe --to backend-a8b3c1d2 --body "hi"
|
|
```
|
|
|
|
## Uninstall
|
|
|
|
```
|
|
/plugin uninstall claude-mailbox@claude-mailbox
|
|
npm uninstall -g @kuns/claude-mailbox
|
|
claude-mailbox uninstall-autostart # if you registered it
|
|
```
|