fix(cli,plugin): CLAUDE_MAILBOX_URL env override + port-conflict-aware doctor
All checks were successful
CI (Node) / build-test (push) Successful in 9s

The plugin's UserPromptSubmit and SessionStart hooks call `claude-mailbox`
with no --url flag, so they previously always hit the hardcoded
http://127.0.0.1:47822/mcp default. If port 47822 was held by another
local service (e.g. ClaudeDo), the daemon couldn't bind there and every
hook was talking to the wrong process.

CLI default for --url now resolves to $CLAUDE_MAILBOX_URL when set,
falling back to http://127.0.0.1:47822. Doctor gained a Step 2 that
probes /health on 47822, identifies foreign occupants, picks a free
port, writes both ~/.claude-mailbox/mailbox.json and the
CLAUDE_MAILBOX_URL entry in .claude/settings.json env so the hooks
follow along automatically.

Also adds a fallback hint when Windows schtasks /Create fails with
Access is denied (Group Policy restricts non-admin task creation): run
install-autostart from an elevated shell, or accept an ephemeral serve
for the current session.
This commit is contained in:
Mika Kuns
2026-05-19 13:30:51 +02:00
parent 73a49e405f
commit ac626f678b
3 changed files with 62 additions and 28 deletions

View File

@@ -71,6 +71,15 @@ describe("`check --hook` CLI behavior", () => {
expect(r.stdout).toContain("[Claude-Mailbox] Daemon not reachable");
});
it("uses CLAUDE_MAILBOX_URL env as default base URL when --url is not given", () => {
const r = runCli(["check", "--hook"], {
env: { CLAUDE_MAILBOX_NAME: undefined, CLAUDE_MAILBOX_URL: "http://127.0.0.1:1" },
stdin: HOOK_STDIN,
});
expect(r.status).toBe(0);
expect(r.stdout).toContain("[Claude-Mailbox] Daemon not reachable at http://127.0.0.1:1");
});
it("non-hook mode errors out when no name resolved", () => {
const r = runCli(["check"], { env: { CLAUDE_MAILBOX_NAME: undefined } });
expect(r.status).not.toBe(0);