Compare commits
5 Commits
v1.1.0
...
8832eab6c7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8832eab6c7 | ||
|
|
8747d638fb | ||
|
|
d456f29138 | ||
|
|
d37d2419d6 | ||
|
|
ee0b72f43b |
@@ -38,6 +38,16 @@ jobs:
|
||||
VERSION: ${{ steps.ver.outputs.version }}
|
||||
run: npm version --no-git-tag-version --allow-same-version "$VERSION"
|
||||
|
||||
- name: Sync plugin.json version
|
||||
working-directory: ${{ github.workspace }}
|
||||
env:
|
||||
VERSION: ${{ steps.ver.outputs.version }}
|
||||
run: |
|
||||
set -euo pipefail
|
||||
jq --arg v "$VERSION" '.version = $v' plugin/.claude-plugin/plugin.json > plugin/.claude-plugin/plugin.json.tmp
|
||||
mv plugin/.claude-plugin/plugin.json.tmp plugin/.claude-plugin/plugin.json
|
||||
cat plugin/.claude-plugin/plugin.json
|
||||
|
||||
- name: Install
|
||||
run: npm ci
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ Then drop this into your project's `.mcp.json`:
|
||||
"mcpServers": {
|
||||
"mailbox": {
|
||||
"type": "http",
|
||||
"url": "http://127.0.0.1:47822/mcp"
|
||||
"url": "http://127.0.0.1:37849/mcp"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -96,7 +96,7 @@ dotnet publish src/ClaudeMailbox -c Release -r win-x64 --self-contained -p:Publi
|
||||
Put the resulting `claude-mailbox.exe` on `PATH`. Windows-only `install-service` verbs (admin shell):
|
||||
|
||||
```
|
||||
claude-mailbox install-service [--port 47822] [--bind 127.0.0.1] [--db-path <path>]
|
||||
claude-mailbox install-service [--port 37849] [--bind 127.0.0.1] [--db-path <path>]
|
||||
claude-mailbox uninstall-service [--purge]
|
||||
```
|
||||
|
||||
@@ -193,7 +193,7 @@ 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). Override with `--config <path>`.
|
||||
|
||||
Defaults: port `47822`, bind `127.0.0.1`, database at `~/.claude-mailbox/mailbox.db`.
|
||||
Defaults: port `37849`, bind `127.0.0.1`, database at `~/.claude-mailbox/mailbox.db`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -48,5 +48,5 @@ Cost: one local HTTP round-trip plus Node coldstart per prompt (~100ms on Window
|
||||
npm config set //git.kuns.dev/api/packages/releases/npm/:_authToken=<token>
|
||||
```
|
||||
|
||||
`gyp ERR! find VS` on Windows during install
|
||||
: `better-sqlite3` ships prebuilt binaries for current Node LTS versions. If yours isn't covered, npm falls back to building from source and needs the Visual Studio Build Tools. Either install them or pin to a Node version with a matching prebuild.
|
||||
`Cannot find module 'node:sqlite'` or similar
|
||||
: claude-mailbox uses Node's built-in `node:sqlite`, stable since Node 24. On Node 22.5–23.x it works only with `--experimental-sqlite`. Upgrade to Node 24 LTS or newer: `nvm install 24 && nvm use 24` (or `winget install OpenJS.NodeJS.LTS` on Windows).
|
||||
|
||||
2031
node/package-lock.json
generated
2031
node/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@kuns/claude-mailbox",
|
||||
"version": "1.1.0",
|
||||
"version": "1.3.0",
|
||||
"description": "Standalone MCP mail server that lets parallel Claude sessions coordinate with each other.",
|
||||
"type": "module",
|
||||
"bin": {
|
||||
@@ -20,11 +20,10 @@
|
||||
"prepack": "npm run build"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=20"
|
||||
"node": ">=24"
|
||||
},
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.29.0",
|
||||
"better-sqlite3": "^11.3.0",
|
||||
"commander": "^12.1.0",
|
||||
"fastify": "^5.0.0",
|
||||
"zod": "^3.25.0"
|
||||
@@ -33,10 +32,9 @@
|
||||
"node-windows": "^1.0.0-beta.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/better-sqlite3": "^7.6.11",
|
||||
"@types/node": "^22.7.4",
|
||||
"typescript": "^5.6.2",
|
||||
"vitest": "^2.1.1"
|
||||
"vitest": "^4.1.6"
|
||||
},
|
||||
"keywords": [
|
||||
"mcp",
|
||||
|
||||
@@ -271,7 +271,7 @@ program
|
||||
program
|
||||
.command("mcp-stdio")
|
||||
.description(
|
||||
"Run a stdio MCP server that proxies tool calls to the local daemon's REST API. The daemon URL comes from $CLAUDE_MAILBOX_URL (default http://127.0.0.1:47822). Used by the Claude Code plugin's .mcp.json so the URL is configurable per machine without env-substitution in the URL field.",
|
||||
"Run a stdio MCP server that proxies tool calls to the local daemon's REST API. The daemon URL comes from $CLAUDE_MAILBOX_URL (default http://127.0.0.1:37849). Used by the Claude Code plugin's .mcp.json so the URL is configurable per machine without env-substitution in the URL field.",
|
||||
)
|
||||
.action(async () => {
|
||||
try {
|
||||
@@ -345,11 +345,49 @@ program
|
||||
.option("--port <port>", "Port to listen on", (v) => parseInt(v, 10))
|
||||
.option("--bind <address>", "Bind address")
|
||||
.option("--db-path <path>", "SQLite database path")
|
||||
.action(async (opts: { service?: boolean; port?: number; bind?: string; dbPath?: string }) => {
|
||||
const mgr = await autostartManager(opts.service ? "service" : "default");
|
||||
await mgr.install({ port: opts.port, bind: opts.bind, dbPath: opts.dbPath });
|
||||
console.log("Autostart installed.");
|
||||
});
|
||||
.option(
|
||||
"--skip-port-check",
|
||||
"Skip the pre-install probe for a foreign occupant on the daemon's port",
|
||||
)
|
||||
.action(
|
||||
async (opts: {
|
||||
service?: boolean;
|
||||
port?: number;
|
||||
bind?: string;
|
||||
dbPath?: string;
|
||||
skipPortCheck?: boolean;
|
||||
}) => {
|
||||
if (!opts.skipPortCheck) {
|
||||
const cfg = resolveConfig({ port: opts.port, bind: opts.bind, dbPath: opts.dbPath });
|
||||
const probeUrl = `http://${cfg.bind}:${cfg.port}/health`;
|
||||
try {
|
||||
const res = await fetch(probeUrl, { headers: { Accept: "application/json" } });
|
||||
const text = await res.text();
|
||||
let parsed: { status?: string; version?: string } | null = null;
|
||||
try {
|
||||
parsed = text.length ? (JSON.parse(text) as { status?: string; version?: string }) : null;
|
||||
} catch {
|
||||
parsed = null;
|
||||
}
|
||||
if (res.ok && parsed?.status === "ok" && parsed.version) {
|
||||
console.log(
|
||||
`Port ${cfg.port} already serves a claude-mailbox daemon (version ${parsed.version}). Autostart will manage that one.`,
|
||||
);
|
||||
} else {
|
||||
console.error(
|
||||
`Port ${cfg.port} is held by a non-claude-mailbox service (status ${res.status}). Pick a free port via \`--port <n>\` or write {"port": <n>} to ~/.claude-mailbox/mailbox.json. Use --skip-port-check to bypass.`,
|
||||
);
|
||||
process.exit(4);
|
||||
}
|
||||
} catch {
|
||||
// Connection refused or similar — port is free, proceed.
|
||||
}
|
||||
}
|
||||
const mgr = await autostartManager(opts.service ? "service" : "default");
|
||||
await mgr.install({ port: opts.port, bind: opts.bind, dbPath: opts.dbPath });
|
||||
console.log("Autostart installed.");
|
||||
},
|
||||
);
|
||||
|
||||
program
|
||||
.command("uninstall-autostart")
|
||||
|
||||
@@ -2,7 +2,7 @@ import { existsSync, readFileSync } from "node:fs";
|
||||
import { homedir } from "node:os";
|
||||
import { join, resolve } from "node:path";
|
||||
|
||||
export const DEFAULT_PORT = 47822;
|
||||
export const DEFAULT_PORT = 37849;
|
||||
export const DEFAULT_BIND = "127.0.0.1";
|
||||
|
||||
export interface FileConfig {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import Database from "better-sqlite3";
|
||||
import { DatabaseSync, type StatementSync } from "node:sqlite";
|
||||
import { mkdirSync } from "node:fs";
|
||||
import { dirname } from "node:path";
|
||||
|
||||
@@ -57,28 +57,44 @@ function parseDate(s: string | null | undefined): Date | null {
|
||||
return isNaN(d.getTime()) ? null : d;
|
||||
}
|
||||
|
||||
function runInTransaction<T>(db: DatabaseSync, fn: () => T): T {
|
||||
db.exec("BEGIN");
|
||||
try {
|
||||
const result = fn();
|
||||
db.exec("COMMIT");
|
||||
return result;
|
||||
} catch (err) {
|
||||
try {
|
||||
db.exec("ROLLBACK");
|
||||
} catch {
|
||||
// ignore: original error already on its way up
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
export class MailboxStore {
|
||||
private readonly db: Database.Database;
|
||||
private readonly db: DatabaseSync;
|
||||
|
||||
private readonly stmts: {
|
||||
findMailbox: Database.Statement;
|
||||
insertMailbox: Database.Statement;
|
||||
touchMailbox: Database.Statement;
|
||||
listMailboxes: Database.Statement;
|
||||
insertMessage: Database.Statement;
|
||||
countPending: Database.Statement;
|
||||
oldestPending: Database.Statement;
|
||||
selectPending: Database.Statement;
|
||||
markDelivered: Database.Statement;
|
||||
pendingByRecipient: Database.Statement;
|
||||
findMailbox: StatementSync;
|
||||
insertMailbox: StatementSync;
|
||||
touchMailbox: StatementSync;
|
||||
listMailboxes: StatementSync;
|
||||
insertMessage: StatementSync;
|
||||
countPending: StatementSync;
|
||||
oldestPending: StatementSync;
|
||||
selectPending: StatementSync;
|
||||
markDelivered: StatementSync;
|
||||
pendingByRecipient: StatementSync;
|
||||
};
|
||||
|
||||
constructor(public readonly dbPath: string) {
|
||||
mkdirSync(dirname(dbPath), { recursive: true });
|
||||
this.db = new Database(dbPath);
|
||||
this.db.pragma("journal_mode = WAL");
|
||||
this.db.pragma("foreign_keys = ON");
|
||||
for (const sql of DDL_STATEMENTS) this.db.prepare(sql).run();
|
||||
this.db = new DatabaseSync(dbPath);
|
||||
this.db.exec("PRAGMA journal_mode = WAL");
|
||||
this.db.exec("PRAGMA foreign_keys = ON");
|
||||
for (const sql of DDL_STATEMENTS) this.db.exec(sql);
|
||||
|
||||
this.stmts = {
|
||||
findMailbox: this.db.prepare("SELECT * FROM mailboxes WHERE name = ?"),
|
||||
@@ -114,7 +130,7 @@ export class MailboxStore {
|
||||
|
||||
upsertMailbox(name: string): void {
|
||||
const now = nowIso();
|
||||
const existing = this.stmts.findMailbox.get(name) as MailboxRow | undefined;
|
||||
const existing = this.stmts.findMailbox.get(name) as unknown as MailboxRow | undefined;
|
||||
if (existing) {
|
||||
this.stmts.touchMailbox.run(now, name);
|
||||
} else {
|
||||
@@ -123,14 +139,13 @@ export class MailboxStore {
|
||||
}
|
||||
|
||||
send(from: string, to: string, body: string): { id: number; queuedAt: Date } {
|
||||
const tx = this.db.transaction(() => {
|
||||
return runInTransaction(this.db, () => {
|
||||
this.upsertMailbox(from);
|
||||
this.upsertMailbox(to);
|
||||
const createdAt = nowIso();
|
||||
const result = this.stmts.insertMessage.run(to, from, body, createdAt);
|
||||
return { id: Number(result.lastInsertRowid), queuedAt: new Date(createdAt) };
|
||||
});
|
||||
return tx();
|
||||
}
|
||||
|
||||
peek(name: string): InboxStatus {
|
||||
@@ -141,19 +156,18 @@ export class MailboxStore {
|
||||
}
|
||||
|
||||
checkInbox(name: string): MessageRow[] {
|
||||
const tx = this.db.transaction(() => {
|
||||
const pending = this.stmts.selectPending.all(name) as MessageRow[];
|
||||
return runInTransaction(this.db, () => {
|
||||
const pending = this.stmts.selectPending.all(name) as unknown as MessageRow[];
|
||||
if (pending.length > 0) {
|
||||
const ids = pending.map((m) => m.id);
|
||||
this.stmts.markDelivered.run(nowIso(), JSON.stringify(ids));
|
||||
}
|
||||
return pending;
|
||||
});
|
||||
return tx();
|
||||
}
|
||||
|
||||
listMailboxes(forName?: string): MailboxInfo[] {
|
||||
const rows = this.stmts.listMailboxes.all() as MailboxRow[];
|
||||
const rows = this.stmts.listMailboxes.all() as unknown as MailboxRow[];
|
||||
const pendingMap = new Map<string, number>();
|
||||
if (forName) {
|
||||
const counts = this.stmts.pendingByRecipient.all() as { to_mailbox: string; n: number }[];
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "claude-mailbox",
|
||||
"version": "0.1.0",
|
||||
"description": "Auto-checks the local Claude-Mailbox daemon before every prompt and injects pending messages into the conversation context.",
|
||||
"version": "1.3.0",
|
||||
"description": "Auto-checks the local Claude-Mailbox daemon before every prompt and after each subagent run, and injects pending messages into the conversation context.",
|
||||
"author": {
|
||||
"name": "Mika Kuns"
|
||||
},
|
||||
|
||||
@@ -14,7 +14,7 @@ The doctor walks the rest:
|
||||
|
||||
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`
|
||||
3. health-probes `http://127.0.0.1:37849/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
|
||||
|
||||
@@ -39,8 +39,9 @@ The `SessionStart` hook announces the current session's mailbox name in the conv
|
||||
|---|---|---|
|
||||
| `SessionStart` | `claude-mailbox session-announce` | Registers the session with the daemon, then prints (a) this session's mailbox name, (b) the exact `from` / `name` args to pass to MCP tools, and (c) a list of other mailboxes active in the last hour — so Claude knows who's around without needing to call `list_mailboxes` first. |
|
||||
| `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. |
|
||||
| `SubagentStop` | `claude-mailbox check --hook` | Same as `UserPromptSubmit`, but fires when a subagent finishes (Task tool). Lets the parent see peer messages that arrived during a long-running subagent run, instead of waiting until the next user prompt. |
|
||||
|
||||
Cost: one local HTTP round-trip per prompt + Node coldstart (~100ms on Windows).
|
||||
Cost: one local HTTP round-trip per prompt and per subagent stop + Node coldstart (~100ms on Windows).
|
||||
|
||||
## MCP tools
|
||||
|
||||
|
||||
@@ -1,13 +1,27 @@
|
||||
---
|
||||
description: Diagnose and auto-fix the Claude-Mailbox setup (binary install, port-conflict detection, daemon autostart, smoke test, optional base-prefix).
|
||||
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`, `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.
|
||||
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 — daemon binary on PATH
|
||||
## 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`
|
||||
|
||||
@@ -27,21 +41,21 @@ Run: `claude-mailbox --version`
|
||||
|
||||
After install, re-run `claude-mailbox --version`. If it still fails, stop and report.
|
||||
|
||||
## Step 2 — port-conflict check (before autostart!)
|
||||
## Step 3 — port-conflict check (before autostart!)
|
||||
|
||||
Default port is 47822. Probe whether anything is already on it:
|
||||
Default port is 37849. Probe whether anything is already on it:
|
||||
|
||||
```
|
||||
curl -sf http://127.0.0.1:47822/health
|
||||
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 4.
|
||||
- **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 47822.
|
||||
- **Connection refused** → port is free, ✓ continue to Step 3.
|
||||
- **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 47822 | Select-Object OwningProcess`, then `Get-Process -Id <pid>`; macOS/Linux: `lsof -i :47822`).
|
||||
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:
|
||||
@@ -51,7 +65,7 @@ If port conflict detected:
|
||||
Merge into existing env, preserving other keys.
|
||||
5. Mark `restart_needed = true`.
|
||||
|
||||
## Step 3 — daemon autostart and running state
|
||||
## Step 4 — daemon autostart and running state
|
||||
|
||||
Run: `claude-mailbox status`
|
||||
|
||||
@@ -63,11 +77,11 @@ Run: `claude-mailbox status`
|
||||
|
||||
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 4 — health probe
|
||||
## Step 5 — health probe
|
||||
|
||||
Hit `http://127.0.0.1:<port>/health` (use the configured port, not necessarily 47822). Expect a JSON body with `"status":"ok"` AND a `version` matching `claude-mailbox --version`. If unreachable or version mismatch, stop and report.
|
||||
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 5 — mailbox identity (base prefix)
|
||||
## Step 6 — mailbox identity (base prefix)
|
||||
|
||||
**No prompt by default.** Each Claude Code session gets a unique mailbox name auto-derived from its `session_id` (e.g., `claude-a8b3c1d2`).
|
||||
|
||||
@@ -80,7 +94,7 @@ Ask once: *"Want to flavor your mailbox names with a memorable prefix (e.g., `ba
|
||||
|
||||
On yes/explicit name: merge `env.CLAUDE_MAILBOX_NAME = <name>` into `.claude/settings.json`, preserving other keys. Mark `restart_needed = true`.
|
||||
|
||||
## Step 6 — smoke test
|
||||
## Step 7 — smoke test
|
||||
|
||||
Use two ephemeral names — we don't need the real session name here:
|
||||
|
||||
@@ -89,18 +103,19 @@ claude-mailbox send --from doctor-probe-a --to doctor-probe-b --body "ping from
|
||||
claude-mailbox check --name doctor-probe-b
|
||||
```
|
||||
|
||||
(If the port was changed in Step 2, pass `--url http://127.0.0.1:<port>` to both.)
|
||||
(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 7 — summary
|
||||
## 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 47822 to <port>)
|
||||
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
|
||||
|
||||
@@ -11,7 +11,7 @@ Print exactly this block, filling in each line:
|
||||
Claude-Mailbox status
|
||||
binary: <output of `claude-mailbox --version`, or "not installed">
|
||||
daemon: <output of `claude-mailbox status`>
|
||||
health: <"ok" if GET http://127.0.0.1:47822/health returns 200, else "unreachable">
|
||||
health: <"ok" if GET http://127.0.0.1:37849/health returns 200, else "unreachable">
|
||||
mailbox name: <value of env.CLAUDE_MAILBOX_NAME in ./.claude/settings.json, or "unset"; also note if ~/.claude/settings.json has a value>
|
||||
pending: <integer count from `claude-mailbox peek --name <resolved-name>` if name is set, else "n/a">
|
||||
```
|
||||
|
||||
@@ -19,6 +19,16 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"SubagentStop": [
|
||||
{
|
||||
"hooks": [
|
||||
{
|
||||
"type": "command",
|
||||
"command": "claude-mailbox check --hook"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace ClaudeMailbox.Cli;
|
||||
|
||||
public static class ClientCommands
|
||||
{
|
||||
private const string DefaultUrl = "http://127.0.0.1:47822";
|
||||
private const string DefaultUrl = "http://127.0.0.1:37849";
|
||||
|
||||
public static async Task<int> RunAsync(string[] args)
|
||||
{
|
||||
|
||||
@@ -61,7 +61,7 @@ public static class ServiceCommands
|
||||
if (!File.Exists(configPath))
|
||||
{
|
||||
var portStr = ClientCommands.GetOption(args, "--port");
|
||||
var port = int.TryParse(portStr, out var p) ? p : 47822;
|
||||
var port = int.TryParse(portStr, out var p) ? p : 37849;
|
||||
var bind = ClientCommands.GetOption(args, "--bind") ?? "127.0.0.1";
|
||||
var dbPath = ClientCommands.GetOption(args, "--db-path") ?? defaultDbPath;
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ namespace ClaudeMailbox.Config;
|
||||
|
||||
public sealed class DaemonConfig
|
||||
{
|
||||
public const int DefaultPort = 47822;
|
||||
public const int DefaultPort = 37849;
|
||||
public const string DefaultBindAddress = "127.0.0.1";
|
||||
|
||||
public int Port { get; init; } = DefaultPort;
|
||||
|
||||
Reference in New Issue
Block a user