Files
ClaudeMailbox/README.md
Mika Kuns 5c5843e62d feat(plugin): ship Claude Code plugin + marketplace manifest
Adds a /plugin marketplace at the repo root and a `claude-mailbox` plugin under
plugin/ that wires the UserPromptSubmit hook without needing the per-user
`install-hook` step. The hook command (`claude-mailbox check --hook`) now reads
the mailbox name from $CLAUDE_MAILBOX_NAME when --name is omitted and emits a
one-line setup hint when the daemon is unreachable, so a missing daemon is loud
instead of invisible.

The plugin only contains the Claude Code glue — the daemon binary is still a
separate prerequisite (`npm i -g @kuns/claude-mailbox` + install-autostart),
and the plugin/README plus main README spell out the three-step setup.
2026-05-19 10:49:36 +02:00

7.2 KiB

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.

# 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:

# Windows
irm https://git.kuns.dev/releases/ClaudeMailbox/raw/branch/main/install.ps1 | iex
# 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:

brew install kuns/tap/claude-mailbox

Autostart

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

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:

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 for colleagues — install the marketplace once, then the plugin:

/plugin marketplace add https://git.kuns.dev/releases/ClaudeMailbox
/plugin install claude-mailbox@claude-mailbox

The plugin only wires the UserPromptSubmit hook. The daemon binary is a separate prerequisite — install it via the npm package above (or the bootstrap one-liner) and run claude-mailbox install-autostart so it starts on boot.

Then set a per-machine mailbox name:

setx CLAUDE_MAILBOX_NAME alice          # Windows
export CLAUDE_MAILBOX_NAME=alice        # macOS / Linux (in ~/.zshrc or ~/.bashrc)

Restart Claude Code and unread messages will appear in context before every prompt. If the daemon is not reachable, the hook emits a one-line setup hint instead of staying silent — so a missing daemon is loud, not invisible.

See plugin/README.md for the full walkthrough.

Use from a Claude session

Drop this into your project's .mcp.json (one per session, different X-Mailbox values):

{
  "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.