Files
ClaudeMailbox/README.md
Mika Kuns c231f8c18c feat(plugin): add /claude-mailbox:mailbox-doctor for one-command setup
The doctor command runs entirely inside Claude Code and walks through:
binary install via npm, daemon autostart, mailbox-name prompt with write
to per-project `.claude/settings.json` env, and a self → self smoke test.
Also adds `/claude-mailbox:mailbox-status` as a read-only health check.

Reduces the colleague onboarding to: add marketplace, install plugin,
run the doctor — no terminal context-switch required.
2026-05-19 10:55:05 +02:00

196 lines
7.1 KiB
Markdown

# ClaudeMailbox
A standalone MCP mail server that lets parallel Claude sessions coordinate with each other. Any Claude session (plain terminal, ClaudeDo worktree, anything that consumes `.mcp.json`) can send messages to a peer session's inbox, check for pending messages, and discover other active mailboxes.
Not a substitute for `run_in_background: true` — that handles single-session responsiveness. This handles **session-to-session** coordination.
## Architecture
One long-running daemon binds HTTP on loopback, hosts the MCP server at `/mcp` and a small REST API at `/v1/*`, and persists state in a single SQLite file. Sessions declare themselves via an `X-Mailbox` header in their `.mcp.json`.
```
session-backend session-frontend external sender
(X-Mailbox: backend) (X-Mailbox: frontend) (CLI / UI / hook)
| | |
| HTTP | |
+--------------+-----------------+--------------------------+
v
claude-mailbox serve (ASP.NET Core + Kestrel)
/mcp MCP tools
/v1/* REST for non-MCP senders
/health
v
~/.claude-mailbox/mailbox.db (SQLite WAL)
```
## Install
The recommended path is the npm package — it works on Windows, macOS, and Linux.
```sh
# one-time per machine: point the @kuns scope at the public Gitea npm registry
npm config set @kuns:registry=https://git.kuns.dev/api/packages/releases/npm/
# install
npm install -g @kuns/claude-mailbox
```
Or use the bootstrap one-liner:
```powershell
# Windows
irm https://git.kuns.dev/releases/ClaudeMailbox/raw/branch/main/install.ps1 | iex
```
```sh
# macOS / Linux
curl -fsSL https://git.kuns.dev/releases/ClaudeMailbox/raw/branch/main/install.sh | sh
```
macOS users can also install via Homebrew once the tap is published:
```sh
brew install kuns/tap/claude-mailbox
```
### Autostart
```sh
claude-mailbox install-autostart # per-user, no admin
claude-mailbox install-autostart --service # Windows only: register as a Windows Service (admin)
claude-mailbox status # Running | Stopped | NotInstalled
claude-mailbox uninstall-autostart [--purge]
```
| Platform | Default mechanism | `--service` mechanism |
|---|---|---|
| Windows | Scheduled Task at logon (no admin) | Windows Service (admin, via `node-windows`) |
| macOS | launchd LaunchAgent in `~/Library/LaunchAgents/` | n/a |
| Linux | systemd `--user` unit in `~/.config/systemd/user/` | n/a |
### Config precedence
```
CLI flag > mailbox.json > built-in defaults
```
`mailbox.json` is searched at `~/.claude-mailbox/mailbox.json` (per-user), and on Windows additionally at `%ProgramData%\ClaudeMailbox\mailbox.json` (machine-wide, written by `--service` install). Pass `--config <path>` to override.
Defaults: port `47822`, bind `127.0.0.1`, database at `~/.claude-mailbox/mailbox.db`.
### Smoke test
```sh
claude-mailbox install-autostart
claude-mailbox status
curl http://127.0.0.1:47822/health
claude-mailbox uninstall-autostart --purge
```
### Build the .NET binary (alternative)
The original .NET 8 implementation still lives in `src/ClaudeMailbox/`. Build a self-contained Windows exe with:
```powershell
dotnet publish src/ClaudeMailbox -c Release -r win-x64 --self-contained -p:PublishSingleFile=true
```
Put the resulting `claude-mailbox.exe` on your `PATH` and use the legacy `install-service` verbs (Windows-only, admin shell):
```
claude-mailbox install-service [--port 47822] [--bind 127.0.0.1] [--db-path <path>]
claude-mailbox uninstall-service [--purge]
```
The .NET and Node builds are wire-compatible (same port, same `X-Mailbox` header, same MCP tool names, same SQLite schema), so a `.mcp.json` configured against one works against the other.
## Use from Claude Code (plugin)
Easiest path — everything happens inside Claude Code:
```
/plugin marketplace add https://git.kuns.dev/releases/ClaudeMailbox
/plugin install claude-mailbox@claude-mailbox
/claude-mailbox:mailbox-doctor
```
The doctor command checks for the `claude-mailbox` binary, installs it if missing (via npm), runs `install-autostart` if the daemon isn't registered, prompts you for a mailbox name and writes it to `.claude/settings.json`, and finishes with a self → self smoke test.
After that, unread messages appear in context before every prompt. If the daemon is unreachable later, the hook emits a one-line setup hint instead of staying silent — missing setup is loud, not invisible.
See [`plugin/README.md`](./plugin/README.md) for details, including why each Claude session needs its own mailbox name.
## Use from a Claude session
Drop this into your project's `.mcp.json` (one per session, different `X-Mailbox` values):
```json
{
"mcpServers": {
"mailbox": {
"type": "http",
"url": "http://127.0.0.1:47822/mcp",
"headers": {
"X-Mailbox": "backend"
}
}
}
}
```
Four MCP tools are exposed:
| Tool | Purpose |
|---|---|
| `mcp__mailbox__send(to, body)` | Send a message to another mailbox |
| `mcp__mailbox__check_inbox()` | Pull all pending messages for this mailbox (marks delivered) |
| `mcp__mailbox__peek_inbox()` | Non-consuming check — returns `{ pending, oldestAt }` |
| `mcp__mailbox__list_mailboxes()` | Discover known mailboxes and who has mail for you |
### Suggested CLAUDE.md snippet for poll discipline
```
When coordinating with a peer session, call mcp__mailbox__peek_inbox
after each subagent completes. If pending > 0, call mcp__mailbox__check_inbox
and treat the messages as input with priority over the current plan.
```
## CLI client mode
Any external process (scripts, UIs, hooks) can talk to a running daemon without needing MCP:
```
claude-mailbox send --to <mailbox> --from <mailbox> --body <text> [--url http://127.0.0.1:47822]
claude-mailbox peek --name <mailbox> [--url ...]
claude-mailbox check --name <mailbox> [--url ...]
claude-mailbox list [--url ...]
```
The CLI subcommands are thin HTTP clients against the `/v1/*` endpoints.
## REST surface
| Method | Path | Requires `X-Mailbox` | Purpose |
|---|---|---|---|
| `GET` | `/health` | no | `{ status, version, dbPath }` |
| `POST` | `/v1/send` | yes (sender) | `{ to, body }` |
| `GET` | `/v1/peek?name=<mailbox>` | no | read-only status |
| `POST` | `/v1/check-inbox?name=<mailbox>` | yes (must match `name`) | consume inbox |
| `GET` | `/v1/list` | no | list all mailboxes |
## Development
```
dotnet build
dotnet test tests/ClaudeMailbox.Tests/ClaudeMailbox.Tests.csproj
dotnet run --project src/ClaudeMailbox -- serve
```
Test suite covers end-to-end coordination, concurrent `check_inbox` race safety, and schema idempotency.
## Scope
- Loopback bind only (v1). Cross-machine coordination is a future extension — swap the middleware for token auth and change the bind address.
- No auth on loopback. Local filesystem permissions are the trust boundary.
- No message expiry or cleanup. Delivered messages stay as a timeline/audit log.