@birdybeep/cli 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.cjs +489 -75
- package/dist/bin.cjs.map +1 -1
- package/dist/bin.js +1 -1
- package/dist/{chunk-OCS5IDYI.js → chunk-ZYFMLHY4.js} +479 -78
- package/dist/chunk-ZYFMLHY4.js.map +1 -0
- package/dist/index.cjs +477 -75
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -1
- package/dist/index.d.ts +18 -1
- package/dist/index.js +1 -1
- package/package.json +7 -5
- package/dist/chunk-OCS5IDYI.js.map +0 -1
package/dist/index.d.cts
CHANGED
|
@@ -35,6 +35,16 @@ interface CommandContext {
|
|
|
35
35
|
flags: GlobalFlags;
|
|
36
36
|
io: Io;
|
|
37
37
|
}
|
|
38
|
+
/** A per-command flag: its accepted spellings, optional value placeholder, and help text. */
|
|
39
|
+
interface CommandOption {
|
|
40
|
+
/** Primary flag token, e.g. `"--expect-email"`. */
|
|
41
|
+
flag: string;
|
|
42
|
+
/** Extra accepted spellings, e.g. `["-y"]`. */
|
|
43
|
+
aliases?: readonly string[];
|
|
44
|
+
/** Value placeholder shown in help (e.g. `"<addr>"`); omit for boolean flags. */
|
|
45
|
+
value?: string;
|
|
46
|
+
summary: string;
|
|
47
|
+
}
|
|
38
48
|
interface Command {
|
|
39
49
|
name: string;
|
|
40
50
|
summary: string;
|
|
@@ -42,6 +52,13 @@ interface Command {
|
|
|
42
52
|
usage?: string;
|
|
43
53
|
/** Nested subcommands (e.g. `agent install` / `agent uninstall`). */
|
|
44
54
|
subcommands?: Command[];
|
|
55
|
+
/**
|
|
56
|
+
* Flags this command accepts IN ADDITION to the global ones. Without this allowlist the
|
|
57
|
+
* dispatcher rejects every non-global flag as an unknown option, so a command that owns
|
|
58
|
+
* flags must declare them here — and declaring them also documents them in `--help`.
|
|
59
|
+
* Both `--flag value` and `--flag=value` are accepted; parsing stays the command's job.
|
|
60
|
+
*/
|
|
61
|
+
options?: readonly CommandOption[];
|
|
45
62
|
/** Command logic; returns the intended exit code. Absent for pure command groups. */
|
|
46
63
|
run?(ctx: CommandContext): Promise<number> | number;
|
|
47
64
|
}
|
|
@@ -139,4 +156,4 @@ interface RunCliDeps {
|
|
|
139
156
|
/** Run the CLI against an argv slice (without `node`/script path). Returns the exit code. */
|
|
140
157
|
declare function runCli(argv: string[], deps?: RunCliDeps): Promise<number>;
|
|
141
158
|
|
|
142
|
-
export { CLI_VERSION, type Command, type CommandContext, type DispatchDeps, EXIT, type GlobalFlags, type Io, MissingInputError, type RunCliDeps, type Writer, buildCommands, createIo, dispatch, parseGlobalFlags, requireValue, runCli };
|
|
159
|
+
export { CLI_VERSION, type Command, type CommandContext, type CommandOption, type DispatchDeps, EXIT, type GlobalFlags, type Io, MissingInputError, type RunCliDeps, type Writer, buildCommands, createIo, dispatch, parseGlobalFlags, requireValue, runCli };
|
package/dist/index.d.ts
CHANGED
|
@@ -35,6 +35,16 @@ interface CommandContext {
|
|
|
35
35
|
flags: GlobalFlags;
|
|
36
36
|
io: Io;
|
|
37
37
|
}
|
|
38
|
+
/** A per-command flag: its accepted spellings, optional value placeholder, and help text. */
|
|
39
|
+
interface CommandOption {
|
|
40
|
+
/** Primary flag token, e.g. `"--expect-email"`. */
|
|
41
|
+
flag: string;
|
|
42
|
+
/** Extra accepted spellings, e.g. `["-y"]`. */
|
|
43
|
+
aliases?: readonly string[];
|
|
44
|
+
/** Value placeholder shown in help (e.g. `"<addr>"`); omit for boolean flags. */
|
|
45
|
+
value?: string;
|
|
46
|
+
summary: string;
|
|
47
|
+
}
|
|
38
48
|
interface Command {
|
|
39
49
|
name: string;
|
|
40
50
|
summary: string;
|
|
@@ -42,6 +52,13 @@ interface Command {
|
|
|
42
52
|
usage?: string;
|
|
43
53
|
/** Nested subcommands (e.g. `agent install` / `agent uninstall`). */
|
|
44
54
|
subcommands?: Command[];
|
|
55
|
+
/**
|
|
56
|
+
* Flags this command accepts IN ADDITION to the global ones. Without this allowlist the
|
|
57
|
+
* dispatcher rejects every non-global flag as an unknown option, so a command that owns
|
|
58
|
+
* flags must declare them here — and declaring them also documents them in `--help`.
|
|
59
|
+
* Both `--flag value` and `--flag=value` are accepted; parsing stays the command's job.
|
|
60
|
+
*/
|
|
61
|
+
options?: readonly CommandOption[];
|
|
45
62
|
/** Command logic; returns the intended exit code. Absent for pure command groups. */
|
|
46
63
|
run?(ctx: CommandContext): Promise<number> | number;
|
|
47
64
|
}
|
|
@@ -139,4 +156,4 @@ interface RunCliDeps {
|
|
|
139
156
|
/** Run the CLI against an argv slice (without `node`/script path). Returns the exit code. */
|
|
140
157
|
declare function runCli(argv: string[], deps?: RunCliDeps): Promise<number>;
|
|
141
158
|
|
|
142
|
-
export { CLI_VERSION, type Command, type CommandContext, type DispatchDeps, EXIT, type GlobalFlags, type Io, MissingInputError, type RunCliDeps, type Writer, buildCommands, createIo, dispatch, parseGlobalFlags, requireValue, runCli };
|
|
159
|
+
export { CLI_VERSION, type Command, type CommandContext, type CommandOption, type DispatchDeps, EXIT, type GlobalFlags, type Io, MissingInputError, type RunCliDeps, type Writer, buildCommands, createIo, dispatch, parseGlobalFlags, requireValue, runCli };
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@birdybeep/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "The BirdyBeep CLI — pair your machine, install agent adapters, and stream coding-agent lifecycle events to BirdyBeep.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -32,10 +32,12 @@
|
|
|
32
32
|
],
|
|
33
33
|
"dependencies": {
|
|
34
34
|
"uqr": "0.1.2",
|
|
35
|
-
"@birdybeep/agent-core": "0.
|
|
36
|
-
"@birdybeep/claude-code": "0.
|
|
37
|
-
"@birdybeep/codex": "0.
|
|
38
|
-
"@birdybeep/
|
|
35
|
+
"@birdybeep/agent-core": "0.4.0",
|
|
36
|
+
"@birdybeep/claude-code": "0.4.0",
|
|
37
|
+
"@birdybeep/codex": "0.4.0",
|
|
38
|
+
"@birdybeep/copilot": "0.4.0",
|
|
39
|
+
"@birdybeep/cursor": "0.4.0",
|
|
40
|
+
"@birdybeep/opencode": "0.4.0"
|
|
39
41
|
},
|
|
40
42
|
"devDependencies": {
|
|
41
43
|
"@birdybeep/test-harness": "0.0.0"
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/framework.ts","../src/version.ts","../src/commands/agent.ts","../src/commands/doctor.ts","../src/config.ts","../src/diagnostics.ts","../src/commands/hook.ts","../src/commands/logout.ts","../src/commands/pair.ts","../src/pairing.ts","../src/commands/queue.ts","../src/commands/report-status.ts","../src/commands/status.ts","../src/commands/test.ts","../src/commands.ts","../src/update-check.ts","../src/cli.ts"],"sourcesContent":["/**\n * The CLI framework (§9.4): a small zero-dependency command dispatcher every `birdybeep`\n * command plugs into. Owns global flag parsing (`--json` / `--non-interactive` /\n * `--version` / `--help`), nested subcommand routing, help rendering, the config-dir\n * bootstrap, a json-aware output layer, and a shared exit-code convention. Network/auth,\n * adapter, and secret logic live in the individual commands — never here.\n *\n * Kept dependency-light on purpose: this code installs into developers' machines, so the\n * smaller + more auditable the surface, the better (§16.4).\n */\nimport { mkdirSync } from \"node:fs\";\n\nimport { birdyBeepConfigDir } from \"@birdybeep/agent-core\";\n\n/** Shared exit-code convention so callers (humans + agents) can branch on the result. */\nexport const EXIT = { OK: 0, ERROR: 1, USAGE: 2 } as const;\n\n/** A minimal output sink (process.stdout/stderr in prod; capturing buffers in tests). */\nexport interface Writer {\n write(s: string): void;\n}\n\nexport interface GlobalFlags {\n /** Machine-readable JSON output for agents/scripts. */\n json: boolean;\n /** Never prompt; fail fast (non-zero) when a required value is missing. */\n nonInteractive: boolean;\n help: boolean;\n version: boolean;\n}\n\n/** Json-aware output. `line`/`result` are mutually exclusive by mode so stdout stays clean. */\nexport interface Io {\n readonly json: boolean;\n /** Human line → stdout (suppressed in `--json` mode). */\n line(text: string): void;\n /** Always → stderr (errors/warnings show in both modes). */\n errline(text: string): void;\n /** Structured result → stdout as JSON (only in `--json` mode). */\n result(value: unknown): void;\n /** Emit the right one for the mode: human text, or the structured value as JSON. */\n emit(human: string, json: unknown): void;\n}\n\nexport function createIo(json: boolean, stdout: Writer, stderr: Writer): Io {\n return {\n json,\n line: (text) => {\n if (!json) stdout.write(`${text}\\n`);\n },\n errline: (text) => stderr.write(`${text}\\n`),\n result: (value) => {\n if (json) stdout.write(`${JSON.stringify(value)}\\n`);\n },\n emit: (human, value) => {\n if (json) stdout.write(`${JSON.stringify(value)}\\n`);\n else stdout.write(`${human}\\n`);\n },\n };\n}\n\nexport interface CommandContext {\n /** Positional args after the resolved command path. */\n args: string[];\n flags: GlobalFlags;\n io: Io;\n}\n\nexport interface Command {\n name: string;\n summary: string;\n /** One-line usage shown in the command's own `--help`. */\n usage?: string;\n /** Nested subcommands (e.g. `agent install` / `agent uninstall`). */\n subcommands?: Command[];\n /** Command logic; returns the intended exit code. Absent for pure command groups. */\n run?(ctx: CommandContext): Promise<number> | number;\n}\n\n/** Thrown by a command when a required value is missing under `--non-interactive`. */\nexport class MissingInputError extends Error {\n constructor(readonly field: string) {\n super(`missing required value: ${field}`);\n this.name = \"MissingInputError\";\n }\n}\n\n/**\n * Resolve a value that may require interaction. Returns `provided` when present; otherwise\n * throws {@link MissingInputError} under `--non-interactive` (so the CLI fails fast instead\n * of hanging), or returns undefined for the caller to prompt in interactive mode.\n */\nexport function requireValue<T>(ctx: CommandContext, field: string, provided: T | undefined): T {\n if (provided !== undefined) return provided;\n if (ctx.flags.nonInteractive) throw new MissingInputError(field);\n throw new MissingInputError(field); // interactive prompting is a per-command concern; default fail-fast\n}\n\nconst GLOBAL_FLAG_TOKENS = new Set([\n \"--json\",\n \"--non-interactive\",\n \"--version\",\n \"-v\",\n \"--help\",\n \"-h\",\n]);\n\n/** Split a raw argv into global flags + the remaining (command path + positional) tokens. */\nexport function parseGlobalFlags(argv: string[]): { flags: GlobalFlags; rest: string[] } {\n const flags: GlobalFlags = { json: false, nonInteractive: false, help: false, version: false };\n const rest: string[] = [];\n for (const token of argv) {\n switch (token) {\n case \"--json\":\n flags.json = true;\n break;\n case \"--non-interactive\":\n flags.nonInteractive = true;\n break;\n case \"--version\":\n case \"-v\":\n flags.version = true;\n break;\n case \"--help\":\n case \"-h\":\n flags.help = true;\n break;\n default:\n rest.push(token);\n }\n }\n return { flags, rest };\n}\n\n/** Is `token` an unknown long/short flag (after global flags were stripped)? */\nfunction isUnknownFlag(token: string): boolean {\n return token.startsWith(\"-\") && !GLOBAL_FLAG_TOKENS.has(token);\n}\n\nfunction renderRootHelp(version: string, commands: Command[]): string {\n const width = Math.max(...commands.map((c) => c.name.length));\n const lines = commands.map((c) => ` ${c.name.padEnd(width)} ${c.summary}`);\n return [\n `birdybeep ${version} — stream coding-agent lifecycle events to BirdyBeep.`,\n \"\",\n \"Usage:\",\n \" birdybeep <command> [options]\",\n \"\",\n \"Commands:\",\n ...lines,\n \"\",\n \"Global options:\",\n \" --json Machine-readable JSON output\",\n \" --non-interactive Never prompt; fail fast if input is required\",\n \" -h, --help Show help (root or per-command)\",\n \" -v, --version Show the CLI version\",\n ].join(\"\\n\");\n}\n\nfunction renderCommandHelp(path: string, command: Command): string {\n const lines = [\n `birdybeep ${path} — ${command.summary}`,\n \"\",\n \"Usage:\",\n ` ${command.usage ?? `birdybeep ${path} [options]`}`,\n ];\n if (command.subcommands && command.subcommands.length > 0) {\n const width = Math.max(...command.subcommands.map((c) => c.name.length));\n lines.push(\n \"\",\n \"Subcommands:\",\n ...command.subcommands.map((c) => ` ${c.name.padEnd(width)} ${c.summary}`),\n );\n }\n return lines.join(\"\\n\");\n}\n\nexport interface DispatchDeps {\n version: string;\n commands: Command[];\n stdout: Writer;\n stderr: Writer;\n /** Skip the config-dir bootstrap (tests that don't want filesystem side effects). */\n ensureConfig?: boolean;\n /**\n * Optional post-command update notifier, invoked after a command runs successfully (not for\n * help/version). The framework only invokes it — all registry/cache/semver logic lives in the\n * CLI layer (`update-check.ts`), never here — and its failure never affects the command result.\n */\n notifyUpdate?: (ctx: { command: string; flags: GlobalFlags; io: Io }) => Promise<void>;\n}\n\n/**\n * Run the CLI against an argv slice (without `node`/script path). Resolves the command\n * (with nested subcommands), handles `--help`/`--version`, and returns the exit code.\n * Never throws — command errors become a stderr message + {@link EXIT.ERROR}.\n */\nexport async function dispatch(argv: string[], deps: DispatchDeps): Promise<number> {\n const { flags, rest } = parseGlobalFlags(argv);\n const io = createIo(flags.json, deps.stdout, deps.stderr);\n\n // Config dir is created on first run (non-secret CLI config only — never a token).\n if (deps.ensureConfig !== false) {\n try {\n mkdirSync(birdyBeepConfigDir(), { recursive: true, mode: 0o700 });\n } catch {\n /* non-fatal: a read-only config dir is surfaced by `doctor`, not here */\n }\n }\n\n if (flags.version) {\n io.emit(deps.version, { version: deps.version });\n return EXIT.OK;\n }\n\n // Resolve the command path (supports one level of nested subcommands).\n let command: Command | undefined = deps.commands.find((c) => c.name === rest[0]);\n const pathParts: string[] = [];\n let argsStart = 1;\n if (command) {\n pathParts.push(command.name);\n if (command.subcommands && command.subcommands.length > 0) {\n const sub = command.subcommands.find((c) => c.name === rest[1]);\n if (sub) {\n command = sub;\n pathParts.push(sub.name);\n argsStart = 2;\n }\n }\n }\n\n if (rest.length === 0 || (flags.help && command === undefined)) {\n io.emit(renderRootHelp(deps.version, deps.commands), {\n version: deps.version,\n commands: deps.commands.map((c) => ({ name: c.name, summary: c.summary })),\n });\n return EXIT.OK;\n }\n\n if (command === undefined) {\n io.errline(`birdybeep: unknown command \"${rest[0]}\". Run \\`birdybeep --help\\`.`);\n return EXIT.USAGE;\n }\n\n const path = pathParts.join(\" \");\n if (flags.help) {\n io.emit(renderCommandHelp(path, command), {\n name: path,\n summary: command.summary,\n usage: command.usage,\n subcommands: command.subcommands?.map((c) => ({ name: c.name, summary: c.summary })),\n });\n return EXIT.OK;\n }\n\n if (command.run === undefined) {\n // A pure command group invoked without a subcommand → show its help as a usage error.\n io.errline(renderCommandHelp(path, command));\n return EXIT.USAGE;\n }\n\n const args = rest.slice(argsStart);\n const unknown = args.find(isUnknownFlag);\n if (unknown !== undefined) {\n io.errline(`birdybeep ${path}: unknown option \"${unknown}\".`);\n return EXIT.USAGE;\n }\n\n let code: number;\n try {\n code = await command.run({ args, flags, io });\n } catch (err) {\n if (err instanceof MissingInputError) {\n io.errline(\n `birdybeep ${path}: ${err.message} (re-run without --non-interactive to be prompted).`,\n );\n return EXIT.USAGE;\n }\n io.errline(`birdybeep ${path}: ${err instanceof Error ? err.message : String(err)}`);\n return EXIT.ERROR;\n }\n\n // Opportunistic, best-effort update notice (never alters the command's exit code or stdout).\n if (deps.notifyUpdate !== undefined) {\n try {\n await deps.notifyUpdate({ command: pathParts[0] ?? \"\", flags, io });\n } catch {\n /* the notifier is best-effort; a failure must not affect the command result */\n }\n }\n return code;\n}\n","/**\n * CLI version — single-sourced from package.json at build time (s0o7). `tsup.config.ts`\n * injects the real `@birdybeep/cli` version via the `__CLI_VERSION__` esbuild define, so\n * the shipped binary reports its true version for `--version` and the `cli_version` it\n * sends on `/pair/start` (the mobile approval sheet's machine identity). The `0.0.0`\n * fallback only applies to non-bundled runs (vitest / tsx), where the define is absent.\n */\n\n/** Build-time-replaced global; declared so source typechecks before tsup substitutes it. */\ndeclare const __CLI_VERSION__: string | undefined;\n\nexport const CLI_VERSION: string =\n typeof __CLI_VERSION__ === \"string\" && __CLI_VERSION__.length > 0 ? __CLI_VERSION__ : \"0.0.0\";\n","/**\n * `birdybeep agent install|uninstall [all|claude|codex|opencode]` (§7.3, §9.4) — the\n * once-per-machine setup half: detect supported harnesses and run each adapter's\n * idempotent, non-destructive install/uninstall. Adds ONLY BirdyBeep-managed entries\n * (existing config backed up + preserved), the installed config invokes\n * `birdybeep hook <harness>`, and NO durable token is ever written into harness/repo\n * config — the hook reads the token from the secure store at runtime. Prints the changed\n * files + any required user action (Codex `/hooks` trust, OpenCode restart).\n *\n * Built as a factory with an injectable adapter set so tests exercise the REAL adapter\n * installs under a temp HOME with deterministic detection.\n */\nimport type { AgentAdapter, InstallResult } from \"@birdybeep/agent-core\";\nimport { claudeCodeAdapter } from \"@birdybeep/claude-code\";\nimport { codexAdapter } from \"@birdybeep/codex\";\nimport { opencodeAdapter } from \"@birdybeep/opencode\";\n\nimport { type Command, type CommandContext, EXIT } from \"../framework\";\n\nconst DEFAULT_ADAPTERS: AgentAdapter[] = [claudeCodeAdapter, codexAdapter, opencodeAdapter];\n\n/** CLI short target name → adapter id (the CLI says `claude`, the adapter id is `claude_code`). */\nconst TARGET_TO_ID: Record<string, string> = {\n claude: \"claude_code\",\n codex: \"codex\",\n opencode: \"opencode\",\n};\n\nexport const AGENT_TARGETS: readonly string[] = [\"all\", \"claude\", \"codex\", \"opencode\"];\n\n/** Resolve a target to the adapter(s) it names, or `\"unknown\"` for a bad target. */\nexport function selectAdapters(\n target: string,\n adapters: AgentAdapter[],\n): AgentAdapter[] | \"unknown\" {\n if (target === \"all\") return adapters;\n const id = TARGET_TO_ID[target];\n if (id === undefined) return \"unknown\";\n return adapters.filter((a) => a.id === id);\n}\n\ninterface InstallOutcome {\n harness: string;\n displayName: string;\n detected: boolean;\n status?: InstallResult[\"status\"];\n changedFiles?: string[];\n backupFiles?: string[];\n requiredActions?: string[];\n}\n\nasync function installSelected(adapters: AgentAdapter[], ctx: CommandContext): Promise<number> {\n const target = ctx.args[0] ?? \"all\";\n const selected = selectAdapters(target, adapters);\n if (selected === \"unknown\") {\n ctx.io.errline(\n `birdybeep agent install: unknown target \"${target}\" (expected ${AGENT_TARGETS.join(\"|\")}).`,\n );\n return EXIT.USAGE;\n }\n\n const outcomes: InstallOutcome[] = [];\n for (const adapter of selected) {\n const detection = await adapter.detect();\n if (!detection.detected) {\n outcomes.push({ harness: adapter.id, displayName: adapter.displayName, detected: false });\n continue;\n }\n const result = await adapter.install();\n outcomes.push({\n harness: adapter.id,\n displayName: adapter.displayName,\n detected: true,\n status: result.status,\n changedFiles: result.changedFiles,\n backupFiles: result.backupFiles,\n requiredActions: result.requiredActions,\n });\n }\n\n if (ctx.flags.json) {\n ctx.io.result({ target, results: outcomes });\n return EXIT.OK;\n }\n\n if (outcomes.length === 0 || outcomes.every((o) => !o.detected)) {\n ctx.io.line(\"No supported harnesses detected — nothing to install.\");\n }\n for (const o of outcomes) {\n if (!o.detected) {\n ctx.io.line(`– ${o.displayName}: not detected (skipped)`);\n continue;\n }\n const changed = (o.changedFiles ?? []).length > 0 ? o.changedFiles!.join(\", \") : \"no changes\";\n ctx.io.line(`✓ ${o.displayName}: ${o.status} (${changed})`);\n for (const action of o.requiredActions ?? []) ctx.io.line(` → ${action}`);\n }\n return EXIT.OK;\n}\n\ninterface UninstallOutcome {\n harness: string;\n displayName: string;\n changed: boolean;\n removedFiles: string[];\n restoredFiles: string[];\n}\n\nasync function uninstallSelected(adapters: AgentAdapter[], ctx: CommandContext): Promise<number> {\n const target = ctx.args[0] ?? \"all\";\n const selected = selectAdapters(target, adapters);\n if (selected === \"unknown\") {\n ctx.io.errline(\n `birdybeep agent uninstall: unknown target \"${target}\" (expected ${AGENT_TARGETS.join(\"|\")}).`,\n );\n return EXIT.USAGE;\n }\n\n const outcomes: UninstallOutcome[] = [];\n for (const adapter of selected) {\n // Uninstall is safe + idempotent even if nothing is installed (a no-op).\n const result = await adapter.uninstall();\n outcomes.push({\n harness: adapter.id,\n displayName: adapter.displayName,\n changed: result.changed,\n removedFiles: result.removedFiles,\n restoredFiles: result.restoredFiles,\n });\n }\n\n if (ctx.flags.json) {\n ctx.io.result({ target, results: outcomes });\n return EXIT.OK;\n }\n for (const o of outcomes) {\n if (!o.changed) {\n ctx.io.line(`– ${o.displayName}: nothing to remove`);\n continue;\n }\n const touched = [...o.removedFiles, ...o.restoredFiles].join(\", \") || \"config restored\";\n ctx.io.line(`✓ ${o.displayName}: removed (${touched})`);\n }\n return EXIT.OK;\n}\n\nexport interface AgentCommandDeps {\n /** Adapter set (tests inject deterministic detection). Defaults to the three real adapters. */\n adapters?: AgentAdapter[];\n}\n\n/** Build the `agent` command group (install + uninstall, both via the adapter contract). */\nexport function createAgentCommand(deps: AgentCommandDeps = {}): Command {\n const adapters = deps.adapters ?? DEFAULT_ADAPTERS;\n return {\n name: \"agent\",\n summary: \"Install or uninstall harness adapters\",\n usage: \"birdybeep agent <install|uninstall> [all|claude|codex|opencode]\",\n subcommands: [\n {\n name: \"install\",\n summary: \"Install adapters (all | claude | codex | opencode)\",\n usage: \"birdybeep agent install [all|claude|codex|opencode]\",\n run: (ctx) => installSelected(adapters, ctx),\n },\n {\n name: \"uninstall\",\n summary: \"Restore harness config to its pre-install state\",\n usage: \"birdybeep agent uninstall [all|claude|codex|opencode]\",\n run: (ctx) => uninstallSelected(adapters, ctx),\n },\n ],\n };\n}\n","/**\n * `birdybeep doctor` (§9.4, §21.1–21.2) — the self-service troubleshooter. Runs a battery\n * of checks (machine token, each adapter's doctor() incl. needs_trust/needs_restart/error,\n * local queue health, backend reachability), prints a concrete copy-pasteable fix for each\n * failure, drains the queue opportunistically, and exits non-zero when anything fails so\n * it's CI/script friendly. Read-only (never mutates harness config); never prints token\n * material or notification bodies. `--json` mirrors all findings.\n */\nimport {\n type AgentAdapter,\n createSender as defaultCreateSender,\n type Sender,\n type TokenStoreOptions,\n} from \"@birdybeep/agent-core\";\nimport { claudeCodeAdapter } from \"@birdybeep/claude-code\";\nimport { codexAdapter } from \"@birdybeep/codex\";\nimport { opencodeAdapter } from \"@birdybeep/opencode\";\n\nimport { resolveApiUrl } from \"../config\";\nimport { isPaired, localQueueDepth } from \"../diagnostics\";\nimport { type Command, EXIT } from \"../framework\";\n\nconst DEFAULT_ADAPTERS: AgentAdapter[] = [claudeCodeAdapter, codexAdapter, opencodeAdapter];\n\ninterface Check {\n name: string;\n ok: boolean;\n detail?: string;\n remedy?: string;\n}\n\n/** Best-effort backend reachability probe (HEAD; any non-5xx response = reachable). */\nasync function defaultProbeNetwork(baseUrl: string): Promise<boolean> {\n try {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), 3000);\n if (typeof timer.unref === \"function\") timer.unref();\n const res = await fetch(baseUrl, { method: \"HEAD\", signal: controller.signal });\n clearTimeout(timer);\n return res.status < 500;\n } catch {\n return false;\n }\n}\n\nexport interface DoctorCommandDeps {\n adapters?: AgentAdapter[];\n createSender?: (baseUrl: string) => Sender;\n tokenOptions?: TokenStoreOptions;\n /** Backend reachability probe (tests inject reachable/unreachable). */\n probeNetwork?: (baseUrl: string) => Promise<boolean>;\n}\n\nexport function createDoctorCommand(deps: DoctorCommandDeps = {}): Command {\n const adapters = deps.adapters ?? DEFAULT_ADAPTERS;\n const probeNetwork = deps.probeNetwork ?? defaultProbeNetwork;\n const makeSender =\n deps.createSender ??\n ((baseUrl) =>\n defaultCreateSender(\n deps.tokenOptions ? { baseUrl, tokenOptions: deps.tokenOptions } : { baseUrl },\n ));\n\n return {\n name: \"doctor\",\n summary: \"Diagnose token, trust, restart, and offline-queue issues\",\n usage: \"birdybeep doctor [--json]\",\n run: async (ctx) => {\n const checks: Check[] = [];\n const apiUrl = resolveApiUrl();\n\n // 1. Machine token.\n const paired = await isPaired(deps.tokenOptions ?? {});\n checks.push(\n paired\n ? { name: \"Machine token\", ok: true }\n : {\n name: \"Machine token\",\n ok: false,\n detail: \"No machine token found.\",\n remedy: \"Run `birdybeep pair` to pair this machine.\",\n },\n );\n\n // 2. Each adapter's own diagnostics (detected? installed? needs_trust/needs_restart/error?).\n for (const adapter of adapters) {\n const result = await adapter.doctor();\n for (const c of result.checks) {\n checks.push({\n name: `${adapter.displayName}: ${c.name}`,\n ok: c.ok,\n ...(c.detail !== undefined ? { detail: c.detail } : {}),\n ...(c.remedy !== undefined ? { remedy: c.remedy } : {}),\n });\n }\n }\n\n // 3. Local queue: drain opportunistically, report depth.\n const depthBefore = localQueueDepth();\n const drain = await makeSender(apiUrl).drainNow();\n const depthAfter = localQueueDepth();\n checks.push({\n name: \"Local queue\",\n ok: true,\n detail: `${depthBefore} queued → ${drain.delivered} delivered, ${depthAfter} remaining`,\n });\n\n // 4. Backend reachability.\n const reachable = await probeNetwork(apiUrl);\n checks.push(\n reachable\n ? { name: \"Backend reachable\", ok: true }\n : {\n name: \"Backend reachable\",\n ok: false,\n detail: `Could not reach ${apiUrl}.`,\n remedy: \"Check your network; queued events will retry automatically.\",\n },\n );\n\n const ok = checks.every((c) => c.ok);\n\n if (ctx.flags.json) {\n ctx.io.result({\n ok,\n checks,\n queue: { depthBefore, delivered: drain.delivered, depthAfter },\n });\n } else {\n for (const c of checks) {\n ctx.io.line(`${c.ok ? \"✓\" : \"✗\"} ${c.name}${c.detail ? ` — ${c.detail}` : \"\"}`);\n if (!c.ok && c.remedy) ctx.io.line(` → ${c.remedy}`);\n }\n ctx.io.line(ok ? \"\\nAll checks passed.\" : \"\\nSome checks failed — see fixes above.\");\n }\n return ok ? EXIT.OK : EXIT.ERROR;\n },\n };\n}\n","/**\n * Non-secret CLI config (§9.4): a small `config.json` in the BirdyBeep user config dir\n * holding things like the API base URL. The machine TOKEN never lives here — it is read\n * exclusively from the secure token store (keychain / strict-perm file). Tolerant readers:\n * a missing/corrupt config falls back to defaults rather than crashing the hot path.\n */\nimport { mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport { birdyBeepConfigDir } from \"@birdybeep/agent-core\";\n\n/** Default backend base URL (overridable via env or `birdybeep pair`; finalized in a-release). */\nexport const DEFAULT_API_URL = \"https://api.birdybeep.com\";\nexport const CONFIG_FILE = \"config.json\";\n\nexport interface CliConfig {\n /** Backend base URL (set by `pair`); never holds a token. */\n apiUrl?: string;\n}\n\nexport function cliConfigPath(): string {\n return join(birdyBeepConfigDir(), CONFIG_FILE);\n}\n\n/** Read the CLI config; returns `{}` on a missing/unreadable/corrupt file (never throws). */\nexport function readCliConfig(): CliConfig {\n try {\n const parsed: unknown = JSON.parse(readFileSync(cliConfigPath(), \"utf8\"));\n return typeof parsed === \"object\" && parsed !== null ? parsed : {};\n } catch {\n return {};\n }\n}\n\n/**\n * Merge + persist non-secret CLI config (strict-perm dir). Only the KNOWN non-secret keys\n * are ever written — anything else (e.g. a token someone passed by mistake) is dropped, so\n * the token can only ever live in the secure store, never here.\n */\nexport function writeCliConfig(patch: CliConfig): void {\n const current = readCliConfig();\n const merged: CliConfig = {};\n const apiUrl = patch.apiUrl ?? current.apiUrl;\n if (apiUrl !== undefined) merged.apiUrl = apiUrl;\n mkdirSync(birdyBeepConfigDir(), { recursive: true, mode: 0o700 });\n writeFileSync(cliConfigPath(), `${JSON.stringify(merged, null, 2)}\\n`, { mode: 0o600 });\n}\n\n/** Resolve the backend base URL: `BIRDYBEEP_API_URL` env → CLI config → default. */\nexport function resolveApiUrl(): string {\n const env = process.env[\"BIRDYBEEP_API_URL\"];\n if (env !== undefined && env.length > 0) return env;\n return readCliConfig().apiUrl ?? DEFAULT_API_URL;\n}\n\n/** Public npm registry — where `@birdybeep/cli` is published; used by the update notifier. */\nexport const DEFAULT_REGISTRY_URL = \"https://registry.npmjs.org\";\n\n/**\n * Resolve the npm registry base URL for the passive update check: honor `npm_config_registry`\n * (which npm/pnpm/yarn export, so a private-registry user's mirror is respected) and fall back to\n * the public registry. Never carries auth or a token.\n */\nexport function resolveRegistryUrl(): string {\n const env = process.env[\"npm_config_registry\"];\n if (env !== undefined && env.length > 0) return env;\n return DEFAULT_REGISTRY_URL;\n}\n","/**\n * Shared status/queue plumbing used by `birdybeep status` and `birdybeep doctor`: gather\n * each adapter's integration status, the machine identity + pairing state, and local queue\n * depth. Read-only + privacy-safe — never prints token material or notification bodies.\n */\nimport {\n type AgentAdapter,\n getMachineIdentity,\n getToken,\n type IntegrationStatus,\n LocalEventQueue,\n type TokenStoreOptions,\n} from \"@birdybeep/agent-core\";\n\nexport interface IntegrationState {\n harness: string;\n displayName: string;\n status: IntegrationStatus;\n}\n\n/** Each adapter's current §8.8 integration status (runs the real adapter.status()). */\nexport async function gatherIntegrations(adapters: AgentAdapter[]): Promise<IntegrationState[]> {\n return Promise.all(\n adapters.map(async (a) => ({\n harness: a.id,\n displayName: a.displayName,\n status: await a.status(),\n })),\n );\n}\n\n/** Is a machine token present in the secure store? (pairing state — never prints the token.) */\nexport async function isPaired(tokenOptions: TokenStoreOptions = {}): Promise<boolean> {\n return (await getToken(tokenOptions)) !== null;\n}\n\n/** Current local event-queue depth (fresh, non-expired entries). */\nexport function localQueueDepth(): number {\n return new LocalEventQueue().size();\n}\n\n/** Machine label + OS (the event `machine` identity). */\nexport function machineIdentity(): { label: string; os: string } {\n return getMachineIdentity();\n}\n","/**\n * `birdybeep hook <claude|codex|opencode>` (§9.2–9.3) — the hot-path entrypoint every\n * installed adapter config invokes when its harness fires a lifecycle event. It reads the\n * raw payload (from the trailing arg for Codex's notify argv, else from stdin), selects the\n * named harness's `runXHook` (normalize → redact/hash/truncate → dedup → send w/ short\n * timeout → queue-on-fail → opportunistic drain → fast return), and ALWAYS exits 0 so it\n * never errors the harness. The token is read by the sender from the secure store — never\n * from config — and notification content is never persisted (the adapters' normalizers\n * enforce that).\n *\n * Built as a factory so the sender + stdin reader are injectable: tests drive the full\n * dispatch → command → pipeline → stub-sink path hermetically, exactly like the adapter E2Es.\n */\nimport {\n createSender as defaultCreateSender,\n type HookResult,\n type Sender,\n} from \"@birdybeep/agent-core\";\nimport { runClaudeHook } from \"@birdybeep/claude-code\";\nimport { runCodexHook } from \"@birdybeep/codex\";\nimport { runOpenCodeHook } from \"@birdybeep/opencode\";\n\nimport { resolveApiUrl } from \"../config\";\nimport { type Command, EXIT } from \"../framework\";\n\nexport type HarnessName = \"claude\" | \"codex\" | \"opencode\";\n\ntype HarnessRunner = (input: unknown, options: { sender: Sender }) => Promise<HookResult>;\n\nconst RUNNERS: Record<HarnessName, HarnessRunner> = {\n claude: runClaudeHook,\n codex: runCodexHook,\n opencode: runOpenCodeHook,\n};\n\nexport const HOOK_HARNESSES: readonly HarnessName[] = [\"claude\", \"codex\", \"opencode\"];\n\n/**\n * Hard cap on reading the payload — a misbehaving harness must never hang the hook.\n * 3s (was 2s, erm): a loaded machine can be slow to flush a pipe, and a timeout here\n * silently DROPS the event (\"skipped\"). BUDGET MATH: this cap and the sender's\n * DEFAULT_TOTAL_BUDGET_MS (5s) run SEQUENTIALLY and must sum comfortably under the 10s\n * hook timeout the adapters register, leaving headroom for Node startup — 3s + 5s + ~1s\n * startup < 10s. (5s + 5s summed to exactly the timeout: a slow start got the hook\n * SIGKILLed mid-send, which skips the queue-on-failure catch and loses the event.)\n */\nexport const STDIN_READ_TIMEOUT_MS = 3000;\n\n/** Resolve to `fallback` if `promise` does not settle within `ms` (the timer is unref'd). */\nfunction withTimeout<T>(promise: Promise<T>, ms: number, fallback: T): Promise<T> {\n return new Promise<T>((resolve) => {\n let settled = false;\n const finish = (value: T): void => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n resolve(value);\n };\n const timer = setTimeout(() => finish(fallback), ms);\n if (typeof timer.unref === \"function\") timer.unref();\n void promise.then(finish, () => finish(fallback));\n });\n}\n\nexport function isHarnessName(value: string | undefined): value is HarnessName {\n return value === \"claude\" || value === \"codex\" || value === \"opencode\";\n}\n\n/** Run one hook fire: select the harness runner and execute via the shared pipeline. */\nexport function runHookCommand(\n harness: HarnessName,\n payload: unknown,\n sender: Sender,\n): Promise<HookResult> {\n return RUNNERS[harness](payload, { sender });\n}\n\n/** Read process.stdin to EOF (the harness pipes a small JSON then closes); never throws. */\nfunction readStdinDefault(): Promise<string> {\n return new Promise((resolve) => {\n if (process.stdin.isTTY) {\n resolve(\"\");\n return;\n }\n let data = \"\";\n process.stdin.setEncoding(\"utf8\");\n process.stdin.on(\"data\", (chunk: string) => (data += chunk));\n process.stdin.on(\"end\", () => resolve(data));\n process.stdin.on(\"error\", () => resolve(\"\"));\n });\n}\n\n/** Resolve the raw payload: the trailing arg (Codex notify argv) wins, else read stdin. */\nexport async function readHookPayload(\n args: string[],\n readStdin: () => Promise<string>,\n): Promise<string> {\n return args[1] ?? (await readStdin());\n}\n\nexport interface HookCommandDeps {\n /** Build the sender (default: agent-core `createSender` with the resolved API URL). */\n createSender?: (baseUrl: string) => Sender;\n /** Read the raw payload from stdin (default: real process.stdin). */\n readStdin?: () => Promise<string>;\n /** Hard cap on the payload read (default {@link STDIN_READ_TIMEOUT_MS}); tests shrink it. */\n stdinTimeoutMs?: number;\n}\n\n/** Build the `hook` command. Pure stubs aside, this is the live event path. */\nexport function createHookCommand(deps: HookCommandDeps = {}): Command {\n const makeSender = deps.createSender ?? ((baseUrl) => defaultCreateSender({ baseUrl }));\n const readStdin = deps.readStdin ?? readStdinDefault;\n const stdinTimeoutMs = deps.stdinTimeoutMs ?? STDIN_READ_TIMEOUT_MS;\n\n return {\n name: \"hook\",\n summary: \"Internal: normalize + send an event fired by a harness hook\",\n usage: \"birdybeep hook <claude|codex|opencode>\",\n run: async (ctx) => {\n const harness = ctx.args[0];\n if (!isHarnessName(harness)) {\n ctx.io.errline(`birdybeep hook: expected one of ${HOOK_HARNESSES.join(\"|\")}`);\n return EXIT.USAGE;\n }\n\n // Bounded read: the trailing argv payload resolves instantly; a hung/never-closing\n // stdin falls back to \"\" after the timeout so the hook ALWAYS returns fast (§9.3).\n const raw = await withTimeout(readHookPayload(ctx.args, readStdin), stdinTimeoutMs, \"\");\n let payload: unknown;\n try {\n payload = JSON.parse(raw);\n } catch {\n // Garbled/empty payload → skip silently + fast. Never error the harness.\n ctx.io.result({ harness, outcome: \"skipped\" });\n return EXIT.OK;\n }\n\n const sender = makeSender(resolveApiUrl());\n const result = await runHookCommand(harness, payload, sender);\n // Hot path: human mode is silent; --json emits the outcome for scripts/debugging.\n ctx.io.result({ harness, outcome: result.outcome, eventType: result.eventType });\n return EXIT.OK; // delivered/queued/deduped/skipped all return fast + non-erroring\n },\n };\n}\n","/**\n * `birdybeep logout` / `birdybeep unpair` (§9.4) — remove the local machine token from BOTH\n * the OS keychain and the strict-perm file fallback. `unpair` is the pairing-vocabulary twin\n * of `pair` and `logout` is the familiar sign-out verb; they are the SAME operation, so both\n * are offered. Idempotent (no error when already signed out). Does NOT touch harness\n * integration config (that is `agent uninstall`) or the local queue.\n */\nimport { clearToken, type TokenStoreOptions } from \"@birdybeep/agent-core\";\n\nimport { type Command, EXIT } from \"../framework\";\n\nexport interface LogoutCommandDeps {\n /** Token-store options (tests inject the file fallback). */\n tokenOptions?: TokenStoreOptions;\n}\n\n/**\n * Build a token-clearing command. `logout` and `unpair` share this one handler — only the\n * command name, help copy, and the human/JSON confirmation differ.\n */\nfunction createClearTokenCommand(\n spec: { name: \"logout\" | \"unpair\"; summary: string; humanMessage: string; jsonKey: string },\n deps: LogoutCommandDeps = {},\n): Command {\n return {\n name: spec.name,\n summary: spec.summary,\n usage: `birdybeep ${spec.name}`,\n run: async (ctx) => {\n await clearToken(deps.tokenOptions ?? {});\n ctx.io.emit(spec.humanMessage, { [spec.jsonKey]: true });\n return EXIT.OK;\n },\n };\n}\n\nexport function createLogoutCommand(deps: LogoutCommandDeps = {}): Command {\n return createClearTokenCommand(\n {\n name: \"logout\",\n summary: \"Remove the local machine token (same as `unpair`)\",\n humanMessage: \"Logged out — the machine token was removed.\",\n jsonKey: \"loggedOut\",\n },\n deps,\n );\n}\n\nexport function createUnpairCommand(deps: LogoutCommandDeps = {}): Command {\n return createClearTokenCommand(\n {\n name: \"unpair\",\n summary: \"Unpair this machine — remove the local machine token (same as `logout`)\",\n humanMessage: \"Unpaired — the machine token was removed.\",\n jsonKey: \"unpaired\",\n },\n deps,\n );\n}\n","/**\n * `birdybeep pair` (§7.1/§7.2/§9.4) — pair this machine via the device-code flow.\n * `POST /v1/pair/start` (machine_label derived from hostname/OS) → show a scannable\n * QR matrix + the pair link + `user_code` → poll `POST /v1/pair/token` with the device\n * code (+ stable machine fingerprint) until it returns the durable token or the\n * `expires_at` (10-min) deadline. The issued token is stored in the SECURE store only\n * (keychain / strict-perm file — never config or the QR); the non-secret apiUrl is\n * persisted. Per SPEC §11 the QR/code carries only short-lived pairing info.\n *\n * The QR matrix (birdybeep-agent-pe1) renders only on an interactive TTY — piped/CI\n * output keeps the plain link + code lines, which are ALWAYS printed as the SSH/\n * headless fallback (docs/pairing.md \"Headless and SSH machines\"). In `--json` mode\n * the pairing info is emitted as an NDJSON line up front (status \"pairing_started\")\n * so scripts/agents can read the code and approve — previously json mode printed\n * nothing until success, making scripted pairing impossible (birdybeep-agent-pe1).\n *\n * fetch/sleep/clock/QR/TTY are injectable for hermetic tests.\n */\nimport { getMachineIdentity, setToken, type TokenStoreOptions } from \"@birdybeep/agent-core\";\n// uqr is the CLI's ONLY third-party runtime dep (MIT, itself zero-dependency), pinned\n// EXACTLY in package.json: QR encoding (Reed–Solomon + masking) is too error-prone to\n// vendor, and a floating range would defeat the small-auditable-supply-chain goal (§16.4).\nimport { renderUnicodeCompact } from \"uqr\";\n\nimport { resolveApiUrl, writeCliConfig } from \"../config\";\nimport { type Command, EXIT } from \"../framework\";\nimport { pairStart, pairTokenPoll, type PairTokenResult } from \"../pairing\";\nimport { CLI_VERSION } from \"../version\";\n\n/** Default delay between `/pair/token` polls (the start response has no interval). */\nexport const DEFAULT_POLL_INTERVAL_MS = 2000;\n\n/**\n * How often to reprint a \"still waiting…\" heartbeat while polling. Without it, `pair`\n * prints the code once and then appears frozen (\"stuck doing nothing\") for the whole\n * 10-minute window — the reported bug. Time-gated on the injected clock so it never\n * fires spuriously in the fast, instant-sleep tests.\n */\nexport const HEARTBEAT_MS = 15_000;\n\n/**\n * Render the QR payload as a terminal-scannable half-block matrix. `border: 2` keeps a\n * quiet zone around the symbol (phone cameras misread flush-against-text QRs).\n */\nexport function renderQrMatrix(qrPayload: string): string {\n return renderUnicodeCompact(qrPayload, { border: 2 });\n}\n\nexport interface PairCommandDeps {\n fetchImpl?: typeof fetch;\n tokenOptions?: TokenStoreOptions;\n /** Injectable delay between polls (default real setTimeout; tests make it instant). */\n sleep?: (ms: number) => Promise<void>;\n /** Injectable clock for the expiry deadline (default Date.now). */\n now?: () => number;\n /** Render the QR payload as a matrix (default {@link renderQrMatrix} via uqr). */\n renderQr?: (qrPayload: string) => string;\n /** Whether stdout is an interactive terminal (default process.stdout.isTTY). The QR\n * matrix renders only on a TTY — piped output stays plain text. */\n isTTY?: boolean;\n pollIntervalMs?: number;\n}\n\nexport function createPairCommand(deps: PairCommandDeps = {}): Command {\n const fetchImpl = deps.fetchImpl ?? fetch;\n const sleep = deps.sleep ?? ((ms: number) => new Promise<void>((r) => setTimeout(r, ms)));\n const clock = deps.now ?? (() => Date.now());\n const renderQr = deps.renderQr ?? renderQrMatrix;\n const intervalMs = deps.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS;\n\n return {\n name: \"pair\",\n summary: \"Pair this machine with your BirdyBeep account (QR or manual)\",\n usage: \"birdybeep pair [--json]\",\n run: async (ctx) => {\n const apiUrl = resolveApiUrl();\n const identity = getMachineIdentity(); // { label, os, fingerprintHash }\n const start = await pairStart(\n apiUrl,\n { machineLabel: identity.label, os: identity.os, cliVersion: CLI_VERSION },\n fetchImpl,\n );\n\n if (ctx.flags.json) {\n // NDJSON: emit the pairing info NOW so a script/agent can surface the code for\n // approval while we poll; the final success object is a later line (pe1).\n ctx.io.result({\n status: \"pairing_started\",\n user_code: start.user_code,\n qr_payload: start.qr_payload,\n expires_at: start.expires_at,\n });\n } else {\n // Point at the RELIABLE path: the in-app scanner. Opening the https link only\n // reaches the approval screen where universal/app links are configured; scanning\n // (or typing the code) in the app always works, so lead with that.\n ctx.io.line(\n \"To pair this machine, open the BirdyBeep app, tap “pair a machine”, and scan this QR (or enter the code):\",\n );\n // The matrix is TTY-only (a piped/CI consumer wants greppable lines, and\n // half-block art garbles logs); the link + code lines below ALWAYS print.\n const isTTY = deps.isTTY ?? process.stdout.isTTY === true;\n if (isTTY) ctx.io.line(renderQr(start.qr_payload));\n ctx.io.line(` Scan or open: ${start.qr_payload}`);\n ctx.io.line(` Code: ${start.user_code}`);\n ctx.io.line(\"Waiting for you to approve this machine in the app…\");\n }\n\n // Poll /pair/token until approved (201), a TERMINAL error, or the window expires.\n const deadline = Date.parse(start.expires_at);\n const startedAt = clock();\n let lastBeat = startedAt;\n let paired: PairTokenResult | undefined;\n let terminal: Extract<PairTokenResult, { status: \"error\" }> | undefined;\n for (;;) {\n const nowMs = clock();\n if (nowMs >= deadline) break;\n await sleep(intervalMs);\n const poll = await pairTokenPoll(\n apiUrl,\n start.device_code,\n fetchImpl,\n identity.fingerprintHash,\n );\n if (poll.status === \"paired\") {\n paired = poll;\n break;\n }\n // A failure that waiting can't fix (e.g. the agent-install cap) must STOP the loop\n // and be shown — never masked as \"not approved yet\" so the prompt hangs silently.\n if (poll.status === \"error\" && !poll.retryable) {\n terminal = poll;\n break;\n }\n // Otherwise pending (not approved yet) or a transient server error → keep waiting,\n // reprinting a heartbeat so the prompt is visibly alive. Human-mode only (NDJSON\n // stays a clean two-line stream); time-gated on the clock so tests never see it.\n if (!ctx.flags.json && nowMs - lastBeat >= HEARTBEAT_MS) {\n ctx.io.line(\n poll.status === \"error\"\n ? ` still trying — the server is busy (${poll.message}). approve in the app when you can…`\n : \" still waiting — approve this machine in the BirdyBeep app…\",\n );\n lastBeat = nowMs;\n }\n }\n\n if (terminal !== undefined) {\n // NDJSON: a terminal result object on stderr+stdout so scripts see the reason code.\n ctx.io.result({ paired: false, reason: terminal.code });\n ctx.io.errline(`Pairing failed: ${terminal.message}`);\n return EXIT.ERROR;\n }\n\n if (paired === undefined || paired.status !== \"paired\") {\n // NDJSON contract: json mode gets a TERMINAL result object on every exit path,\n // so scripts can key off the last parseable line instead of only the exit code.\n ctx.io.result({ paired: false, reason: \"timeout\" });\n ctx.io.errline(\n \"Pairing timed out before you approved it. In the BirdyBeep app, tap “pair a machine”, scan the QR (or enter the code), then run `birdybeep pair` again.\",\n );\n return EXIT.ERROR;\n }\n\n // Durable token → secure store ONLY. Non-secret apiUrl → config. Never the reverse.\n await setToken(paired.machineToken, deps.tokenOptions ?? {});\n writeCliConfig({ apiUrl });\n\n ctx.io.emit(`✓ Paired. Run \\`birdybeep test\\` to send a test Beep.`, {\n paired: true,\n machineId: paired.machineId,\n });\n return EXIT.OK;\n },\n };\n}\n","/**\n * CLI pairing client — the device-code flow (§7.2/§13.4). `pairStart` opens a session via\n * `POST /v1/pair/start`; the CLI shows `qr_payload` + `user_code`, then polls\n * `POST /v1/pair/token` (`pairTokenPoll`) until it returns 201 `{ machine_token, machine_id }`\n * or the `expires_at` deadline. A `validation_failed`/4xx during polling means \"not approved\n * yet — keep polling\". Per SPEC §11 the QR / user code carries only short-lived pairing info,\n * NEVER a durable token. Request/response shapes are mirrored from the product (agent-core).\n */\nimport {\n type ErrorCode,\n errorEnvelopeSchema,\n type PairStartResponse,\n pairStartResponseSchema,\n pairTokenResponseSchema,\n} from \"@birdybeep/agent-core\";\n\nfunction base(apiUrl: string): string {\n return apiUrl.replace(/\\/$/, \"\");\n}\n\nexport interface PairStartInput {\n /** Required — the human machine label (derived from hostname/OS). */\n machineLabel: string;\n os?: string;\n cliVersion?: string;\n}\n\n/** Begin a pairing session (`POST /v1/pair/start`, unauthenticated). */\nexport async function pairStart(\n apiUrl: string,\n input: PairStartInput,\n fetchImpl: typeof fetch,\n): Promise<PairStartResponse> {\n const body = {\n machine_label: input.machineLabel,\n ...(input.os !== undefined ? { os: input.os } : {}),\n ...(input.cliVersion !== undefined ? { cli_version: input.cliVersion } : {}),\n };\n const res = await fetchImpl(`${base(apiUrl)}/v1/pair/start`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n if (!res.ok) throw new Error(`pairing could not be started (HTTP ${res.status})`);\n const parsed = pairStartResponseSchema.safeParse(await res.json());\n if (!parsed.success) throw new Error(\"pairing start returned an unexpected response shape\");\n return parsed.data;\n}\n\nexport type PairTokenResult =\n | { status: \"pending\" }\n | { status: \"paired\"; machineToken: string; machineId: string }\n /**\n * The backend returned an outcome that will NOT resolve by waiting (`retryable: false`,\n * e.g. `quota_exceeded` — the install cap is hit) or a transient server-side failure\n * (`retryable: true`, e.g. `internal_error`/5xx). Surfacing these is what stops `pair`\n * from masking a real error as \"not approved yet\" and hanging silently until timeout.\n */\n | { status: \"error\"; code: ErrorCode | \"unknown\"; message: string; retryable: boolean };\n\n/**\n * Terminal error codes on `/v1/pair/token`: waiting can never turn them into a 201, so the\n * CLI must STOP polling and show the user the reason. `quota_exceeded` (the agent-install cap)\n * is the one a real user actually hits; the auth-shaped codes should never occur on this\n * unauthenticated endpoint but are treated as terminal defensively (never loop forever).\n */\nconst TERMINAL_TOKEN_ERRORS: ReadonlySet<ErrorCode> = new Set<ErrorCode>([\n \"quota_exceeded\",\n \"unauthorized\",\n \"forbidden\",\n \"token_revoked\",\n \"not_found\",\n \"payload_too_large\",\n]);\n\n/**\n * Poll once for the device token (`POST /v1/pair/token`, unauthenticated). Outcomes:\n * - 201 with a valid token body → `paired`.\n * - `validation_failed`/4xx (the documented \"not approved yet\" signal) → `pending`, so the\n * caller keeps polling until the `expires_at` deadline.\n * - a TERMINAL error (e.g. `quota_exceeded`) → `error` with `retryable: false` — the caller\n * surfaces it and stops, instead of hanging silently on a failure waiting can't fix.\n * - `rate_limited`/`internal_error`/5xx/unparseable → `error` with `retryable: true` — the\n * caller keeps polling (transient) but can warn if it persists.\n */\nexport async function pairTokenPoll(\n apiUrl: string,\n deviceCode: string,\n fetchImpl: typeof fetch,\n machineFingerprint?: string,\n): Promise<PairTokenResult> {\n const body = {\n device_code: deviceCode,\n ...(machineFingerprint !== undefined ? { machine_fingerprint: machineFingerprint } : {}),\n };\n const res = await fetchImpl(`${base(apiUrl)}/v1/pair/token`, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n });\n\n if (res.ok) {\n const parsed = pairTokenResponseSchema.safeParse(await res.json());\n if (!parsed.success) return { status: \"pending\" };\n return {\n status: \"paired\",\n machineToken: parsed.data.machine_token,\n machineId: parsed.data.machine_id,\n };\n }\n\n // Non-2xx: read the typed §13.4 error envelope to tell \"not approved yet\" (keep polling)\n // apart from a real failure the user must see. A body that isn't a parseable envelope falls\n // back to the status code.\n let errBody: unknown = null;\n try {\n errBody = await res.json();\n } catch {\n /* empty / non-JSON error body → classify by status below */\n }\n const env = errorEnvelopeSchema.safeParse(errBody);\n const code = env.success ? env.data.error.code : undefined;\n\n // \"not approved yet\" is the documented benign signal → keep polling. Also treat any\n // unclassifiable 4xx (except 429) as pending, preserving the endpoint's historical\n // accept-and-keep-waiting behavior.\n if (\n code === \"validation_failed\" ||\n (code === undefined && res.status >= 400 && res.status < 500 && res.status !== 429)\n ) {\n return { status: \"pending\" };\n }\n\n const message = env.success ? env.data.error.message : `pairing failed (HTTP ${res.status})`;\n if (code !== undefined && TERMINAL_TOKEN_ERRORS.has(code)) {\n return { status: \"error\", code, message, retryable: false };\n }\n // rate_limited / internal_error / any 5xx / unrecognized → transient; safe to keep polling.\n return { status: \"error\", code: code ?? \"unknown\", message, retryable: true };\n}\n","/**\n * `birdybeep queue clear` (§9.4) — debug maintenance: drop all locally-queued events. The\n * queue is best-effort (≤24h retention), so clearing it only discards pending retries; it\n * never touches harness config or the token. Reports how many entries were removed.\n */\nimport { LocalEventQueue } from \"@birdybeep/agent-core\";\n\nimport { type Command, EXIT } from \"../framework\";\n\nexport function createQueueCommand(): Command {\n return {\n name: \"queue\",\n summary: \"Local event-queue maintenance\",\n usage: \"birdybeep queue <clear>\",\n subcommands: [\n {\n name: \"clear\",\n summary: \"Clear the local offline event queue (debug)\",\n usage: \"birdybeep queue clear\",\n run: (ctx) => {\n const cleared = new LocalEventQueue().clear();\n ctx.io.emit(`Cleared ${cleared} queued event(s).`, { cleared });\n return EXIT.OK;\n },\n },\n ],\n };\n}\n","/**\n * `birdybeep report-status` (§7.3 step 7, §8.8, §21.2) — push each adapter's pre-event\n * integration status to the backend so the Machines/Integrations screen shows them BEFORE\n * any agent event fires. Sends ONE BATCHED `POST /v1/integrations/status` request\n * ({ integrations: [...] }, machine-token auth), parses the `{ integrations: [...] }`\n * response (surfacing the server's EFFECTIVE status, e.g. Codex → needs_trust), and parses\n * the mirrored error envelope: a 401/403 (unauthorized / forbidden / token_revoked) is\n * TERMINAL (exit non-zero), while offline / 5xx / rate_limit is \"deferred\" (surfaced, exit 0)\n * so it never blocks install.\n *\n * Request/response/error shapes are mirrored from the product (agent-core). fetch/adapters/\n * token injectable for hermetic tests; the live post is the deferred cross-repo follow-up.\n */\nimport {\n type AgentAdapter,\n errorEnvelopeSchema,\n getToken,\n type IntegrationStatusItem,\n integrationStatusResponseSchema,\n type TokenStoreOptions,\n} from \"@birdybeep/agent-core\";\nimport { CLAUDE_CODE_ADAPTER_VERSION, claudeCodeAdapter } from \"@birdybeep/claude-code\";\nimport { CODEX_ADAPTER_VERSION, codexAdapter } from \"@birdybeep/codex\";\nimport { OPENCODE_ADAPTER_VERSION, opencodeAdapter } from \"@birdybeep/opencode\";\n\nimport { resolveApiUrl } from \"../config\";\nimport { type Command, EXIT } from \"../framework\";\n\nconst DEFAULT_ADAPTERS: AgentAdapter[] = [claudeCodeAdapter, codexAdapter, opencodeAdapter];\n\n/** Per-harness BirdyBeep adapter version (the schema's optional `adapter_version`). */\nconst ADAPTER_VERSIONS: Record<string, string> = {\n claude_code: CLAUDE_CODE_ADAPTER_VERSION,\n codex: CODEX_ADAPTER_VERSION,\n opencode: OPENCODE_ADAPTER_VERSION,\n};\n\nconst base = (apiUrl: string): string => apiUrl.replace(/\\/$/, \"\");\n\nasync function gatherItems(adapters: AgentAdapter[]): Promise<IntegrationStatusItem[]> {\n return Promise.all(\n adapters.map(async (a) => {\n const [detection, status] = await Promise.all([a.detect(), a.status()]);\n const item: IntegrationStatusItem = { harness: a.id, status };\n if (detection.version !== undefined) item.harness_version = detection.version;\n const adapterVersion = ADAPTER_VERSIONS[a.id];\n if (adapterVersion !== undefined) item.adapter_version = adapterVersion;\n return item;\n }),\n );\n}\n\nexport interface ReportStatusCommandDeps {\n adapters?: AgentAdapter[];\n fetchImpl?: typeof fetch;\n tokenOptions?: TokenStoreOptions;\n}\n\nexport function createReportStatusCommand(deps: ReportStatusCommandDeps = {}): Command {\n const adapters = deps.adapters ?? DEFAULT_ADAPTERS;\n const fetchImpl = deps.fetchImpl ?? fetch;\n\n return {\n name: \"report-status\",\n summary: \"Internal: report integration status to the backend\",\n usage: \"birdybeep report-status [--json]\",\n run: async (ctx) => {\n const token = await getToken(deps.tokenOptions ?? {});\n if (token === null) {\n ctx.io.errline(\"No machine token — run `birdybeep pair` first.\");\n return EXIT.ERROR;\n }\n\n const items = await gatherItems(adapters);\n if (items.length === 0) {\n ctx.io.emit(\"No integrations to report.\", { outcome: \"reported\", integrations: [] });\n return EXIT.OK;\n }\n\n // The effective per-harness status to display; defaults to what we sent, overwritten by\n // the server's response when it 200s.\n let effective = items.map((i) => ({ harness: i.harness, status: i.status }));\n let outcome: \"reported\" | \"deferred\" | \"terminal\" = \"deferred\";\n let errorCode: string | undefined;\n\n try {\n const res = await fetchImpl(`${base(resolveApiUrl())}/v1/integrations/status`, {\n method: \"POST\",\n headers: { authorization: `Bearer ${token}`, \"content-type\": \"application/json\" },\n body: JSON.stringify({ integrations: items }),\n });\n if (res.ok) {\n outcome = \"reported\";\n const parsed = integrationStatusResponseSchema.safeParse(\n await res.json().catch(() => undefined),\n );\n if (parsed.success) {\n effective = parsed.data.integrations.map((i) => ({\n harness: i.harness,\n status: i.status,\n }));\n }\n } else {\n const env = errorEnvelopeSchema.safeParse(await res.json().catch(() => undefined));\n errorCode = env.success ? env.data.error.code : undefined;\n // The error CODE is the canonical terminal signal (auth failures); HTTP status is\n // only the fallback when the envelope didn't parse. Everything else → deferred.\n const terminal =\n errorCode !== undefined\n ? errorCode === \"unauthorized\" ||\n errorCode === \"forbidden\" ||\n errorCode === \"token_revoked\"\n : res.status === 401 || res.status === 403;\n outcome = terminal ? \"terminal\" : \"deferred\";\n }\n } catch {\n outcome = \"deferred\"; // offline / transport error → surfaced, not fatal\n }\n\n if (ctx.flags.json) {\n ctx.io.result({\n outcome,\n integrations: effective,\n ...(errorCode !== undefined ? { error: errorCode } : {}),\n });\n } else if (outcome === \"terminal\") {\n ctx.io.errline(\n `Report rejected (${errorCode ?? \"auth\"}) — your token may be revoked. Re-run \\`birdybeep pair\\`.`,\n );\n } else {\n for (const e of effective) {\n ctx.io.line(\n outcome === \"reported\"\n ? `✓ ${e.harness}: ${e.status} (reported)`\n : `• ${e.harness}: ${e.status} (deferred — backend unreachable)`,\n );\n }\n }\n\n // Terminal auth failure → non-zero; offline/deferred → 0 (must never block install).\n return outcome === \"terminal\" ? EXIT.ERROR : EXIT.OK;\n },\n };\n}\n","/**\n * `birdybeep status` (§9.3, §9.4) — a quick health snapshot: machine identity + pairing\n * state, per-harness integration status, and local queue depth, while opportunistically\n * draining the queue (best-effort, non-blocking) and reporting delivered-vs-remaining.\n * Exits non-zero when not paired so scripts can branch. `--json` mirrors everything.\n * Factory with injectable adapters/sender/token so tests run hermetically against a stub.\n */\nimport {\n type AgentAdapter,\n createSender as defaultCreateSender,\n type Sender,\n type TokenStoreOptions,\n} from \"@birdybeep/agent-core\";\nimport { claudeCodeAdapter } from \"@birdybeep/claude-code\";\nimport { codexAdapter } from \"@birdybeep/codex\";\nimport { opencodeAdapter } from \"@birdybeep/opencode\";\n\nimport { resolveApiUrl } from \"../config\";\nimport { gatherIntegrations, isPaired, localQueueDepth, machineIdentity } from \"../diagnostics\";\nimport { type Command, EXIT } from \"../framework\";\n\nconst DEFAULT_ADAPTERS: AgentAdapter[] = [claudeCodeAdapter, codexAdapter, opencodeAdapter];\n\nexport interface StatusCommandDeps {\n adapters?: AgentAdapter[];\n /** Build the drain sender (default: agent-core createSender at the resolved API URL). */\n createSender?: (baseUrl: string) => Sender;\n /** Token-store options (tests inject the file fallback). */\n tokenOptions?: TokenStoreOptions;\n}\n\nexport function createStatusCommand(deps: StatusCommandDeps = {}): Command {\n const adapters = deps.adapters ?? DEFAULT_ADAPTERS;\n const makeSender =\n deps.createSender ??\n ((baseUrl) =>\n defaultCreateSender(\n deps.tokenOptions ? { baseUrl, tokenOptions: deps.tokenOptions } : { baseUrl },\n ));\n\n return {\n name: \"status\",\n summary: \"Show pairing + per-harness integration status\",\n usage: \"birdybeep status [--json]\",\n run: async (ctx) => {\n const machine = machineIdentity();\n const paired = await isPaired(deps.tokenOptions ?? {});\n const integrations = await gatherIntegrations(adapters);\n const depthBefore = localQueueDepth();\n const drain = await makeSender(resolveApiUrl()).drainNow(); // opportunistic, best-effort\n const depthAfter = localQueueDepth();\n\n const report = {\n machine,\n paired,\n integrations,\n queue: { depthBefore, delivered: drain.delivered, depthAfter },\n };\n\n if (ctx.flags.json) {\n ctx.io.result(report);\n } else {\n ctx.io.line(`Machine: ${machine.label} (${machine.os})`);\n ctx.io.line(paired ? \"Paired: yes\" : \"Paired: no — run `birdybeep pair`\");\n ctx.io.line(\"Integrations:\");\n for (const i of integrations) ctx.io.line(` ${i.displayName}: ${i.status}`);\n ctx.io.line(\n `Queue: ${depthBefore} queued → ${drain.delivered} delivered, ${depthAfter} remaining`,\n );\n }\n return paired ? EXIT.OK : EXIT.ERROR; // not-paired → defined non-zero\n },\n };\n}\n","/**\n * `birdybeep test` (§7.1, §9.4) — send a representative test event through the REAL sender\n * path (normalize/redact/truncate → send w/ short timeout → queue-on-fail → opportunistic\n * drain) so a developer can confirm end-to-end delivery (and trigger a test Beep) right\n * after pairing. Not a mock — it exercises the production code path. Reports delivered vs\n * queued (offline) vs rejected; --json mirrors the outcome.\n *\n * Sends event_type \"test\" (9fh): the backend notifies it by default and exempts it from\n * the beep quota. (The old \"custom\" type is unconditionally suppressed by the §10.5\n * matrix — every test \"succeeded\" while no push could ever be sent.) The session id is\n * unique per run so back-to-back tests don't collapse in the backend's dedupe window,\n * and the CLI reports the backend's actual DECISION instead of assuming a beep.\n */\nimport { randomUUID } from \"node:crypto\";\n\nimport {\n type BirdyBeepAgentEvent,\n createSender as defaultCreateSender,\n getMachineIdentity,\n normalizeEvent,\n type NormalizeOptions,\n type Sender,\n type TokenStoreOptions,\n} from \"@birdybeep/agent-core\";\n\nimport { resolveApiUrl } from \"../config\";\nimport { type Command, EXIT } from \"../framework\";\n\n/** Build the canonical test event (event_type `test`, unique session per run). cwd is hashed by the normalizer. */\nexport function buildTestEvent(opts: NormalizeOptions = {}): BirdyBeepAgentEvent {\n const machine = getMachineIdentity();\n return normalizeEvent(\n {\n event_type: \"test\",\n status: \"running\",\n harness: \"claude_code\", // schema requires a harness; the \"test\" type distinguishes it\n // Unique per run: a repeat `birdybeep test` inside the backend's dedupe window must\n // still beep — a constant id made the second test silently \"deduped\" (9fh).\n source_session_id: `birdybeep-cli-test-${randomUUID()}`,\n machine: { label: machine.label, os: machine.os },\n workspace: { cwd: process.cwd() },\n title: \"BirdyBeep test event\",\n body: \"If you can see this, your machine is wired up correctly.\",\n metadata: { test: true },\n },\n opts,\n );\n}\n\nexport interface TestCommandDeps {\n createSender?: (baseUrl: string) => Sender;\n tokenOptions?: TokenStoreOptions;\n}\n\nexport function createTestCommand(deps: TestCommandDeps = {}): Command {\n const makeSender =\n deps.createSender ??\n ((baseUrl) =>\n defaultCreateSender(\n deps.tokenOptions ? { baseUrl, tokenOptions: deps.tokenOptions } : { baseUrl },\n ));\n\n return {\n name: \"test\",\n summary: \"Send a test event end-to-end\",\n usage: \"birdybeep test [--json]\",\n run: async (ctx) => {\n const event = buildTestEvent();\n const result = await makeSender(resolveApiUrl()).send(event); // real path; also drains the queue\n\n if (ctx.flags.json) {\n ctx.io.result({\n outcome: result.outcome,\n ...(result.status ? { status: result.status } : {}),\n ...(result.decision ? { decision: result.decision } : {}),\n });\n } else if (result.outcome === \"delivered\") {\n // The 202 body says what the backend DECIDED — \"delivered\" alone only means\n // \"accepted\". Claiming a beep that was suppressed is how 9fh went unnoticed.\n if (result.decision === \"notified\" || result.decision === undefined) {\n ctx.io.line(\"✓ Test event delivered — check your phone for a test Beep.\");\n } else if (result.decision === \"suppressed\") {\n ctx.io.line(\n \"⚠ The backend accepted the test event but suppressed the push — this machine \" +\n \"or integration is probably muted. Check mutes in the app, or run `birdybeep doctor`.\",\n );\n } else if (result.decision === \"deduped\") {\n ctx.io.line(\n \"⚠ The backend accepted the test event but folded it into a recent duplicate — \" +\n \"wait ~30s and run `birdybeep test` again.\",\n );\n } else {\n ctx.io.line(\n `⚠ The backend accepted the test event but decided \"${result.decision}\" — no push ` +\n \"was sent. Run `birdybeep doctor`.\",\n );\n }\n } else if (result.outcome === \"queued\") {\n ctx.io.line(\"• Offline — test event queued; it will deliver when you reconnect.\");\n } else {\n ctx.io.line(\"✗ Test event was rejected by the backend. Run `birdybeep doctor`.\");\n }\n\n // delivered + queued are non-failure (offline is by design); a hard reject is an error.\n return result.outcome === \"dropped\" ? EXIT.ERROR : EXIT.OK;\n },\n };\n}\n","/**\n * The `birdybeep` command registry (§9.4) — the command tree the framework dispatches.\n * Every command is a factory (`create*Command`) so its dependencies (adapters, sender,\n * token store, fetch, stdin) are injectable for hermetic tests; the framework (help /\n * flags / routing / config dir / exit codes) is command-independent.\n */\nimport { createAgentCommand } from \"./commands/agent\";\nimport { createDoctorCommand } from \"./commands/doctor\";\nimport { createHookCommand } from \"./commands/hook\";\nimport { createLogoutCommand, createUnpairCommand } from \"./commands/logout\";\nimport { createPairCommand } from \"./commands/pair\";\nimport { createQueueCommand } from \"./commands/queue\";\nimport { createReportStatusCommand } from \"./commands/report-status\";\nimport { createStatusCommand } from \"./commands/status\";\nimport { createTestCommand } from \"./commands/test\";\nimport { type Command } from \"./framework\";\n\n/** Build the full §9.4 command tree. */\nexport function buildCommands(): Command[] {\n return [\n createPairCommand(),\n createLogoutCommand(),\n createUnpairCommand(),\n createStatusCommand(),\n createTestCommand(),\n createDoctorCommand(),\n createAgentCommand(),\n createHookCommand(),\n createQueueCommand(),\n createReportStatusCommand(),\n ];\n}\n","/**\n * Passive update notifier (§9.4). Instead of a manual `update` command, the CLI opportunistically\n * checks the npm registry for a newer `@birdybeep/cli` and prints a subtle \"new version available\"\n * notice to **stderr** after an eligible command runs — so users learn about upgrades just by using\n * the tool. It is:\n *\n * - **Cached (TTL-gated):** the result is stored in the config dir and only refreshed from the\n * network once per {@link DEFAULT_CHECK_INTERVAL_MS}; every other run is a local file read.\n * - **Non-blocking to the hot path:** the `hook` command (which runs inside the harness and must\n * return fast) and the internal `report-status` command are skipped before any I/O.\n * - **Quiet for machines/scripts:** skipped under `--json`, `--non-interactive`, a non-TTY stderr,\n * `CI`, or the `NO_UPDATE_NOTIFIER` / `BIRDYBEEP_NO_UPDATE_NOTIFIER` opt-outs.\n * - **Best-effort & side-effect-free on the result:** it never throws, never changes stdout, and\n * never affects the command's exit code (registry/semver logic lives here, not in the framework).\n */\nimport { mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nimport { birdyBeepConfigDir } from \"@birdybeep/agent-core\";\n\nimport { resolveRegistryUrl } from \"./config\";\nimport { type GlobalFlags, type Io } from \"./framework\";\nimport { CLI_VERSION } from \"./version\";\n\n/** The published package the notice points at. */\nexport const PACKAGE_NAME = \"@birdybeep/cli\";\n/** URL-encoded scoped path for the registry `latest` dist-tag endpoint. */\nconst PACKAGE_PATH = \"@birdybeep%2Fcli\";\n/** Cache file (non-secret) in the BirdyBeep config dir. */\nexport const UPDATE_CACHE_FILE = \"update-check.json\";\n/** Refresh the registry at most once per this window; every other run reads the cache. */\nexport const DEFAULT_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000; // 24h\n/** Best-effort timeout for the (rare) registry refresh — short so it can't stall a command. */\nconst DEFAULT_TIMEOUT_MS = 1500;\n\n/**\n * Top-level commands that must never trigger a check/notice:\n * - `hook` runs inside the harness hot path and must return fast (never block the harness);\n * - `report-status` is invoked by BirdyBeep itself, not by an interactive user.\n */\nconst SKIP_COMMANDS = new Set([\"hook\", \"report-status\"]);\n\n/** A parsed semver: numeric core + dot-separated prerelease identifiers (build metadata dropped). */\nexport interface Semver {\n major: number;\n minor: number;\n patch: number;\n /** Prerelease identifiers (e.g. `1.2.0-beta.1` → `[\"beta\", \"1\"]`); empty for a release. */\n prerelease: string[];\n}\n\n// Simplified semver.org grammar: `MAJOR.MINOR.PATCH[-prerelease][+build]`, tolerating a leading `v`.\nconst SEMVER_RE = /^v?(\\d+)\\.(\\d+)\\.(\\d+)(?:-([0-9A-Za-z.-]+))?(?:\\+[0-9A-Za-z.-]+)?$/;\n\n/** Parse a semver string; returns null for anything that isn't a clean `MAJOR.MINOR.PATCH[...]`. */\nexport function parseSemver(input: string): Semver | null {\n const m = SEMVER_RE.exec(input.trim());\n if (m === null) return null;\n return {\n major: Number(m[1]),\n minor: Number(m[2]),\n patch: Number(m[3]),\n prerelease: m[4] !== undefined ? m[4].split(\".\") : [],\n };\n}\n\n/** Compare two prerelease identifier lists per semver §11 (a release outranks any prerelease). */\nfunction comparePrerelease(a: string[], b: string[]): number {\n if (a.length === 0 && b.length === 0) return 0;\n if (a.length === 0) return 1; // 1.2.0 > 1.2.0-beta\n if (b.length === 0) return -1;\n const len = Math.min(a.length, b.length);\n for (let i = 0; i < len; i++) {\n const ai = a[i]!;\n const bi = b[i]!;\n const aNum = /^\\d+$/.test(ai);\n const bNum = /^\\d+$/.test(bi);\n if (aNum && bNum) {\n const d = Number(ai) - Number(bi);\n if (d !== 0) return d < 0 ? -1 : 1;\n } else if (aNum) {\n return -1; // numeric identifiers rank lower than alphanumeric\n } else if (bNum) {\n return 1;\n } else if (ai !== bi) {\n return ai < bi ? -1 : 1; // ASCII lexical order\n }\n }\n if (a.length === b.length) return 0;\n return a.length < b.length ? -1 : 1; // more identifiers wins when all preceding are equal\n}\n\n/** -1 if `a < b`, 0 if equal, 1 if `a > b` (semver precedence). */\nexport function compareSemver(a: Semver, b: Semver): number {\n if (a.major !== b.major) return a.major < b.major ? -1 : 1;\n if (a.minor !== b.minor) return a.minor < b.minor ? -1 : 1;\n if (a.patch !== b.patch) return a.patch < b.patch ? -1 : 1;\n return comparePrerelease(a.prerelease, b.prerelease);\n}\n\n/** `true` when `latest` is a strictly higher version than `current` (both must parse). */\nexport function isNewer(current: string, latest: string): boolean {\n const cur = parseSemver(current);\n const lat = parseSemver(latest);\n return cur !== null && lat !== null && compareSemver(cur, lat) < 0;\n}\n\n/** Cached registry result. `latest` is the last-seen published version, or null if never fetched. */\nexport interface UpdateCache {\n /** Epoch ms of the last registry refresh attempt. */\n checkedAt: number;\n latest: string | null;\n}\n\nexport function updateCachePath(): string {\n return join(birdyBeepConfigDir(), UPDATE_CACHE_FILE);\n}\n\n/** Read the cache; returns null on a missing/unreadable/corrupt/invalid file (never throws). */\nexport function readUpdateCache(): UpdateCache | null {\n try {\n const parsed: unknown = JSON.parse(readFileSync(updateCachePath(), \"utf8\"));\n if (typeof parsed !== \"object\" || parsed === null) return null;\n const { checkedAt, latest } = parsed as Record<string, unknown>;\n if (typeof checkedAt !== \"number\") return null;\n if (latest !== null && typeof latest !== \"string\") return null;\n return { checkedAt, latest };\n } catch {\n return null;\n }\n}\n\n/** Persist the cache (strict-perm dir + file); best-effort — a write failure is swallowed by callers. */\nexport function writeUpdateCache(cache: UpdateCache): void {\n mkdirSync(birdyBeepConfigDir(), { recursive: true, mode: 0o700 });\n writeFileSync(updateCachePath(), `${JSON.stringify(cache)}\\n`, { mode: 0o600 });\n}\n\n/** Fetch the `latest` dist-tag version from the registry, or throw a concise reason. */\nasync function fetchLatestVersion(\n registryUrl: string,\n fetchImpl: typeof fetch,\n timeoutMs: number,\n): Promise<string> {\n const url = `${registryUrl.replace(/\\/+$/, \"\")}/${PACKAGE_PATH}/latest`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n if (typeof timer.unref === \"function\") timer.unref();\n try {\n const res = await fetchImpl(url, {\n headers: { accept: \"application/json\" },\n signal: controller.signal,\n });\n if (!res.ok) throw new Error(`registry responded ${res.status}`);\n const body = (await res.json()) as { version?: unknown };\n if (typeof body.version !== \"string\" || body.version.length === 0) {\n throw new Error(\"registry response had no version\");\n }\n return body.version;\n } finally {\n clearTimeout(timer);\n }\n}\n\n/** The two-line upgrade notice printed to stderr (lowercase/chirpy per the Perch voice). */\nfunction renderNotice(current: string, latest: string): string {\n return (\n `a new version of birdybeep is available: ${current} → ${latest}\\n` +\n `upgrade with: npm install -g ${PACKAGE_NAME}@latest`\n );\n}\n\nexport interface NotifyUpdateOptions {\n /** Resolved top-level command name (used to skip `hook` / `report-status`). */\n command?: string;\n flags: GlobalFlags;\n io: Io;\n // --- injectables (production defaults are the real registry / fs / clock / env / TTY) ---\n fetchImpl?: typeof fetch;\n currentVersion?: string;\n registryUrl?: string;\n now?: number;\n intervalMs?: number;\n timeoutMs?: number;\n /** Override the stderr-TTY gate (tests set this true to exercise the notice deterministically). */\n isTTY?: boolean;\n env?: NodeJS.ProcessEnv;\n readCache?: () => UpdateCache | null;\n writeCache?: (cache: UpdateCache) => void;\n}\n\n/**\n * The notifier entry point, invoked by the framework after an eligible command runs. Reads the\n * cache, refreshes from the registry when stale (TTL-gated, short timeout, best-effort), and prints\n * the upgrade notice to stderr when a newer version exists. Never throws.\n */\nexport async function maybeNotifyUpdate(opts: NotifyUpdateOptions): Promise<void> {\n try {\n // Hot-path / internal commands: bail before any work so the harness is never slowed.\n if (opts.command !== undefined && SKIP_COMMANDS.has(opts.command)) return;\n // Machine/script output or explicit non-interactive: no chatter on stderr.\n if (opts.flags.json || opts.flags.nonInteractive) return;\n\n const env = opts.env ?? process.env;\n if (env[\"BIRDYBEEP_NO_UPDATE_NOTIFIER\"] || env[\"NO_UPDATE_NOTIFIER\"] || env[\"CI\"]) return;\n\n const isTTY = opts.isTTY ?? Boolean(process.stderr.isTTY);\n if (!isTTY) return; // don't nag in pipes/logs\n\n const current = opts.currentVersion ?? CLI_VERSION;\n const now = opts.now ?? Date.now();\n const intervalMs = opts.intervalMs ?? DEFAULT_CHECK_INTERVAL_MS;\n const readCache = opts.readCache ?? readUpdateCache;\n const writeCache = opts.writeCache ?? writeUpdateCache;\n\n let cache = readCache();\n if (cache === null || now - cache.checkedAt >= intervalMs) {\n // Refresh at most once per interval. On failure, keep the last-known `latest` (so a\n // previously-seen update still shows) but still stamp `checkedAt` to back off, never hammer.\n let latest = cache?.latest ?? null;\n try {\n latest = await fetchLatestVersion(\n opts.registryUrl ?? resolveRegistryUrl(),\n opts.fetchImpl ?? fetch,\n opts.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n );\n } catch {\n /* offline / registry error: fall back to last-known latest, back off for the interval */\n }\n cache = { checkedAt: now, latest };\n try {\n writeCache(cache);\n } catch {\n /* config dir not writable: notice still works this run, just won't be cached */\n }\n }\n\n if (cache.latest !== null && isNewer(current, cache.latest)) {\n opts.io.errline(renderNotice(current, cache.latest));\n }\n } catch {\n /* the notifier is best-effort — it must never break or slow a command */\n }\n}\n","/**\n * @birdybeep/cli — the public, side-effect-free CLI API. `runCli` wires the §9.4 command\n * registry into the framework dispatcher with injectable output (so it is fully unit\n * testable); the executable shell lives in `bin.ts`.\n */\nimport { buildCommands } from \"./commands\";\nimport { type Command, dispatch, type Writer } from \"./framework\";\nimport { maybeNotifyUpdate, type NotifyUpdateOptions } from \"./update-check\";\nimport { CLI_VERSION } from \"./version\";\n\nexport { buildCommands } from \"./commands\";\nexport * from \"./framework\";\nexport { CLI_VERSION } from \"./version\";\n\nexport interface RunCliDeps {\n stdout?: Writer;\n stderr?: Writer;\n /** Override the command registry (tests). Defaults to the real §9.4 tree. */\n commands?: Command[];\n /** Skip the config-dir bootstrap (tests without filesystem side effects). */\n ensureConfig?: boolean;\n /**\n * Override the passive update-notifier. `false` disables it; an object injects the registry\n * fetch / clock / TTY / cache for hermetic tests. Omitted in production → the real notifier\n * (which no-ops on a non-TTY stderr, so unit tests capturing to buffers stay offline & quiet).\n */\n updateCheck?: Partial<NotifyUpdateOptions> | false;\n}\n\n/** Run the CLI against an argv slice (without `node`/script path). Returns the exit code. */\nexport function runCli(argv: string[], deps: RunCliDeps = {}): Promise<number> {\n const notifyUpdate =\n deps.updateCheck === false\n ? undefined\n : (ctx: {\n command: string;\n flags: NotifyUpdateOptions[\"flags\"];\n io: NotifyUpdateOptions[\"io\"];\n }) => maybeNotifyUpdate({ ...ctx, ...(deps.updateCheck ?? {}) });\n\n return dispatch(argv, {\n version: CLI_VERSION,\n commands: deps.commands ?? buildCommands(),\n stdout: deps.stdout ?? process.stdout,\n stderr: deps.stderr ?? process.stderr,\n ...(notifyUpdate !== undefined ? { notifyUpdate } : {}),\n ...(deps.ensureConfig !== undefined ? { ensureConfig: deps.ensureConfig } : {}),\n });\n}\n"],"mappings":"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","names":["claudeCodeAdapter","codexAdapter","opencodeAdapter","mkdirSync","birdyBeepConfigDir","DEFAULT_ADAPTERS","claudeCodeAdapter","codexAdapter","opencodeAdapter","defaultCreateSender","defaultCreateSender","getMachineIdentity","getMachineIdentity","LocalEventQueue","LocalEventQueue","errorEnvelopeSchema","getToken","claudeCodeAdapter","codexAdapter","opencodeAdapter","DEFAULT_ADAPTERS","claudeCodeAdapter","codexAdapter","opencodeAdapter","base","getToken","errorEnvelopeSchema","defaultCreateSender","claudeCodeAdapter","codexAdapter","opencodeAdapter","DEFAULT_ADAPTERS","claudeCodeAdapter","codexAdapter","opencodeAdapter","defaultCreateSender","defaultCreateSender","getMachineIdentity","getMachineIdentity","defaultCreateSender","mkdirSync","readFileSync","writeFileSync","join","birdyBeepConfigDir","join","birdyBeepConfigDir","readFileSync","mkdirSync","writeFileSync"]}
|