Mailbox names are now built as <project>-<session-short>, where <project> is the sanitized git-repo basename (or cwd basename) — no more env-var prefix step. Sessions can re-tag themselves at runtime via the new mcp__mailbox__rename tool (POST /v1/rename), which transfers all pending messages to the new name in a single transaction. Peers using the old name re-discover via list_mailboxes. BREAKING: \$CLAUDE_MAILBOX_NAME is no longer read. Existing setups that relied on the env-var prefix should remove it from .claude/settings.json; the prefix now comes from the working directory automatically. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
124 lines
6.5 KiB
Markdown
124 lines
6.5 KiB
Markdown
---
|
|
description: Diagnose and auto-fix the Claude-Mailbox setup (Node version, binary install, port-conflict detection, daemon autostart, smoke test, optional base-prefix).
|
|
allowed-tools: Bash, Read, Edit, Write
|
|
---
|
|
|
|
You are running the **Claude-Mailbox doctor**. Walk through these checks in order. After each step, print a one-line `✓` / `✗` with the action you took. End with a summary block.
|
|
|
|
Use `Bash` only for `claude-mailbox` subcommands, `npm`, `node`, `where`/`which`, and HTTP probes. Use `Read`/`Edit`/`Write` for `.claude/settings.json` and `mailbox.json`. Never run `sudo` automatically — if elevation is needed, stop and ask.
|
|
|
|
## Step 1 — Node.js version
|
|
|
|
Run: `node --version`
|
|
|
|
claude-mailbox uses Node's built-in `node:sqlite` and therefore requires **Node 24 or newer**. Parse the major version from the output.
|
|
|
|
- **Major ≥ 24** → ✓ record the version, continue.
|
|
- **Major == 22 or 23** → ✗ Stop. `node:sqlite` is experimental on these and requires `--experimental-sqlite`. Print:
|
|
> Found Node `<X.Y.Z>`. claude-mailbox needs Node 24 LTS or newer. Install via `nvm install 24 && nvm use 24` (or `nvs` / `winget install OpenJS.NodeJS.LTS` on Windows), then re-run the doctor.
|
|
- **Major < 22** → ✗ Stop with the same message; this Node is end-of-life.
|
|
- **Major ≥ 26** with `better-sqlite3` still installed globally from a previous version → just note: "Node `<X.Y.Z>` is fine for the current claude-mailbox (no native deps); ignore any old `better-sqlite3` build warnings from a prior install."
|
|
|
|
If `node --version` itself fails (`command not found`), stop and tell the user to install Node 24+ first.
|
|
|
|
## Step 2 — daemon binary on PATH
|
|
|
|
Run: `claude-mailbox --version`
|
|
|
|
- **Exit 0** → ✓ record the version. Continue.
|
|
- **Command not found** → binary missing. Install path:
|
|
|
|
| Platform | Command |
|
|
|---|---|
|
|
| Windows | `npm install -g @kuns/claude-mailbox` (no admin) |
|
|
| macOS / Linux | `npm install -g @kuns/claude-mailbox` (may fail with EACCES — never run sudo automatically; ask the user) |
|
|
|
|
Prerequisite: `npm config get @kuns:registry` must point at `https://git.kuns.dev/api/packages/releases/npm/`. If not:
|
|
|
|
```
|
|
npm config set @kuns:registry=https://git.kuns.dev/api/packages/releases/npm/
|
|
```
|
|
|
|
After install, re-run `claude-mailbox --version`. If it still fails, stop and report.
|
|
|
|
## Step 3 — port-conflict check (before autostart!)
|
|
|
|
Default port is 37849. Probe whether anything is already on it:
|
|
|
|
```
|
|
curl -sf http://127.0.0.1:37849/health
|
|
```
|
|
|
|
- **Returns a JSON body with `"status":"ok"` and a `version` field that matches `claude-mailbox --version`** → it's already our daemon, ✓ skip to Step 5.
|
|
- **Returns 200 with `"status":"ok"` but a different `version`** → it's an older claude-mailbox; treat as running, ✓.
|
|
- **Returns non-200, non-JSON, or any other foreign response** → **port conflict**. Some other process owns 37849.
|
|
- **Connection refused** → port is free, ✓ continue to Step 4.
|
|
|
|
If port conflict detected:
|
|
1. Tell the user which process holds the port (Windows: `Get-NetTCPConnection -LocalPort 37849 | Select-Object OwningProcess`, then `Get-Process -Id <pid>`; macOS/Linux: `lsof -i :37849`).
|
|
2. Pick a free port. Default suggestion: **47900**. Verify it's free: `curl -sf http://127.0.0.1:47900/health` should fail with connection refused.
|
|
3. Read `~/.claude-mailbox/mailbox.json` (create empty `{}` if missing) and merge `{"port": <chosen>}`. Write back.
|
|
4. Also write the override into `.claude/settings.json` env so the plugin's hooks find the right URL:
|
|
```json
|
|
"env": { "CLAUDE_MAILBOX_URL": "http://127.0.0.1:<chosen>" }
|
|
```
|
|
Merge into existing env, preserving other keys.
|
|
5. Mark `restart_needed = true`.
|
|
|
|
## Step 4 — daemon autostart and running state
|
|
|
|
Run: `claude-mailbox status`
|
|
|
|
- `Running` → ✓ continue.
|
|
- `Stopped` → `claude-mailbox start`, re-check.
|
|
- `NotInstalled` → `claude-mailbox install-autostart`, then `claude-mailbox start`, re-check.
|
|
|
|
**Behavior on `install-autostart`:** The CLI tries a Scheduled Task first (`schtasks /RL LIMITED`, no admin). If Windows Group Policy returns "Access is denied", it falls back transparently to an `HKCU\Software\Microsoft\Windows\CurrentVersion\Run` registry entry plus a hidden `node serve` process — same per-user persistence, no admin needed. The chosen mechanism is recorded in `~/.claude-mailbox/autostart-mode` and respected by `status`/`start`/`stop`/`uninstall-autostart`.
|
|
|
|
If `install-autostart` still fails after both attempts (very rare — would mean both `schtasks` and `reg add` are blocked), stop and report what `status` and `start` printed.
|
|
|
|
## Step 5 — health probe
|
|
|
|
Hit `http://127.0.0.1:<port>/health` (use the configured port, not necessarily 37849). Expect a JSON body with `"status":"ok"` AND a `version` matching `claude-mailbox --version`. If unreachable or version mismatch, stop and report.
|
|
|
|
## Step 6 — mailbox identity
|
|
|
|
**No prompt.** Each Claude Code session gets a unique mailbox name auto-derived as `<project>-<short_session_id>`, where `<project>` is the git-repo basename of the session's `cwd` (or the cwd basename if not a git repo). Example: `claude-mailbox-a8b3c1d2`.
|
|
|
|
✓ "Mailbox name will be auto-derived as `<project>-<short_session_id>`."
|
|
|
|
Sessions can also rename themselves at runtime via the `mcp__mailbox__rename` MCP tool — e.g. to add an area tag like `claude-mailbox-frontend-a8b3c1d2`. No config involved.
|
|
|
|
## Step 7 — smoke test
|
|
|
|
Use two ephemeral names — we don't need the real session name here:
|
|
|
|
```
|
|
claude-mailbox send --from doctor-probe-a --to doctor-probe-b --body "ping from doctor"
|
|
claude-mailbox check --name doctor-probe-b
|
|
```
|
|
|
|
(If the port was changed in Step 3, pass `--url http://127.0.0.1:<port>` to both.)
|
|
|
|
The `check` output must be a JSON array with one message: `from: doctor-probe-a`, body matches. ✓ on success, ✗ otherwise.
|
|
|
|
## Step 8 — summary
|
|
|
|
```
|
|
Claude-Mailbox doctor
|
|
node: <version>
|
|
binary: <version>
|
|
daemon: Running (port: <port>, what you did if anything)
|
|
health: ok
|
|
port conflict: none | resolved (moved from 37849 to <port>)
|
|
base prefix: <name from settings, or "auto-derived (anonymous)">
|
|
smoke test: passed | failed
|
|
restart hint: yes if restart_needed, otherwise no
|
|
```
|
|
|
|
End with one of:
|
|
|
|
- All ✓ and no restart needed → "Setup is healthy. Your mailbox name this session will be revealed by the SessionStart hook on next session start."
|
|
- All ✓ and restart needed → "Restart Claude Code (or open a new session) so the SessionStart hook picks up the new env values."
|
|
- Anything ✗ → "Setup incomplete: <first failure>."
|