feat(plugin): per-session mailbox identity + mailbox-update command
The hook now derives a unique mailbox name from the session_id supplied on hook stdin, so two parallel Claude Code sessions in the same project get distinct mailboxes (e.g. `claude-a8b3c1d2`, `claude-d4e5f6a7`) instead of colliding on a shared env value. An optional CLAUDE_MAILBOX_NAME base prefix flavors the names as `<base>-<sid>`. Adds: - `claude-mailbox session-announce` subcommand for the new SessionStart hook, which prints the current session's mailbox name to context - `/claude-mailbox:mailbox-update` slash command for `npm update` + daemon restart - stdin parsing helpers (parseHookStdin, deriveSessionName) with unit tests; the doctor no longer needs a mandatory name prompt
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
# 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.
|
||||
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 (two steps, all inside Claude Code)
|
||||
## Setup (three prompts, all inside Claude Code)
|
||||
|
||||
```
|
||||
/plugin marketplace add https://git.kuns.dev/releases/ClaudeMailbox
|
||||
@@ -10,50 +10,59 @@ Lets Claude Code pull unread messages from a local `claude-mailbox` daemon befor
|
||||
/claude-mailbox:mailbox-doctor
|
||||
```
|
||||
|
||||
The doctor command walks the rest:
|
||||
The doctor walks the rest:
|
||||
|
||||
1. checks whether the `claude-mailbox` binary is on `PATH` — installs it (`npm install -g @kuns/claude-mailbox`) if missing, asks before doing anything that might need elevation
|
||||
2. checks the daemon status — runs `install-autostart` and/or `start` until it reports `Running`
|
||||
3. ensures `CLAUDE_MAILBOX_NAME` is set in `.claude/settings.json` env — prompts for a name if not, writes it idempotently
|
||||
4. runs a self → self smoke test to verify the round-trip works
|
||||
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:47822/health`
|
||||
4. optionally lets you set a **base prefix** (e.g., `backend`) — without one, mailbox names are anonymous (`claude-XXXXXXXX`)
|
||||
5. runs a self → self smoke test
|
||||
|
||||
Restart Claude Code after the doctor finishes (only needed if the mailbox name was newly written). Unread messages will then appear in context before every prompt.
|
||||
Restart Claude Code only if step 4 wrote a new prefix. After that, every prompt auto-pulls unread messages.
|
||||
|
||||
## Why a mailbox name?
|
||||
## Mailbox identity (the important bit)
|
||||
|
||||
Each Claude session has an identity used to address peer sessions — like an email address. If you run a `backend` session and a `frontend` session in parallel, they need different names so they can send messages to each other.
|
||||
Each Claude Code session gets its own mailbox name, derived from the session's UUID:
|
||||
|
||||
For a single Claude Code instance just wanting notifications, any stable kebab-case name works. The name lives in **per-project** `.claude/settings.json` env, so different worktrees / projects automatically get different mailboxes.
|
||||
| Configuration | Resulting mailbox name |
|
||||
|---|---|
|
||||
| No `CLAUDE_MAILBOX_NAME` set | `claude-a8b3c1d2` (first 8 hex chars of session_id) |
|
||||
| `CLAUDE_MAILBOX_NAME=backend` in `.claude/settings.json` env | `backend-a8b3c1d2` |
|
||||
|
||||
## What the hook actually does
|
||||
So if you open two Claude Code sessions in the same project, they'll be e.g. `backend-a8b3c1d2` and `backend-d4e5f6a7` — distinct, addressable, no manual setup.
|
||||
|
||||
Before every prompt the plugin runs `claude-mailbox check --hook`, which:
|
||||
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.
|
||||
|
||||
- prints unread mailbox messages in a Claude-friendly format and marks them delivered,
|
||||
- stays **silent** when the inbox is empty or `CLAUDE_MAILBOX_NAME` is not set,
|
||||
- emits a one-line setup hint when the daemon is unreachable, so a missing daemon is loud, not invisible.
|
||||
## What the hooks do
|
||||
|
||||
Cost: one local HTTP round-trip plus Node coldstart per prompt (~100ms on Windows).
|
||||
| Hook | Command | Effect |
|
||||
|---|---|---|
|
||||
| `SessionStart` | `claude-mailbox session-announce` | Prints `"Claude-Mailbox: this session is mailbox \`X\`"` so Claude knows its own identity. |
|
||||
| `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. |
|
||||
|
||||
## Commands
|
||||
Cost: one local HTTP round-trip per prompt + Node coldstart (~100ms on Windows).
|
||||
|
||||
## 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. |
|
||||
|
||||
## Smoke test (manually, after doctor finishes)
|
||||
## Sending a message to a peer session
|
||||
|
||||
From inside Claude Code, use the MCP tool (the daemon already exposes `mcp__mailbox__*`). From any shell:
|
||||
|
||||
```sh
|
||||
claude-mailbox send --from probe --to <your-mailbox-name> --body "hello"
|
||||
claude-mailbox list # find the recipient's mailbox name
|
||||
claude-mailbox send --from probe --to backend-a8b3c1d2 --body "hi"
|
||||
```
|
||||
|
||||
Then start a new Claude Code prompt — the message should appear in context before Claude's first reply.
|
||||
|
||||
## Uninstall
|
||||
|
||||
```
|
||||
/plugin uninstall claude-mailbox@claude-mailbox
|
||||
npm uninstall -g @kuns/claude-mailbox
|
||||
claude-mailbox uninstall-autostart # if you used it
|
||||
claude-mailbox uninstall-autostart # if you registered it
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user