{"version":3,"sources":["../src/commands/agent.ts","../src/framework.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/version.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","../src/node-check.ts","../src/bin.ts"],"sourcesContent":["/**\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 * 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 * `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 * 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 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","/**\n * Node version guard (§16.3): the CLI installs into developers' machines, so it fails\n * gracefully with a clear message on an unsupported Node rather than crashing on a missing\n * API. The minimum here matches every package's `engines.node`.\n */\nexport const MIN_NODE_MAJOR = 20;\n\n/** Parse the major version from a `process.versions.node` string (e.g. \"20.11.0\" → 20). */\nexport function parseNodeMajor(version: string): number | null {\n  const match = /^v?(\\d+)\\./.exec(version);\n  return match ? Number(match[1]) : null;\n}\n\n/** A clear error message if `version` is below the supported range, else null. */\nexport function nodeVersionError(version: string): string | null {\n  const major = parseNodeMajor(version);\n  if (major === null) return null; // unparseable → don't block (best-effort)\n  return major < MIN_NODE_MAJOR\n    ? `birdybeep requires Node ${MIN_NODE_MAJOR}+ (you have ${version}). Please upgrade Node and retry.`\n    : null;\n}\n","#!/usr/bin/env node\nimport { runCli } from \"./cli.js\";\nimport { nodeVersionError } from \"./node-check.js\";\n\n// Executable entry: the only side-effectful module. Guard the Node version first (clear\n// message instead of a cryptic missing-API crash), then dispatch. Use exitCode (not\n// process.exit) so buffered stdout/stderr flushes before the process exits.\nconst versionError = nodeVersionError(process.versions.node);\nif (versionError !== null) {\n  process.stderr.write(`${versionError}\\n`);\n  process.exitCode = 1;\n} else {\n  runCli(process.argv.slice(2)).then(\n    (code) => {\n      process.exitCode = code;\n    },\n    (err: unknown) => {\n      process.stderr.write(`birdybeep: ${err instanceof Error ? err.message : String(err)}\\n`);\n      process.exitCode = 1;\n    },\n  );\n}\n"],"mappings":"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","names":["import_agent_core","import_claude_code","import_codex","import_opencode","import_node_fs","import_agent_core","import_agent_core","DEFAULT_ADAPTERS","defaultCreateSender","import_agent_core","import_claude_code","import_codex","import_opencode","defaultCreateSender","import_agent_core","import_agent_core","import_agent_core","import_agent_core","import_agent_core","import_claude_code","import_codex","import_opencode","DEFAULT_ADAPTERS","base","import_agent_core","import_claude_code","import_codex","import_opencode","DEFAULT_ADAPTERS","defaultCreateSender","import_agent_core","defaultCreateSender","import_node_fs","import_node_path","import_agent_core"]}