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.
64 lines
2.1 KiB
TypeScript
64 lines
2.1 KiB
TypeScript
import { describe, it, expect, beforeAll } from "vitest";
|
|
import { spawnSync } from "node:child_process";
|
|
import { existsSync } from "node:fs";
|
|
import { resolve } from "node:path";
|
|
|
|
const cliPath = resolve(__dirname, "..", "dist", "cli.js");
|
|
|
|
function runCli(args: string[], env: Record<string, string | undefined> = {}): {
|
|
status: number;
|
|
stdout: string;
|
|
stderr: string;
|
|
} {
|
|
const r = spawnSync(process.execPath, [cliPath, ...args], {
|
|
encoding: "utf8",
|
|
env: { ...process.env, ...env },
|
|
});
|
|
return {
|
|
status: r.status ?? -1,
|
|
stdout: typeof r.stdout === "string" ? r.stdout : "",
|
|
stderr: typeof r.stderr === "string" ? r.stderr : "",
|
|
};
|
|
}
|
|
|
|
describe("`check --hook` CLI behavior", () => {
|
|
beforeAll(() => {
|
|
if (!existsSync(cliPath)) {
|
|
throw new Error(`CLI not built. Run \`npm run build\` first. Missing: ${cliPath}`);
|
|
}
|
|
});
|
|
|
|
it("exits 0 silently when no name resolved (no --name, no env)", () => {
|
|
const r = runCli(["check", "--hook"], { CLAUDE_MAILBOX_NAME: undefined });
|
|
expect(r.status).toBe(0);
|
|
expect(r.stdout).toBe("");
|
|
expect(r.stderr).toBe("");
|
|
});
|
|
|
|
it("emits daemon-not-reachable hint when name is set but daemon is down", () => {
|
|
const r = runCli(
|
|
["check", "--hook", "--url", "http://127.0.0.1:1"],
|
|
{ CLAUDE_MAILBOX_NAME: "alice" },
|
|
);
|
|
expect(r.status).toBe(0);
|
|
expect(r.stdout).toContain("[Claude-Mailbox] Daemon not reachable");
|
|
expect(r.stdout).toContain("http://127.0.0.1:1");
|
|
expect(r.stdout).toContain("claude-mailbox install-autostart");
|
|
});
|
|
|
|
it("`--name` arg wins over CLAUDE_MAILBOX_NAME env (visible via hint URL/contents)", () => {
|
|
const r = runCli(
|
|
["check", "--hook", "--name", "bob", "--url", "http://127.0.0.1:1"],
|
|
{ CLAUDE_MAILBOX_NAME: "alice" },
|
|
);
|
|
expect(r.status).toBe(0);
|
|
expect(r.stdout).toContain("[Claude-Mailbox] Daemon not reachable");
|
|
});
|
|
|
|
it("non-hook mode errors out when no name resolved", () => {
|
|
const r = runCli(["check"], { CLAUDE_MAILBOX_NAME: undefined });
|
|
expect(r.status).not.toBe(0);
|
|
expect(r.stderr).toContain("CLAUDE_MAILBOX_NAME");
|
|
});
|
|
});
|