@posthog/wizard 2.77.0 → 2.78.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.
Files changed (173) hide show
  1. package/README.md +30 -15
  2. package/dist/{add-mcp-server-to-clients-BnRyE4pw.js → add-mcp-server-to-clients-JMv8LP-O.js} +6 -5
  3. package/dist/{add-mcp-server-to-clients-BnRyE4pw.js.map → add-mcp-server-to-clients-JMv8LP-O.js.map} +1 -1
  4. package/dist/agent-bCZ3i3fh.js +3085 -0
  5. package/dist/agent-bCZ3i3fh.js.map +1 -0
  6. package/dist/{agent-interface-Avtr_5M5.js → agent-interface-BAOIHuXS.js} +429 -378
  7. package/dist/agent-interface-BAOIHuXS.js.map +1 -0
  8. package/dist/{agent-prompt-loader-CHixNPgY.js → agent-prompt-loader-7Pd4CfZO.js} +6 -6
  9. package/dist/agent-prompt-loader-7Pd4CfZO.js.map +1 -0
  10. package/dist/analytics-BcV-WCM4.js +2 -0
  11. package/dist/{analytics-C67F2vee.js → analytics-CHCZ_qUR.js} +10 -6
  12. package/dist/analytics-CHCZ_qUR.js.map +1 -0
  13. package/dist/{api-Dj1yabTj.js → api-Diy_2fp8.js} +4 -17
  14. package/dist/api-Diy_2fp8.js.map +1 -0
  15. package/dist/bin.js +410 -68
  16. package/dist/bin.js.map +1 -1
  17. package/dist/{bounded-fs-CWRYuLAn.js → bounded-fs-Bx9zTe6m.js} +4 -4
  18. package/dist/bounded-fs-Bx9zTe6m.js.map +1 -0
  19. package/dist/check-screens.tsx +1 -1
  20. package/dist/{ci-install-CvXL5h13.js → ci-install-CDdQYsPe.js} +6 -5
  21. package/dist/ci-install-CDdQYsPe.js.map +1 -0
  22. package/dist/constants-jFI2SaE1.js +260 -0
  23. package/dist/constants-jFI2SaE1.js.map +1 -0
  24. package/dist/debug-Ch4BDOtD.js +171 -0
  25. package/dist/debug-Ch4BDOtD.js.map +1 -0
  26. package/dist/{debug-CziFS0cA.js → debug-M2gV2iDq.js} +1 -1
  27. package/dist/{defaults-4c4YwTmW.js → defaults-C6J7yL4O.js} +1 -1
  28. package/dist/{defaults-4c4YwTmW.js.map → defaults-C6J7yL4O.js.map} +1 -1
  29. package/dist/endpoints-DCVbM06L.js +108 -0
  30. package/dist/endpoints-DCVbM06L.js.map +1 -0
  31. package/dist/{env-api-key-BZ5wE3Y4.js → env-api-key-Qx8NnYHm.js} +3 -3
  32. package/dist/env-api-key-Qx8NnYHm.js.map +1 -0
  33. package/dist/{environment-BEvsey6i.js → environment-B07Bmxae.js} +6 -6
  34. package/dist/environment-B07Bmxae.js.map +1 -0
  35. package/dist/{errors-BoJvrdw8.js → errors-CQ9kttJD.js} +27 -34
  36. package/dist/errors-CQ9kttJD.js.map +1 -0
  37. package/dist/{file-BoD3REGB.js → file-BcLTjU16.js} +2 -2
  38. package/dist/{file-BoD3REGB.js.map → file-BcLTjU16.js.map} +1 -1
  39. package/dist/{file-watcher-BPFazvG_.js → file-watcher-DWc_bTs6.js} +2 -2
  40. package/dist/{file-watcher-BPFazvG_.js.map → file-watcher-DWc_bTs6.js.map} +1 -1
  41. package/dist/{gateway-session-xPFv6p5c.js → gateway-CjoShdLa.js} +175 -20
  42. package/dist/gateway-CjoShdLa.js.map +1 -0
  43. package/dist/generate-version.cjs +1 -1
  44. package/dist/{headless-ui-CsmQrDIl.js → headless-ui-BFFmYC4v.js} +13 -2
  45. package/dist/headless-ui-BFFmYC4v.js.map +1 -0
  46. package/dist/{interactive-Dej-sxvR.js → interactive-D6zV7brJ.js} +2 -2
  47. package/dist/{interactive-Dej-sxvR.js.map → interactive-D6zV7brJ.js.map} +1 -1
  48. package/dist/{local-dev-DPZiIPCK.js → local-dev-McsurOC-.js} +2 -2
  49. package/dist/local-dev-McsurOC-.js.map +1 -0
  50. package/dist/logging-ui-_TwoMNbG.js +226 -0
  51. package/dist/logging-ui-_TwoMNbG.js.map +1 -0
  52. package/dist/mcp-DAgaoGk5.js +97 -0
  53. package/dist/mcp-DAgaoGk5.js.map +1 -0
  54. package/dist/{mcp-prompt-streaming-BU_kuur_.js → mcp-prompt-streaming-I2U_X7BC.js} +7 -6
  55. package/dist/mcp-prompt-streaming-I2U_X7BC.js.map +1 -0
  56. package/dist/{mint-failure-BrleGqMd.js → mint-failure-D4nd2XmZ.js} +82 -25
  57. package/dist/mint-failure-D4nd2XmZ.js.map +1 -0
  58. package/dist/models-DDdBJKwT.js +83 -0
  59. package/dist/models-DDdBJKwT.js.map +1 -0
  60. package/dist/{non-interactive-DcOjH2fw.js → non-interactive-Dzow7YKY.js} +3 -3
  61. package/dist/non-interactive-Dzow7YKY.js.map +1 -0
  62. package/dist/oauth-session-DJ8h6GFa.js +74 -0
  63. package/dist/oauth-session-DJ8h6GFa.js.map +1 -0
  64. package/dist/{orchestrator-tools-DXwr8Sp3.js → orchestrator-tools-szcdscwn.js} +4 -4
  65. package/dist/orchestrator-tools-szcdscwn.js.map +1 -0
  66. package/dist/{package-json-xt3eeyBI.js → package-json-DY70kkNp.js} +2 -2
  67. package/dist/package-json-DY70kkNp.js.map +1 -0
  68. package/dist/{pi-mY8I2XkG.js → pi-D3h5Ok0i.js} +329 -65
  69. package/dist/pi-D3h5Ok0i.js.map +1 -0
  70. package/dist/{playground-CDUUKLkC.js → playground-5AB4WgNF.js} +11 -7
  71. package/dist/playground-5AB4WgNF.js.map +1 -0
  72. package/dist/{posthog-Hc_-9wrr.js → posthog-DNn574nW.js} +8 -3
  73. package/dist/posthog-DNn574nW.js.map +1 -0
  74. package/dist/{provisioning-xfdjhFtA.js → provisioning-B8uSqRZk.js} +6 -5
  75. package/dist/provisioning-B8uSqRZk.js.map +1 -0
  76. package/dist/{queue-tools-C8y_xZJi.js → queue-tools-9OOVx5TE.js} +7 -86
  77. package/dist/queue-tools-9OOVx5TE.js.map +1 -0
  78. package/dist/{registry-DTmREJ-f.js → registry-8YG-kuXk.js} +265 -6
  79. package/dist/registry-8YG-kuXk.js.map +1 -0
  80. package/dist/run-agent-legacy-d7rWlzQR.js +3739 -0
  81. package/dist/run-agent-legacy-d7rWlzQR.js.map +1 -0
  82. package/dist/{security-Dw2oFJjP.js → security-Cg_4a7vB.js} +6 -6
  83. package/dist/security-Cg_4a7vB.js.map +1 -0
  84. package/dist/{setup-utils-fjJTBhaB.js → setup-utils-CmTCTPkX.js} +46 -18
  85. package/dist/setup-utils-CmTCTPkX.js.map +1 -0
  86. package/dist/smoke-test.sh +1 -1
  87. package/dist/{start-tui-UNe2xQ0U.js → start-tui-CB2PZs1x.js} +38 -44
  88. package/dist/start-tui-CB2PZs1x.js.map +1 -0
  89. package/dist/{steps-C2yqOk_h.js → steps-BZcXRJNY.js} +7 -7
  90. package/dist/{steps-C2yqOk_h.js.map → steps-BZcXRJNY.js.map} +1 -1
  91. package/dist/{store-Bic4Cr3L.js → store-UN7c-ASf.js} +18 -28
  92. package/dist/store-UN7c-ASf.js.map +1 -0
  93. package/dist/{subagent-Dz41vV9j.js → subagent-BofIDK-O.js} +8 -3
  94. package/dist/subagent-BofIDK-O.js.map +1 -0
  95. package/dist/{task-5-fw_Vw3.js → task-r9t1UhQP.js} +124 -36
  96. package/dist/task-r9t1UhQP.js.map +1 -0
  97. package/dist/{task-stream-dVzl6b_q.js → task-stream-CMUilu54.js} +45 -15
  98. package/dist/task-stream-CMUilu54.js.map +1 -0
  99. package/dist/{tasks-D1c2z1aw.js → tasks-Bbv_lOBG.js} +17 -13
  100. package/dist/tasks-Bbv_lOBG.js.map +1 -0
  101. package/dist/{telemetry-BRnxBRWK.js → telemetry-D6ruCtnv.js} +5 -5
  102. package/dist/telemetry-D6ruCtnv.js.map +1 -0
  103. package/dist/{terminal-9bvRa4Qt.js → terminal-DrGyci_a.js} +39 -74
  104. package/dist/terminal-DrGyci_a.js.map +1 -0
  105. package/dist/{tools-Dp6i9k70.js → tools-Dyfh9aCD.js} +11 -11
  106. package/dist/tools-Dyfh9aCD.js.map +1 -0
  107. package/dist/ui-BBVuTM1v.js +15 -0
  108. package/dist/ui-BBVuTM1v.js.map +1 -0
  109. package/dist/version-aXxpgRKx.js +6 -0
  110. package/dist/version-aXxpgRKx.js.map +1 -0
  111. package/dist/warlock-smoke-test.ts +2 -2
  112. package/dist/{wizard-abort-lE6umflt.js → wizard-abort-BBkiUxfS.js} +23 -20
  113. package/dist/wizard-abort-BBkiUxfS.js.map +1 -0
  114. package/dist/wizard-abort-BU4aLyvh.js +3 -0
  115. package/dist/{wizard-session-FSJCkTcP.js → wizard-session-2w4Ru-Wz.js} +12 -16
  116. package/dist/wizard-session-2w4Ru-Wz.js.map +1 -0
  117. package/dist/wizard-session-DGaUHOF3.js +2 -0
  118. package/dist/wizard-ui-DoyOZxK8.js +16 -0
  119. package/dist/wizard-ui-DoyOZxK8.js.map +1 -0
  120. package/dist/{yara-hooks-BTNJ6MGW.js → yara-hooks-DCeMDd1o.js} +19 -68
  121. package/dist/yara-hooks-DCeMDd1o.js.map +1 -0
  122. package/dist/yara-hooks-DSGuCU9A.js +2 -0
  123. package/package.json +1 -1
  124. package/dist/agent-interface-Avtr_5M5.js.map +0 -1
  125. package/dist/agent-prompt-loader-CHixNPgY.js.map +0 -1
  126. package/dist/agent-runner-COOIUJCP.js +0 -6188
  127. package/dist/agent-runner-COOIUJCP.js.map +0 -1
  128. package/dist/analytics-C67F2vee.js.map +0 -1
  129. package/dist/analytics-CJA1uLlk.js +0 -2
  130. package/dist/api-Dj1yabTj.js.map +0 -1
  131. package/dist/bounded-fs-CWRYuLAn.js.map +0 -1
  132. package/dist/ci-install-CvXL5h13.js.map +0 -1
  133. package/dist/debug-B4kzIZPi.js +0 -754
  134. package/dist/debug-B4kzIZPi.js.map +0 -1
  135. package/dist/env-api-key-BZ5wE3Y4.js.map +0 -1
  136. package/dist/environment-BEvsey6i.js.map +0 -1
  137. package/dist/errors-BoJvrdw8.js.map +0 -1
  138. package/dist/gateway-session-C118uACz.js +0 -2
  139. package/dist/gateway-session-xPFv6p5c.js.map +0 -1
  140. package/dist/headless-ui-CsmQrDIl.js.map +0 -1
  141. package/dist/local-dev-DPZiIPCK.js.map +0 -1
  142. package/dist/mcp-Cbuw_xss.js +0 -64
  143. package/dist/mcp-Cbuw_xss.js.map +0 -1
  144. package/dist/mcp-prompt-streaming-BU_kuur_.js.map +0 -1
  145. package/dist/mint-failure-BrleGqMd.js.map +0 -1
  146. package/dist/non-interactive-DcOjH2fw.js.map +0 -1
  147. package/dist/orchestrator-tools-DXwr8Sp3.js.map +0 -1
  148. package/dist/package-json-xt3eeyBI.js.map +0 -1
  149. package/dist/package-manager-DR23m5Jg.js +0 -290
  150. package/dist/package-manager-DR23m5Jg.js.map +0 -1
  151. package/dist/pi-mY8I2XkG.js.map +0 -1
  152. package/dist/playground-CDUUKLkC.js.map +0 -1
  153. package/dist/posthog-Hc_-9wrr.js.map +0 -1
  154. package/dist/provisioning-xfdjhFtA.js.map +0 -1
  155. package/dist/queue-tools-C8y_xZJi.js.map +0 -1
  156. package/dist/registry-DTmREJ-f.js.map +0 -1
  157. package/dist/security-Dw2oFJjP.js.map +0 -1
  158. package/dist/setup-utils-fjJTBhaB.js.map +0 -1
  159. package/dist/start-tui-UNe2xQ0U.js.map +0 -1
  160. package/dist/store-Bic4Cr3L.js.map +0 -1
  161. package/dist/subagent-Dz41vV9j.js.map +0 -1
  162. package/dist/task-5-fw_Vw3.js.map +0 -1
  163. package/dist/task-stream-dVzl6b_q.js.map +0 -1
  164. package/dist/tasks-D1c2z1aw.js.map +0 -1
  165. package/dist/telemetry-BRnxBRWK.js.map +0 -1
  166. package/dist/terminal-9bvRa4Qt.js.map +0 -1
  167. package/dist/tools-Dp6i9k70.js.map +0 -1
  168. package/dist/wizard-abort-CAcInAxg.js +0 -2
  169. package/dist/wizard-abort-lE6umflt.js.map +0 -1
  170. package/dist/wizard-session-CYvyYnti.js +0 -2
  171. package/dist/wizard-session-FSJCkTcP.js.map +0 -1
  172. package/dist/yara-hooks-BTNJ6MGW.js.map +0 -1
  173. package/dist/yara-hooks-CFY4pGcW.js +0 -2
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bin.js","names":["path"],"sources":["../src/commands/command.ts","../src/wizard.ts","../src/commands/provision.ts","../src/commands/basic-integration/index.ts","../src/commands/mcp/tui-availability.ts","../src/commands/mcp/add.ts","../src/commands/mcp/remove.ts","../src/commands/mcp/tutorial.ts","../src/commands/mcp/index.ts","../src/lib/runners/resolve-no-telemetry.ts","../src/lib/runners/run-wizard.ts","../src/lib/runners/run-non-interactive.ts","../src/lib/runners/run-wizard-ci.ts","../src/lib/runners/run-wizard-headless.ts","../src/commands/skill-program-options.ts","../src/commands/factories/shared.ts","../src/commands/factories/native-command-factory.ts","../src/commands/mcp-analytics.ts","../src/commands/replay-vision.ts","../src/commands/ai-observability.ts","../src/commands/metrics.ts","../src/lib/programs/dispatch-family.ts","../src/ui/tui/primitives/picker-filter.ts","../src/ui/tui/primitives/PromptLabel.tsx","../src/ui/tui/primitives/ConfirmButton.tsx","../src/ui/tui/hooks/useStdoutDimensions.ts","../src/ui/tui/hooks/keyboard-hints-utils.ts","../src/ui/tui/hooks/useKeyboardHints.tsx","../src/ui/tui/hooks/useKeyBindings.ts","../src/ui/tui/primitives/PickerMenu.tsx","../src/commands/factories/family-picker.tsx","../src/commands/factories/family-command-factory.ts","../src/commands/audit.ts","../src/commands/doctor.ts","../src/commands/migrate.ts","../src/commands/revenue.ts","../src/commands/warehouse.ts","../src/commands/self-driving.ts","../src/commands/slack.ts","../src/commands/upload-sourcemaps.ts","../src/commands/error-tracking.ts","../src/commands/basic-integration/skill.ts","../src/commands/skill.ts","../src/commands/cli/add.ts","../src/commands/cli/index.ts","../bin.ts"],"sourcesContent":["import type {\n Arguments,\n Argv,\n CommandModule,\n Options,\n PositionalOptions,\n} from 'yargs';\nimport { setEntryCommand } from '@utils/links';\n\nexport interface Command {\n /** Yargs command name. Use `['$0']` for the default command. */\n name: string | readonly string[];\n description: string;\n /** Flags exposed by this command. Same shape as yargs `.options()`. */\n options?: Record<string, Options>;\n /**\n * Positional arguments declared in `name` (e.g. the `id` in `skill [id]`).\n * Under `.strictOptions()`, yargs only treats a positional as a known\n * argument once it's registered via `.positional()` — a command-string\n * positional alone is rejected as `Unknown argument`. Declare each one here\n * so an optional positional like `skill [id]` actually accepts its value.\n */\n positionals?: Record<string, PositionalOptions>;\n /** Nested subcommands. */\n children?: readonly Command[];\n /** `--help` examples shown for this command. */\n examples?: ReadonlyArray<readonly [string, string]>;\n /**\n * Called synchronously by yargs when the command matches. Wrap async work in\n * `void (async () => { ... })()`. Optional only when `children` is set — in\n * that case yargs requires the user to pick a subcommand (or to set\n * `interactiveDefault` for an in-process picker).\n */\n handler?: (argv: Arguments) => void;\n /**\n * Cross-flag validation run by yargs after parsing. Throw to reject (yargs\n * prints the message and exits non-zero); return `true` to accept. Prefer\n * this over per-option `conflicts` for mutually exclusive flags: yargs\n * counts a `default`-valued flag as \"present\", so `conflicts` misfires on\n * boolean flags that default to `false` — a hand-written predicate only\n * sees what you test for (e.g. truthiness).\n */\n check?: (argv: Arguments) => boolean;\n /**\n * Optional handler invoked when this command has `children` but the user\n * supplied no subcommand. Use it to mount an interactive picker over the\n * children so `wizard audit` (no leaf) opens a TUI menu instead of yargs\n * help. When set, suppresses the implicit `demandCommand(1)`.\n *\n * May return a Promise — yargs awaits the result before exiting.\n */\n interactiveDefault?: (argv: Arguments) => void | Promise<void>;\n /**\n * When true, this child is the \"default\" leaf in its family: the\n * family picker pre-highlights it so a single Enter runs it. The picker\n * still always opens — this never auto-runs the child. At most one child\n * per parent should be marked. Propagated from the context-mill manifest\n * entry's `default` flag through `skillCommandFactory`.\n */\n default?: boolean;\n}\n\n/** Extract the bare command word(s) from a yargs name spec, dropping positionals and aliases' arg syntax. */\nexport function commandKeys(name: string | readonly string[]): string[] {\n const list: readonly string[] = typeof name === 'string' ? [name] : name;\n return list.map((n) => n.trim().split(/\\s+/)[0]);\n}\n\nexport function toCommandModule(\n cmd: Command,\n parentPath: readonly string[],\n): CommandModule {\n // `wizard slack` → 'slack', `wizard mcp add` → 'mcp-add'. The default\n // `$0` resolves to '' and is skipped — its handler reports itself.\n const entryCommand = [...parentPath, commandKeys(cmd.name)[0]]\n .filter((key) => key !== '$0')\n .join('-');\n return {\n command: cmd.name,\n describe: cmd.description,\n builder: (y: Argv) => {\n let next = cmd.options ? y.options(cmd.options) : y;\n for (const [key, opts] of Object.entries(cmd.positionals ?? {})) {\n next = next.positional(key, opts);\n }\n if (cmd.check) next = next.check(cmd.check);\n for (const [usage, description] of cmd.examples ?? []) {\n next = next.example(usage, description);\n }\n const ownPath = [...parentPath, commandKeys(cmd.name)[0]];\n for (const child of cmd.children ?? []) {\n next = next.command(toCommandModule(child, ownPath));\n }\n if (cmd.children?.length && !cmd.handler && !cmd.interactiveDefault) {\n next = next.demandCommand(1);\n }\n return next;\n },\n handler: (argv: Arguments) => {\n if (entryCommand) setEntryCommand(entryCommand);\n const run = cmd.handler ?? cmd.interactiveDefault ?? (() => undefined);\n run(argv);\n },\n };\n}\n","import yargs from 'yargs';\nimport { hideBin } from 'yargs/helpers';\nimport type { Argv } from 'yargs';\nimport { IS_PRODUCTION_BUILD } from '@env';\nimport { Harness, Sequence } from '@lib/constants';\nimport { regionOption } from '@lib/headless-mode';\nimport { initLocalDev, localMcpSkillsNotice } from '@lib/local-dev';\nimport { toCommandModule, type Command } from './commands/command';\nimport { ErrorCodes } from '@lib/errors';\nimport { emitWizardError } from '@lib/errors';\n\n/**\n * Global yargs options applied to every command. These are read from the\n * `POSTHOG_WIZARD` env prefix as well as flags.\n *\n * Options with `hidden: true` are \"internal modes\" — they don't show up in\n * `--help` but are still accepted on every command. The `--local-*` flags live\n * in the constructor's `!IS_PRODUCTION_BUILD` block instead, so published\n * builds reject them; see `docs/local-dev.md`.\n */\nexport const GLOBAL_OPTIONS = {\n debug: {\n default: false,\n describe: 'Enable verbose logging\\nenv: POSTHOG_WIZARD_DEBUG',\n type: 'boolean' as const,\n },\n signup: {\n default: false,\n describe:\n 'Create a new PostHog account during setup\\nenv: POSTHOG_WIZARD_SIGNUP',\n type: 'boolean' as const,\n },\n telemetry: {\n default: true,\n describe:\n 'Send wizard run state to PostHog (pass --no-telemetry to disable)\\nenv: POSTHOG_WIZARD_TELEMETRY',\n type: 'boolean' as const,\n },\n 'api-key': {\n describe:\n 'PostHog personal API key (phx_xxx) for authentication\\nenv: POSTHOG_WIZARD_API_KEY',\n type: 'string' as const,\n },\n 'project-id': {\n describe:\n 'PostHog project ID to use (optional; when not set, uses default from API key or OAuth)\\nenv: POSTHOG_WIZARD_PROJECT_ID',\n type: 'string' as const,\n },\n email: {\n describe:\n 'Email address for signup (used with --signup)\\nenv: POSTHOG_WIZARD_EMAIL',\n type: 'string' as const,\n },\n // ── Internal modes ─────────────────────────────────────────────────\n // Hidden from `--help`.\n // NB: the experimental headless flag is deliberately NOT global. Supported\n // commands declare it through `headlessOption` in @lib/headless-mode.\n 'base-url': {\n describe:\n 'Override the PostHog base URL (e.g. http://localhost:8010), bypassing region resolution. Pins the API host, cloud URL, and OAuth server.\\nenv: POSTHOG_WIZARD_BASE_URL',\n type: 'string' as const,\n hidden: true,\n },\n benchmark: {\n default: false,\n describe:\n 'Run in benchmark mode with per-phase token tracking\\nenv: POSTHOG_WIZARD_BENCHMARK',\n type: 'boolean' as const,\n hidden: true,\n },\n 'yara-report': {\n default: false,\n describe:\n 'Print YARA scanner summary after the agent run\\nenv: POSTHOG_WIZARD_YARA_REPORT',\n type: 'boolean' as const,\n hidden: true,\n },\n};\n\nexport class Wizard {\n private cli: Argv;\n\n private constructor() {\n let cli: Argv = yargs(hideBin(process.argv))\n .env('POSTHOG_WIZARD')\n .options(GLOBAL_OPTIONS);\n\n // CI mode (--ci) is only supported in dev/test. It is left undeclared in\n // published builds (NODE_ENV==='production'), so .strictOptions() rejects\n // it there as an unknown argument — exactly like any other unrecognized\n // flag. init() additionally detects it up front to print a clearer message.\n // The published-build, non-interactive path is the experimental headless\n // flag, declared per-command through `headlessOption` (see\n // @lib/headless-mode). CI needs `region` globally because the workbench\n // passes it to every command. --ci and headless stay separate so their\n // behavior can diverge.\n if (!IS_PRODUCTION_BUILD) {\n cli = cli\n .options(regionOption)\n .option('ci', {\n default: false,\n describe:\n 'Enable CI mode for non-interactive execution\\nenv: POSTHOG_WIZARD_CI',\n type: 'boolean',\n hidden: true,\n })\n // Runner overrides — dev/test only, same lifecycle as --ci.\n .option('harness', {\n describe:\n 'Override the agent harness (anthropic | pi). Wins over the PostHog runner flag.\\nenv: POSTHOG_WIZARD_HARNESS',\n choices: Object.values(Harness),\n type: 'string',\n hidden: true,\n })\n .option('sequence', {\n describe:\n 'Override the runner sequence (linear | orchestrator). Wins over the PostHog orchestrator flag.\\nenv: POSTHOG_WIZARD_SEQUENCE',\n choices: Object.values(Sequence),\n type: 'string',\n hidden: true,\n })\n .option('model', {\n describe:\n 'Override the agent model (gateway id, e.g. claude-sonnet-5 | openai/gpt-5.6-terra). Wins over the binding default.\\nenv: POSTHOG_WIZARD_MODEL',\n type: 'string',\n hidden: true,\n })\n .option('capture-aio', {\n default: false,\n describe:\n \"Capture wizard LLM calls as $ai_generation events in the authenticated project's AI Observability tab.\\nenv: POSTHOG_WIZARD_CAPTURE_AIO\",\n type: 'boolean',\n hidden: true,\n })\n // Rides beside the PostHog destination rather than replacing it, so a\n // logged run is the same run the backend sees.\n .option('task-stream-log', {\n describe:\n 'Append every task-stream payload to a local JSONL file. Pass a path, or pass the flag alone for /tmp/posthog-wizard-task-stream.jsonl\\nenv: POSTHOG_WIZARD_TASK_STREAM_LOG',\n type: 'string',\n })\n // ── Local dev targets (see docs/local-dev.md) ──────────────────\n // Not `hidden`: the build gate already keeps them from users, so\n // hiding them would only cost the dev-build help row. Deliberately not\n // named `--local`, which `wizard mcp add` already uses for something\n // unrelated.\n .option('local-dev', {\n default: false,\n describe:\n 'Point context-mill, MCP, and PostHog at local dev servers\\nenv: POSTHOG_WIZARD_LOCAL_DEV',\n type: 'boolean',\n })\n // No `default` on the three below — they must stay `undefined` when\n // absent for resolveLocalDev() to honour the umbrella and `--no-*`.\n .option('local-context-mill', {\n describe:\n 'Fetch skills from the local context-mill server (http://localhost:8765)\\nenv: POSTHOG_WIZARD_LOCAL_CONTEXT_MILL',\n type: 'boolean',\n })\n .option('local-mcp', {\n describe:\n 'Use the local MCP server (http://localhost:8787/mcp). Affects MCP only — use --local-context-mill for skills.\\nenv: POSTHOG_WIZARD_LOCAL_MCP',\n type: 'boolean',\n })\n .option('local-posthog', {\n describe:\n 'Point every PostHog origin (API, app, OAuth, gateway) at http://localhost:8010\\nenv: POSTHOG_WIZARD_LOCAL_POSTHOG',\n type: 'boolean',\n });\n }\n\n this.cli = cli\n // Middleware rather than an argv scan so the env path is covered too,\n // and it runs before any TUI takes the terminal.\n .middleware((argv) => {\n // The one place local targets are resolved; everything downstream reads\n // getLocalDev().\n initLocalDev(argv);\n\n // Temporary.\n const notice = localMcpSkillsNotice({\n localDev: argv.localDev as boolean | undefined,\n localMcp: argv.localMcp as boolean | undefined,\n localContextMill: argv.localContextMill as boolean | undefined,\n });\n if (notice) {\n process.stderr.write(`\\n\\x1b[33m! ${notice}\\x1b[0m\\n\\n`);\n }\n })\n .strictOptions()\n // Reject unrecognized commands (e.g. `wizard bogus`) instead of letting\n // them fall through to the default `$0` integration flow.\n .strictCommands()\n // Print a concise error and point to `--help`, instead of yargs' default\n // of dumping the entire usage screen under every failure.\n .fail((msg, err) => {\n const text = msg || (err && err.message) || 'Invalid arguments';\n process.stderr.write(\n `\\n\\x1b[1;91m✖ ${text}\\x1b[0m\\n` +\n ` Run \\`wizard --help\\` to see available commands and options.\\n\\n`,\n );\n emitWizardError({ code: ErrorCodes.CliBadArgs, message: text });\n process.exit(1);\n })\n .help()\n .alias('help', 'h')\n .version()\n .alias('version', 'v');\n }\n\n /** Start a chain; equivalent to `new Wizard().use(...cmds)`. */\n static use(...cmds: Command[]): Wizard {\n return new Wizard().use(...cmds);\n }\n\n /** Register one or more commands with yargs. */\n use(...cmds: Command[]): this {\n for (const cmd of cmds) {\n this.cli = this.cli.command(toCommandModule(cmd, []));\n }\n return this;\n }\n\n /** Parse argv and dispatch to the matching registered command. */\n init(): void {\n // In published builds, `--ci` is undeclared, so yargs would reject it as\n // an unknown argument — accurate but unhelpful, since --help doesn't list\n // --ci either and the user has no path forward. POSTHOG_WIZARD_CI silently\n // no-ops for the same reason (yargs only resolves env vars for declared\n // options). Detect both up front and exit with a message that explains why.\n if (IS_PRODUCTION_BUILD) {\n const args = process.argv.slice(2);\n const argvHasCI = args.some(\n (a) => a === '--ci' || a === '--no-ci' || a.startsWith('--ci='),\n );\n const envHasCI =\n process.env.POSTHOG_WIZARD_CI != null &&\n process.env.POSTHOG_WIZARD_CI !== '';\n if (argvHasCI || envHasCI) {\n process.stderr.write(\n `\\n\\x1b[1;91m✖ CI mode is not currently supported in published builds.\\x1b[0m\\n\\n`,\n );\n emitWizardError({\n code: ErrorCodes.CliFlagUnavailable,\n message: 'CI mode is not supported in published builds.',\n });\n process.exit(1);\n }\n\n // --harness / --sequence / --model / --capture-aio are dev/test-only.\n // In published builds the env vars would silently no-op, so reject them\n // explicitly instead.\n const argvHasOverride = args.some(\n (a) =>\n a === '--harness' ||\n a.startsWith('--harness=') ||\n a === '--sequence' ||\n a.startsWith('--sequence=') ||\n a === '--model' ||\n a.startsWith('--model=') ||\n a === '--capture-aio' ||\n a === '--no-capture-aio' ||\n a.startsWith('--capture-aio='),\n );\n const envHasOverride =\n (process.env.POSTHOG_WIZARD_HARNESS != null &&\n process.env.POSTHOG_WIZARD_HARNESS !== '') ||\n (process.env.POSTHOG_WIZARD_SEQUENCE != null &&\n process.env.POSTHOG_WIZARD_SEQUENCE !== '') ||\n (process.env.POSTHOG_WIZARD_MODEL != null &&\n process.env.POSTHOG_WIZARD_MODEL !== '') ||\n (process.env.POSTHOG_WIZARD_CAPTURE_AIO != null &&\n process.env.POSTHOG_WIZARD_CAPTURE_AIO !== '');\n if (argvHasOverride || envHasOverride) {\n process.stderr.write(\n `\\n\\x1b[1;91m✖ The --harness, --sequence, --model, and --capture-aio overrides are not available in published builds.\\x1b[0m\\n\\n`,\n );\n emitWizardError({\n code: ErrorCodes.CliFlagUnavailable,\n message:\n 'The --harness, --sequence, --model, and --capture-aio overrides are not available in published builds.',\n });\n process.exit(1);\n }\n\n // `--local-mcp` used to be declared unconditionally, so published builds\n // accepted it and quietly aimed the run at localhost. Reject explicitly.\n const argvHasLocalTarget = args.some((a) =>\n LOCAL_TARGET_FLAGS.some(\n (f) => a === `--${f}` || a === `--no-${f}` || a.startsWith(`--${f}=`),\n ),\n );\n const envHasLocalTarget = LOCAL_TARGET_ENV_VARS.some(\n (k) => process.env[k] != null && process.env[k] !== '',\n );\n if (argvHasLocalTarget || envHasLocalTarget) {\n process.stderr.write(\n `\\n\\x1b[1;91m✖ The --local-dev, --local-context-mill, --local-mcp, and --local-posthog targets are not available in published builds.\\x1b[0m\\n` +\n ` They point the wizard at development servers on localhost.\\n\\n`,\n );\n emitWizardError({\n code: ErrorCodes.CliFlagUnavailable,\n message:\n 'The --local-dev, --local-context-mill, --local-mcp, and --local-posthog targets are not available in published builds.',\n });\n process.exit(1);\n }\n }\n void this.cli.wrap(process.stdout.isTTY ? this.cli.terminalWidth() : 80)\n .argv;\n }\n}\n\n/** Excludes bare `local`: `wizard mcp add --local` stays available in prod. */\nconst LOCAL_TARGET_FLAGS = [\n 'local-dev',\n 'local-context-mill',\n 'local-mcp',\n 'local-posthog',\n] as const;\n\nconst LOCAL_TARGET_ENV_VARS = [\n 'POSTHOG_WIZARD_LOCAL_DEV',\n 'POSTHOG_WIZARD_LOCAL_CONTEXT_MILL',\n 'POSTHOG_WIZARD_LOCAL_MCP',\n 'POSTHOG_WIZARD_LOCAL_POSTHOG',\n] as const;\n","import type { Arguments } from 'yargs';\nimport { getUI, setUI } from '@ui';\nimport { LoggingUI } from '@ui/logging-ui';\nimport type { ProvisioningResult } from '@utils/provisioning';\nimport type { Command } from './command';\n\nexport const provisionCommand: Command = {\n name: 'provision',\n description: 'Create a new PostHog account (headless, no TUI)',\n options: {\n email: {\n describe: 'Email address for the new account',\n type: 'string',\n demandOption: true,\n },\n region: {\n describe: 'Cloud region (us or eu)',\n choices: ['us', 'eu'] as const,\n default: 'us',\n },\n name: {\n describe: 'Name for the new account',\n type: 'string',\n default: '',\n },\n json: {\n describe:\n 'Emit JSON result to stdout (defaults to true when stdout is not a TTY)',\n type: 'boolean',\n },\n },\n examples: [\n ['wizard provision --email matt+test@posthog.com --region us', ''],\n ['wizard provision --email user@example.com --region eu --json', ''],\n ],\n handler: runProvision,\n};\n\nfunction runProvision(argv: Arguments): void {\n const jsonMode =\n argv.json === undefined ? !process.stdout.isTTY : Boolean(argv.json);\n if (!jsonMode) setUI(new LoggingUI());\n\n void provision({\n email: argv.email as string,\n region: (argv.region as string).toUpperCase() as 'US' | 'EU',\n name: (argv.name as string) ?? '',\n baseUrl: argv.baseUrl as string | undefined,\n jsonMode,\n });\n}\n\ntype ProvisionArgs = {\n email: string;\n region: 'US' | 'EU';\n name: string;\n baseUrl?: string;\n jsonMode: boolean;\n};\n\nasync function provision({\n email,\n region,\n name,\n baseUrl,\n jsonMode,\n}: ProvisionArgs): Promise<void> {\n try {\n const { provisionNewAccount } = await import('@utils/provisioning');\n if (!jsonMode) {\n getUI().log.info(`Provisioning account for ${email} in ${region}...`);\n }\n const result = await provisionNewAccount(email, name, region, { baseUrl });\n emitResult(result, jsonMode);\n process.exit(0);\n } catch (error) {\n emitError(error, jsonMode);\n process.exit(1);\n }\n}\n\nfunction emitResult(result: ProvisioningResult, jsonMode: boolean): void {\n if (jsonMode) {\n process.stdout.write(`${JSON.stringify(result)}\\n`);\n return;\n }\n getUI().log.success('Account provisioned successfully:');\n getUI().log.info(` API Key: ${result.projectApiKey}`);\n getUI().log.info(` Host: ${result.host}`);\n getUI().log.info(` Project ID: ${result.projectId}`);\n getUI().log.info(` Account ID: ${result.accountId}`);\n getUI().log.info(` Access Token: ${result.accessToken}`);\n getUI().log.info(` Refresh Token: ${result.refreshToken}`);\n if (result.personalApiKey) {\n getUI().log.info(` Personal API Key: ${result.personalApiKey}`);\n }\n}\n\nfunction emitError(error: unknown, jsonMode: boolean): void {\n const msg = error instanceof Error ? error.message : String(error);\n const code = msg.includes('already associated')\n ? 'email_exists'\n : 'provisioning_failed';\n if (jsonMode) {\n process.stderr.write(`${JSON.stringify({ error: msg, code })}\\n`);\n return;\n }\n getUI().log.error(`Provisioning failed: ${msg}`);\n}\n","import { isNonInteractiveEnvironment } from '@utils/environment';\nimport { setEntryCommand } from '@utils/links';\nimport { headlessOption, isHeadless, regionOption } from '@lib/headless-mode';\nimport { provisionCommand } from '../provision';\nimport type { Command } from '../command';\n\nexport const basicIntegrationCommand: Command = {\n name: ['$0'],\n description: 'Run the PostHog setup wizard',\n // provision is a one-shot HTTP call tied to the base flow, not a wizard\n // program — it rides under the base command rather than as a peer.\n children: [provisionCommand],\n options: {\n 'install-dir': {\n describe:\n 'Directory to install PostHog in\\nenv: POSTHOG_WIZARD_INSTALL_DIR',\n type: 'string',\n },\n name: {\n describe:\n 'Name for account creation with --ci --signup\\nenv: POSTHOG_WIZARD_NAME',\n type: 'string',\n },\n // ── Internal modes ───────────────────────────────────────────────\n // Hidden from `--help`. See CONTRIBUTING.md for what each one does.\n playground: {\n default: false,\n describe: 'Launch the TUI primitives playground',\n type: 'boolean',\n hidden: true,\n },\n // The experimental headless flag — declared here (and on `audit`) rather\n // than globally. Routed by this command's handler via runHeadlessInstall.\n ...headlessOption,\n ...regionOption,\n },\n check: (argv) => {\n // --playground is the standalone TUI demo; it can't combine with a\n // non-interactive run (either --ci or the experimental headless flag).\n if (argv.playground && (argv.ci || isHeadless(argv))) {\n throw new Error('--playground cannot be combined with a headless run.');\n }\n return true;\n },\n handler: (argv) => {\n // The bare run is the integrate flow.\n setEntryCommand('integrate');\n // Each mode file is loaded only when its branch is taken, so a plain\n // `npx @posthog/wizard` never pulls in the CI or playground paths.\n void (async () => {\n // ── The CI / headless division ───────────────────────────────────\n // --ci (dev/test only) and the experimental headless flag (the\n // published-build, non-interactive path; see @lib/headless-mode) both\n // request a non-interactive install, but route to dedicated entry points\n // — runHeadlessInstall vs runCIInstall (and below them runWizardHeadless\n // vs runWizardCI). Both share one pipeline today but are separate\n // functions end-to-end, so headless can diverge later without touching\n // the CI path or its callers.\n if (isHeadless(argv)) {\n const { runHeadlessInstall } = await import('./ci-install');\n return runHeadlessInstall(argv);\n }\n if (argv.ci) {\n const { runCIInstall } = await import('./ci-install');\n return runCIInstall(argv);\n }\n if (isNonInteractiveEnvironment()) {\n const { failNonInteractive } = await import('./non-interactive');\n return failNonInteractive();\n }\n if (argv.playground) {\n const { runPlayground } = await import('./playground');\n return runPlayground();\n }\n const { runInteractive } = await import('./interactive');\n runInteractive(argv);\n })();\n },\n};\n","/**\n * Ink throws \"Raw mode is not supported\" when stdin has no TTY (piped input,\n * CI, some IDE terminals). That is the only TUI failure the mcp commands\n * degrade to LoggingUI for — any other error from the TUI path is a real bug\n * and must surface rather than be silently swallowed.\n */\nexport function isTUIUnavailable(error: unknown): boolean {\n return (\n error instanceof Error && /raw mode is not supported/i.test(error.message)\n );\n}\n","import type { Arguments } from 'yargs';\nimport { setUI } from '@ui';\nimport { LoggingUI } from '@ui/logging-ui';\nimport { headlessOption, isHeadless } from '@lib/headless-mode';\nimport { Program } from '@lib/programs/program-registry';\nimport { VERSION } from '@lib/version';\nimport type { Command } from '../command';\nimport { isTUIUnavailable } from './tui-availability';\n\nexport const mcpAddCommand: Command = {\n name: 'add',\n description: 'Install PostHog MCP server to supported clients',\n options: {\n local: {\n default: false,\n describe: 'Add local development MCP server (http://localhost:8787)',\n type: 'boolean',\n },\n features: {\n describe: 'Comma-separated list of features to enable (default: all)',\n type: 'string',\n },\n 'api-key': {\n describe: 'PostHog personal API key (phx_xxx) for MCP authentication',\n type: 'string',\n },\n // Reuses the run pipeline's headless flag rather than minting a public one:\n // this stays reversible, and today the only caller is our own CI.\n ...headlessOption,\n },\n handler: runMcpAdd,\n};\n\nfunction runMcpAdd(argv: Arguments): void {\n const features = parseFeatures(argv.features);\n void (async () => {\n const { readApiKeyFromEnv } = await import('@utils/env-api-key');\n const apiKey = (argv.apiKey as string | undefined) || readApiKeyFromEnv();\n const debug = argv.debug as boolean | undefined;\n const localMcp = argv.local as boolean | undefined;\n const args = { local: localMcp, features, apiKey };\n\n // Ink renders into a pipe happily and only throws on raw-mode input, so a\n // non-TTY run reaches the confirm prompt and stalls there rather than\n // hitting the isTUIUnavailable fallback below. The headless flag is the\n // only reliable way to install from a script.\n if (isHeadless(argv)) {\n await runHeadlessAdd(args);\n return;\n }\n\n try {\n const { startTUI } = await import('@ui/tui/start-tui');\n const { buildSession } = await import('@lib/wizard-session');\n const tui = startTUI(VERSION, Program.McpAdd);\n tui.store.session = buildSession({\n debug,\n localMcp,\n mcpFeatures: features,\n apiKey,\n baseUrl: argv.baseUrl as string | undefined,\n });\n } catch (error) {\n if (!isTUIUnavailable(error)) throw error;\n await runHeadlessAdd(args);\n }\n })();\n}\n\nasync function runHeadlessAdd(args: {\n local?: boolean;\n features?: string[];\n apiKey?: string;\n}): Promise<void> {\n setUI(new LoggingUI());\n const { addMCPServerToClientsStep } = await import(\n '@steps/add-mcp-server-to-clients/index'\n );\n // Never forwards `ci`: headless implies session.ci elsewhere, and the step\n // reads that as \"skip MCP entirely\" — the opposite of what we're here to do.\n const { installed, failed } = await addMCPServerToClientsStep(args);\n // A scripted caller has no screen to read, so this has to be an exit code.\n // Any failure counts, not just a total wipeout: the step installs to every\n // detected client, so one succeeding would otherwise mask the rest.\n if (failed.length > 0 || installed.length === 0) process.exitCode = 1;\n}\n\nfunction parseFeatures(raw: unknown): string[] | undefined {\n if (typeof raw !== 'string') return undefined;\n return raw\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n}\n","import type { Arguments } from 'yargs';\nimport { setUI } from '@ui';\nimport { LoggingUI } from '@ui/logging-ui';\nimport { headlessOption, isHeadless } from '@lib/headless-mode';\nimport { Program } from '@lib/programs/program-registry';\nimport { VERSION } from '@lib/version';\nimport type { Command } from '../command';\nimport { isTUIUnavailable } from './tui-availability';\n\nexport const mcpRemoveCommand: Command = {\n name: 'remove',\n description: 'Remove PostHog MCP server from supported clients',\n options: {\n local: {\n default: false,\n describe: 'Remove local development MCP server (http://localhost:8787)',\n type: 'boolean',\n },\n // Mirrors `mcp add` — see the note there on reusing the run pipeline's flag.\n ...headlessOption,\n },\n handler: runMcpRemove,\n};\n\nfunction runMcpRemove(argv: Arguments): void {\n void (async () => {\n const debug = argv.debug as boolean | undefined;\n const localMcp = argv.local as boolean | undefined;\n\n // See the note in add.ts: a non-TTY run stalls on the confirm prompt\n // instead of falling back, so scripts need an explicit flag.\n if (isHeadless(argv)) {\n await runHeadlessRemove(localMcp);\n return;\n }\n\n try {\n const { startTUI } = await import('@ui/tui/start-tui');\n const { buildSession } = await import('@lib/wizard-session');\n const tui = startTUI(VERSION, Program.McpRemove);\n tui.store.session = buildSession({\n debug,\n localMcp,\n baseUrl: argv.baseUrl as string | undefined,\n });\n } catch (error) {\n // Same guard as `mcp add`: only a missing TTY falls back to LoggingUI,\n // so a genuine TUI bug surfaces instead of looking like a plain shell.\n if (!isTUIUnavailable(error)) throw error;\n await runHeadlessRemove(localMcp);\n }\n })();\n}\n\n/** No exit code on an empty result: nothing to remove is the requested end state. */\nasync function runHeadlessRemove(local?: boolean): Promise<void> {\n setUI(new LoggingUI());\n const { removeMCPServerFromClientsStep } = await import(\n '@steps/add-mcp-server-to-clients/index'\n );\n await removeMCPServerFromClientsStep({ local });\n}\n","import type { Arguments } from 'yargs';\nimport { getUI, setUI } from '@ui';\nimport { LoggingUI } from '@ui/logging-ui';\nimport { Program } from '@lib/programs/program-registry';\nimport { VERSION } from '@lib/version';\nimport { ErrorCodes } from '@lib/errors';\nimport { emitWizardError } from '@lib/errors';\nimport type { Command } from '../command';\n\nexport const mcpTutorialCommand: Command = {\n name: 'tutorial',\n description: 'Try the PostHog MCP with your agent (no install needed)',\n options: {\n local: {\n default: false,\n describe:\n 'Point the tutorial at the local MCP server (http://localhost:8787)',\n type: 'boolean',\n },\n },\n handler: runMcpTutorial,\n};\n\nfunction runMcpTutorial(argv: Arguments): void {\n void (async () => {\n const debug = argv.debug as boolean | undefined;\n const localMcp = argv.local as boolean | undefined;\n\n try {\n const { startTUI } = await import('@ui/tui/start-tui');\n const { buildSession } = await import('@lib/wizard-session');\n const tui = startTUI(VERSION, Program.McpTutorial);\n tui.store.session = buildSession({\n debug,\n localMcp,\n baseUrl: argv.baseUrl as string | undefined,\n });\n } catch (err) {\n // TUI unavailable — the tutorial has no headless fallback.\n setUI(new LoggingUI());\n getUI().log.error(\n `The MCP tutorial requires an interactive terminal. ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n emitWizardError({\n code: ErrorCodes.CliInteractiveRequired,\n message: 'The MCP tutorial requires an interactive terminal.',\n });\n process.exit(1);\n }\n })();\n}\n","import { mcpAddCommand } from './add';\nimport { mcpRemoveCommand } from './remove';\nimport { mcpTutorialCommand } from './tutorial';\nimport type { Command } from '../command';\n\nexport const mcpCommand: Command = {\n name: 'mcp',\n description: 'MCP server management commands',\n children: [mcpAddCommand, mcpRemoveCommand, mcpTutorialCommand],\n};\n","/**\n * `--no-telemetry` flips `telemetry: false` via yargs negation;\n * `POSTHOG_WIZARD_NO_TELEMETRY` is honoured separately so the env-var\n * form documented in the README keeps working.\n */\nexport function resolveNoTelemetry(options: Record<string, unknown>): boolean {\n if (options.telemetry === false) return true;\n const env = process.env.POSTHOG_WIZARD_NO_TELEMETRY;\n if (env == null || env === '') return false;\n const norm = env.toLowerCase();\n return norm !== '0' && norm !== 'false';\n}\n","import { VERSION } from '@lib/version';\nimport { logToFile, getLogFilePath } from '@utils/debug';\nimport { runAgent } from '@lib/agent/agent-runner';\nimport { authenticate } from '@lib/agent/runner/shared/authenticate';\nimport { getProgramConfig } from '@lib/programs/program-registry';\nimport { getAuditChecks } from '@lib/programs/audit/types';\nimport { maybeStampAiSdkDetected } from '@lib/programs/posthog-integration/detect';\nimport type { ProgramConfig } from '@lib/programs/program-step';\nimport type { Harness, Sequence } from '@lib/constants';\nimport type { startTUI as StartTUIFn } from '@ui/tui/start-tui';\nimport type { WizardStore } from '@ui/tui/store';\nimport { OutroKind, type WizardSession } from '@lib/wizard-session';\nimport type { TaskStreamPush as TaskStreamPushClass } from '@lib/task-stream/task-stream-push';\nimport { resolveNoTelemetry } from './resolve-no-telemetry';\nimport { checkLocalServices, getLocalDev } from '@lib/local-dev';\nimport { runCleanups } from '@utils/wizard-abort';\nimport { classifyRunFailure, emitWizardError } from '@lib/errors';\nimport { isRunFailure } from '@ui/mint-failure';\nimport { getUI } from '@ui';\nimport { analytics } from '@utils/analytics';\nimport { join } from 'node:path';\n\nconst WIZARD_VERSION = VERSION;\n\ntype Step = ProgramConfig['steps'][number];\n\n/** The session a run step's agent runs in: scoped to the step's target dir\n * (e.g. a monorepo sub-app) with its own framework context, after any prep.\n * A step without `targetDir` runs in the live session, unchanged.\n * The frameworkContext copy is shallow and unfiltered — name keys per owning program. */\nasync function prepareRunSession(\n step: Step,\n live: WizardSession,\n): Promise<WizardSession> {\n const session = step.targetDir\n ? {\n ...live,\n installDir: step.targetDir(live),\n frameworkContext: { ...live.frameworkContext },\n }\n : live;\n if (step.onRunPrep) await step.onRunPrep(session);\n return session;\n}\n\n/** Advance one step of a composed run to completion: the auth screen\n * authenticates (every later run reuses it); a step carrying its own `run`\n * thunk runs that agent in its dir and is recorded in `completedRuns`; the\n * host program's own run screen runs `config.run`; any other screen waits for\n * the user to satisfy `isComplete`. */\nasync function advanceStep(\n step: Step,\n store: WizardStore,\n config: ProgramConfig,\n): Promise<void> {\n if (step.screenId === 'auth') {\n await authenticate(store.session, config.id);\n maybeStampAiSdkDetected(store.session);\n } else if (step.run) {\n await step.run(await prepareRunSession(step, store.session));\n store.completeRunStep(step.id);\n } else if (step.screenId === 'run') {\n await runAgent(config, await prepareRunSession(step, store.session));\n } else if (step.isComplete) {\n await store.waitUntil(step.isComplete);\n }\n}\n\n/**\n * Run a full wizard program in the TUI. Handles the full lifecycle: start TUI,\n * build session, run detection, wait for intro gate, execute the\n * agent pipeline, wait for outro dismissal, then exit.\n */\nexport function runWizard(\n config: ProgramConfig,\n options: Record<string, unknown>,\n): void {\n let tui: ReturnType<typeof StartTUIFn> | null = null;\n let taskStream: TaskStreamPushClass | null = null;\n let onSignal: (() => void) | null = null;\n let exitInProgress = false;\n\n void (async () => {\n try {\n const installDir = (options.installDir as string) || process.cwd();\n\n const { startTUI } = await import('@ui/tui/start-tui');\n const { buildSession, RunPhase } = await import('@lib/wizard-session');\n const { TaskStreamPush } = await import('@lib/task-stream/index');\n const { PostHogDestination } = await import(\n '@lib/task-stream/destinations/posthog'\n );\n const { createFileDestination } = await import(\n '@lib/task-stream/destinations/file'\n );\n\n // Before the TUI mounts: once Ink owns the alt screen, anything written\n // to it is wiped on unmount (see the catch block below), so an abort here\n // would leave the user on a loading screen with no message.\n const local = getLocalDev();\n const localServicesError = await checkLocalServices({\n ...local,\n // An explicit --base-url wins over --local-posthog (see buildSession),\n // so don't probe :8010 when one was given.\n localPosthog: local.localPosthog && !options.baseUrl,\n });\n if (localServicesError) {\n const { wizardAbort } = await import('@utils/wizard-abort');\n await wizardAbort({ message: localServicesError });\n return;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n tui = startTUI(WIZARD_VERSION, config.id as any);\n const activeTui = tui;\n\n const session = buildSession({\n debug: options.debug as boolean | undefined,\n localDev: options.localDev as boolean | undefined,\n localMcp: options.localMcp as boolean | undefined,\n localPosthog: options.localPosthog as boolean | undefined,\n installDir,\n ci: false,\n signup: options.signup as boolean | undefined,\n apiKey: options.apiKey as string | undefined,\n projectId: options.projectId as string | undefined,\n email: options.email as string | undefined,\n baseUrl: options.baseUrl as string | undefined,\n benchmark: options.benchmark as boolean | undefined,\n yaraReport: options.yaraReport as boolean | undefined,\n noTelemetry: resolveNoTelemetry(options),\n harness: options.harness as Harness | undefined,\n sequence: options.sequence as Sequence | undefined,\n model: options.model as string | undefined,\n integrate: options.integrate as boolean | undefined,\n captureAio: options.captureAio as boolean | undefined,\n });\n session.programLabel = config.id;\n if (options.skillId) {\n session.skillId = options.skillId as string;\n } else if (config.skillId) {\n session.skillId = config.skillId;\n }\n\n activeTui.store.session = session;\n\n // Flush a terminal-phase push on Ctrl-C so the web app sees the\n // run ended in error rather than hanging on the last \"running\"\n // snapshot. Registered before the stream exists: Ctrl-C on the intro\n // must still restore the terminal and run the cleanups, and there is\n // no run to report yet.\n let signalled = false;\n onSignal = (): void => {\n if (signalled || exitInProgress) return;\n signalled = true;\n logToFile('[run-wizard] signal received, flushing task stream');\n // Run cleanups synchronously first — settings restore is sync fs work\n // and must complete even if the stream shutdown below times out.\n runCleanups();\n if (activeTui.store.session.runPhase === RunPhase.Running) {\n activeTui.store.setRunPhase(RunPhase.Error);\n }\n const teardown = (): void => {\n try {\n activeTui.unmount();\n } catch {\n // terminal may already be torn down\n }\n process.exit(130);\n };\n const stream = taskStream;\n if (!stream) {\n teardown();\n return;\n }\n void stream\n .shutdown(2000)\n .catch((e) =>\n logToFile('[run-wizard] task stream shutdown error on signal:', e),\n )\n .finally(teardown);\n };\n process.on('SIGINT', onSignal);\n process.on('SIGTERM', onSignal);\n\n for (;;) {\n await activeTui.store.runReadyHooks();\n // Settle the pre-run screens; `integration-check` is a no-op gate here.\n await activeTui.store.getGate('intro');\n\n const active = activeTui.store.router.activeProgram;\n if (active === config.id) break;\n config = getProgramConfig(active);\n }\n\n // After the switch loop, not before: the stream bakes its program id,\n // session id, and event-plan path in at construction, so a stream built\n // for the launch program would report the whole run under a program the\n // user left on the intro screen. Nothing before this point produces a\n // task to push.\n // Consent gates the push, not the dump: `--no-telemetry` still logs.\n const fileDestination = createFileDestination(options.taskStreamLog);\n const destinations = [\n ...(session.noTelemetry\n ? []\n : [\n new PostHogDestination({\n getCredentials: () => activeTui.store.session.credentials,\n onError: (err) => logToFile('[task-stream-push]', err.message),\n }),\n ]),\n ...(fileDestination ? [fileDestination] : []),\n ];\n const taskStreamEnabled = destinations.length > 0;\n const activeStream = new TaskStreamPush({\n store: activeTui.store,\n programId: config.streamWorkflowId ?? config.id,\n destinations,\n eventPlanPath: config.eventPlanFile\n ? join(session.installDir, config.eventPlanFile)\n : undefined,\n auditChecks: config.auditLedgerFile\n ? () => getAuditChecks(activeTui.store.session)\n : undefined,\n enabled: taskStreamEnabled,\n });\n taskStream = activeStream;\n activeStream.attach();\n\n await activeTui.store.getGate('integration-check');\n await activeTui.store.getGate('health-check');\n\n const skipAgent = config.run == null;\n const shown = (s: ProgramConfig['steps'][number]) =>\n !s.show || s.show(activeTui.store.session);\n\n if (config.steps.some((s) => s.run || s.targetDir)) {\n // A composed program: its step list splices in run steps that carry\n // their own agent (self-driving runs the integration before its own\n // run), or scopes its own run to a picked project (error-tracking).\n // Walk the list once, advancing each step to completion.\n for (const step of config.steps) {\n if (step.screenId === 'outro') break; // run-completion wait owns it\n if (shown(step)) await advanceStep(step, activeTui.store, config);\n }\n } else if (skipAgent) {\n const { getOrAskForProjectData } = await import('@utils/setup-utils');\n const { projectApiKey, host, accessToken, projectId } =\n await getOrAskForProjectData({\n signup: session.signup,\n ci: session.ci,\n apiKey: session.apiKey,\n projectId: session.projectId,\n baseUrl: session.baseUrl,\n programId: config.id,\n });\n activeTui.store.setCredentials({\n accessToken,\n projectApiKey,\n host,\n projectId,\n });\n } else {\n try {\n await runAgent(config, activeTui.store.session);\n } catch (error) {\n // The run threw before its own error handling rendered an outro.\n // Show the handoff screen and let the user's agent take over.\n const failure = classifyRunFailure(error);\n logToFile('[run-wizard] run failed, handing off:', error);\n runCleanups();\n analytics.captureException(\n error instanceof Error ? error : new Error(String(error)),\n { error_code: failure.code },\n );\n getUI().outroError({\n kind: OutroKind.Error,\n errorCode: failure.code,\n message: failure.message,\n });\n }\n }\n\n const runFailed = isRunFailure(activeTui.store.session);\n await activeTui.store.waitUntil((s) => {\n if (s.mintHandoff === 'exit') return true;\n if (skipAgent && !runFailed) return s.outroDismissed;\n return s.skillsComplete;\n });\n\n exitInProgress = true;\n await activeStream.shutdown(2000);\n process.off('SIGINT', onSignal);\n process.off('SIGTERM', onSignal);\n if (runFailed) await analytics.shutdown('error');\n activeTui.unmount();\n process.exit(runFailed ? 1 : 0);\n } catch (err) {\n // File-log first — the cleanup below can throw or exit.\n logToFile('[run-wizard] FATAL:', err);\n // Run cleanups before anything async so settings are restored even if\n // the stream shutdown hangs.\n runCleanups();\n // The task-stream debounce timer keeps the event loop alive, so\n // we have to drain it before exiting on the error path.\n exitInProgress = true;\n if (onSignal) {\n process.off('SIGINT', onSignal);\n process.off('SIGTERM', onSignal);\n }\n if (taskStream) {\n try {\n await taskStream.shutdown(2000);\n } catch {\n // ignore\n }\n }\n if (tui) {\n try {\n tui.unmount();\n } catch {\n // ignore\n }\n }\n // Print after unmount: anything printed into the alt screen is wiped.\n // A coded failure is a decision with its own message; anything else is\n // unexpected and goes out whole.\n const failure = classifyRunFailure(err);\n if (failure.coded) {\n // eslint-disable-next-line no-console\n console.error(failure.message);\n } else {\n // eslint-disable-next-line no-console\n console.error('Wizard run failed:', err);\n }\n // eslint-disable-next-line no-console\n console.error(`Full logs: ${getLogFilePath()}`);\n emitWizardError({ code: failure.code, message: failure.message });\n process.exit(1);\n }\n })();\n}\n","import { POSTHOG_DOCS_URL, type Harness, type Sequence } from '@lib/constants';\nimport {\n checkLocalServices,\n getLocalDev,\n POSTHOG_LOCAL_URL,\n} from '@lib/local-dev';\nimport type { CloudRegion } from '@utils/types';\nimport { getUI, setUI } from '@ui';\nimport { LoggingUI } from '@ui/logging-ui';\nimport type { ProgramConfig } from '@lib/programs/program-step';\nimport { getAuditChecks } from '@lib/programs/audit/types';\nimport { analytics } from '@utils/analytics';\nimport { resolveNoTelemetry } from './resolve-no-telemetry';\nimport type { WizardStore } from '@ui/tui/store';\nimport type { TaskStreamPush } from '@lib/task-stream/task-stream-push';\nimport { join } from 'node:path';\nimport {\n ErrorCodes,\n classifyRunFailure,\n detectErrorCode,\n emitWizardError,\n} from '@lib/errors';\nimport type { OutroData, RunPhase as RunPhaseT } from '@lib/wizard-session';\n\n/**\n * The two non-interactive run modes. Both drive the same pipeline today; the\n * mode is threaded explicitly (rather than sniffed from a flag) so the dispatch\n * picks an entry point — runWizardCI vs runWizardHeadless — and this core stays\n * mode-agnostic except at the few documented forks. The string values double as\n * the analytics `build` tag, so they segment runs in analytics and on\n * LLM-gateway traces (which read analytics.build).\n */\nexport type NonInteractiveMode = 'ci' | 'headless';\n\n/** User-facing label for a non-interactive mode. */\nfunction modeLabel(mode: NonInteractiveMode): string {\n return mode === 'headless' ? 'Headless' : 'CI';\n}\n\n/** The credentials every non-interactive mode accepts, for error messages. */\nexport const API_KEY_HINT =\n 'personal API key phx_xxx or wizard-app OAuth access token pha_xxx';\n\n/**\n * The single non-interactive validation layer: requires api-key and\n * install-dir. Every non-interactive entry point routes through\n * `runNonInteractive`, so this is the one place these checks live. UI must be\n * initialized before calling.\n */\nexport function validateNonInteractiveOptions(\n options: Record<string, unknown>,\n mode: NonInteractiveMode,\n): void {\n const label = modeLabel(mode);\n if (!options.apiKey) {\n getUI().intro('PostHog Wizard');\n getUI().log.error(`${label} mode requires --api-key (${API_KEY_HINT})`);\n emitWizardError({\n code: ErrorCodes.ArgsMissingApiKey,\n message: `${label} mode requires --api-key (${API_KEY_HINT})`,\n });\n process.exit(1);\n }\n if (!options.installDir) {\n getUI().intro('PostHog Wizard');\n getUI().log.error(\n `${label} mode requires --install-dir (directory to install in)`,\n );\n emitWizardError({\n code: ErrorCodes.ArgsMissingInstallDir,\n message: `${label} mode requires --install-dir`,\n });\n process.exit(1);\n }\n}\n\n/**\n * Non-interactive pipeline shared by CI (`runWizardCI`) and headless\n * (`runWizardHeadless`) runs.\n *\n * Validates flags, builds a `ci:true` session, runs `config.ciPreRun` (or the\n * program's `onReady` hooks by default), executes `runAgent`, and routes any\n * failure through `wizardAbort`. `wizardAbort` owns all exits — never add a\n * raw `process.exit` here.\n *\n * `mode` is the only difference between the two callers today (it sets the\n * analytics build tag and the user-facing label). Keeping it a parameter is\n * what lets CI and headless share this body now and diverge later — branch on\n * `mode` here, or stop sharing this function entirely.\n */\nexport function runNonInteractive(\n config: ProgramConfig,\n options: Record<string, unknown>,\n mode: NonInteractiveMode,\n): void {\n setUI(new LoggingUI());\n validateNonInteractiveOptions(options, mode);\n // Upgrade the build tag so runs segment cleanly in analytics (and on\n // LLM-gateway traces, which read analytics.build). A published headless run\n // (cloud / CI/CD) tags 'headless'; a dev/test `--ci` run upgrades 'dev' to\n // 'ci'. The mode string is the tag value.\n analytics.setTag('build', mode);\n\n void (async () => {\n const path = await import('path');\n const { buildSession, RunPhase, OutroKind } = await import(\n '@lib/wizard-session'\n );\n const { readEnvironment } = await import('@utils/environment');\n const { readApiKeyFromEnv } = await import('@utils/env-api-key');\n const { configureLogFileFromEnvironment, logToFile } = await import(\n '@utils/debug'\n );\n const { wizardAbort, WizardError } = await import('@utils/wizard-abort');\n\n configureLogFileFromEnvironment();\n\n const env = readEnvironment();\n const apiKey =\n (options.apiKey as string) ?? readApiKeyFromEnv() ?? undefined;\n const installDir = path.isAbsolute(options.installDir as string)\n ? (options.installDir as string)\n : path.join(process.cwd(), options.installDir as string);\n\n const session = buildSession({\n debug: options.debug as boolean | undefined,\n installDir,\n ci: true,\n signup: options.signup as boolean | undefined,\n localDev: options.localDev as boolean | undefined,\n localMcp: options.localMcp as boolean | undefined,\n localPosthog: options.localPosthog as boolean | undefined,\n apiKey,\n email: options.email as string | undefined,\n projectId: options.projectId as string | undefined,\n baseUrl: options.baseUrl as string | undefined,\n benchmark: options.benchmark as boolean | undefined,\n yaraReport: options.yaraReport as boolean | undefined,\n noTelemetry: resolveNoTelemetry(options),\n harness: options.harness as Harness | undefined,\n sequence: options.sequence as Sequence | undefined,\n model: options.model as string | undefined,\n captureAio: options.captureAio as boolean | undefined,\n ...env,\n // After the spread: yargs already resolves flag-over-env for --region,\n // so the parsed value must win over the raw env bag.\n region: (options.region ?? env.region) as CloudRegion | undefined,\n });\n session.programLabel = config.id;\n if (config.skillId) {\n session.skillId = config.skillId;\n }\n const runDef = typeof config.run === 'object' ? config.run : null;\n\n getUI().intro('Welcome to the PostHog setup wizard');\n getUI().log.info(`Running ${config.id} in ${modeLabel(mode)} mode`);\n\n // Before auth: a dead local PostHog otherwise surfaces as \"Failed to fetch\n // user data\". Aborts even non-interactively — a CI run pointed at a local\n // server that isn't there is testing nothing.\n const localServicesError = await checkLocalServices({\n ...getLocalDev(),\n localMcp: session.localMcp,\n localPosthog: session.baseUrl === POSTHOG_LOCAL_URL,\n });\n if (localServicesError) {\n await wizardAbort({\n code: ErrorCodes.EnvLocalServicesDown,\n message: localServicesError,\n });\n return;\n }\n\n // Headless streams run state to the PostHog backend so the web app can show\n // live progress. Reuses the interactive TaskStreamPush + WizardStore (no Ink\n // render): HeadlessUI keeps LoggingUI's output and feeds task updates into\n // the store; this runner drives the phase transitions. Headless pushes to\n // PostHog (the web app is that run's only UI); `--ci` is synthetic, so it\n // dumps locally and pushes nothing. Telemetry consent gates the push only.\n let store: WizardStore | null = null;\n let taskStream: TaskStreamPush | null = null;\n {\n const { WizardStore } = await import('@ui/tui/store');\n const { HeadlessUI } = await import('@ui/headless-ui');\n const { TaskStreamPush, PostHogDestination, createFileDestination } =\n await import('@lib/task-stream/index');\n\n // `''` resolves to the default path, so `--ci` always dumps.\n const logTarget =\n mode === 'ci' ? options.taskStreamLog ?? '' : options.taskStreamLog;\n const fileDestination = createFileDestination(logTarget);\n const posthogDestination =\n mode === 'headless' && !session.noTelemetry\n ? new PostHogDestination({\n getCredentials: () => session.credentials,\n onError: (e) => logToFile('[headless task-stream]', e.message),\n })\n : null;\n const destinations = [\n ...(posthogDestination ? [posthogDestination] : []),\n ...(fileDestination ? [fileDestination] : []),\n ];\n\n const headlessStore = new WizardStore(config.id);\n store = headlessStore;\n headlessStore.session = session;\n setUI(new HeadlessUI(headlessStore));\n taskStream = new TaskStreamPush({\n store: headlessStore,\n programId: config.streamWorkflowId ?? config.id,\n destinations,\n eventPlanPath: config.eventPlanFile\n ? join(session.installDir, config.eventPlanFile)\n : undefined,\n auditChecks: config.auditLedgerFile\n ? () => getAuditChecks(headlessStore.session)\n : undefined,\n enabled: destinations.length > 0,\n });\n taskStream.attach();\n headlessStore.setRunPhase(RunPhase.Running);\n if (fileDestination) {\n logToFile(`[task-stream] ${mode} dump: ${fileDestination.path}`);\n }\n }\n\n // wizardAbort exits via process.exit, so flush the terminal phase before any\n // exit. No-op for CI.\n const settleStream = async (\n phase: RunPhaseT,\n outroData?: OutroData,\n ): Promise<void> => {\n if (!store || !taskStream) return;\n if (outroData) store.setOutroData(outroData);\n store.setRunPhase(phase);\n await taskStream.shutdown(2000);\n };\n\n try {\n if (mode === 'ci') {\n const { configureGatewayFromCIEnvironment } = await import(\n '@lib/gateway-session'\n );\n configureGatewayFromCIEnvironment(\n Number(session.projectId),\n session.region ?? 'us',\n );\n }\n if (config.ciPreRun) {\n await config.ciPreRun(session);\n } else {\n const readyCtx = {\n session,\n setFrameworkContext: (key: string, value: unknown) => {\n session.frameworkContext[key] = value;\n },\n setFrameworkConfig: () => undefined,\n setDetectedFramework: () => undefined,\n // Non-interactive session is a plain object (no nanostore\n // copy-on-write), so direct assignment is safe here.\n setSkillId: (skillId: string | null) => {\n session.skillId = skillId;\n },\n setUnsupportedVersion: (info: {\n current: string;\n minimum: string;\n docsUrl: string;\n }) => {\n session.unsupportedVersion = info;\n },\n addDiscoveredFeature: () => undefined,\n setDetectionComplete: () => undefined,\n setPosthogSdkDetected: (detected: boolean) => {\n session.posthogSdkDetected = detected;\n },\n };\n for (const step of config.steps) {\n if (step.onReady) {\n await step.onReady(readyCtx);\n }\n }\n\n const detectError = session.frameworkContext.detectError as\n | { kind: string; [k: string]: unknown }\n | undefined;\n if (session.unsupportedVersion) {\n const { current, minimum, docsUrl } = session.unsupportedVersion;\n const message = `Detected framework version ${current} is not supported. Minimum supported version is ${minimum}.`;\n await settleStream(RunPhase.Error, {\n kind: OutroKind.Error,\n message,\n errorCode: ErrorCodes.DetectUnsupportedVersion,\n });\n await wizardAbort({\n code: ErrorCodes.DetectUnsupportedVersion,\n message: `${message}\\n\\nSee ${docsUrl}`,\n error: new WizardError(\n `${config.id} unsupported framework version`,\n {\n integration: config.id,\n current,\n minimum,\n },\n ErrorCodes.DetectUnsupportedVersion,\n ),\n });\n }\n if (detectError) {\n const code = detectErrorCode(detectError.kind);\n const detectKind = detectError.kind;\n // `kind` stays in the detail: several kinds share one code, so it is\n // the only thing telling a host which precondition actually failed.\n const detail = { ...detectError };\n await settleStream(RunPhase.Error, {\n kind: OutroKind.Error,\n message: `Prerequisites not met: ${detectKind}`,\n errorCode: code,\n errorDetail: detail,\n });\n await wizardAbort({\n code,\n detail,\n message: `Prerequisites not met: ${detectKind}\\n\\nSee ${\n runDef?.docsUrl ?? POSTHOG_DOCS_URL\n }`,\n error: new WizardError(\n `${config.id} prerequisites failed`,\n {\n integration: config.id,\n detect_error_kind: detectKind,\n },\n code,\n ),\n });\n }\n }\n\n const { runAgent } = await import('@lib/agent/agent-runner');\n await runAgent(config, session);\n await settleStream(RunPhase.Completed);\n } catch (error) {\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n const errorStack =\n error instanceof Error && error.stack ? error.stack : undefined;\n\n logToFile(`[${mode}] ERROR: ${errorMessage}`);\n if (errorStack) logToFile(`[${mode}] STACK: ${errorStack}`);\n\n const debugInfo = session.debug && errorStack ? `\\n\\n${errorStack}` : '';\n const docsUrl =\n session.frameworkConfig?.metadata.docsUrl ??\n runDef?.docsUrl ??\n POSTHOG_DOCS_URL;\n // A coded failure is a decision with its own message; anything else is\n // unexpected and gets the generic framing.\n const failure = classifyRunFailure(error);\n await settleStream(RunPhase.Error, {\n kind: OutroKind.Error,\n message: errorMessage,\n errorCode: failure.code,\n });\n await wizardAbort({\n code: failure.code,\n message: failure.coded\n ? `${errorMessage}${debugInfo}`\n : `Something went wrong: ${errorMessage}\\n\\nYou can read the documentation at ${docsUrl} to set up manually.${debugInfo}`,\n error: error as Error,\n });\n }\n })().catch((error: unknown) => {\n emitWizardError({\n code: ErrorCodes.InternalUnhandled,\n message: error instanceof Error ? error.message : String(error),\n });\n process.exit(1);\n });\n}\n","import type { ProgramConfig } from '@lib/programs/program-step';\nimport { runNonInteractive } from './run-non-interactive';\n\n/**\n * CI-mode entry point (`--ci`, dev/test builds). A thin shell over the shared\n * non-interactive pipeline — see `runNonInteractive`. Kept as its own function\n * so CI and headless (`runWizardHeadless`) can diverge without re-threading the\n * many callers that route here.\n */\nexport function runWizardCI(\n config: ProgramConfig,\n options: Record<string, unknown>,\n): void {\n runNonInteractive(config, options, 'ci');\n}\n","import type { ProgramConfig } from '@lib/programs/program-step';\nimport { runNonInteractive } from './run-non-interactive';\n\n/**\n * Headless entry point (the experimental published-build, non-interactive run\n * path; see @lib/headless-mode). A thin shell over the shared non-interactive\n * pipeline — see `runNonInteractive`. Today it behaves exactly like\n * `runWizardCI`; it exists as a separate function so headless can diverge later\n * (its own auth handling, telemetry, prompts, …) without touching CI or its\n * callers. Diverge by branching on the mode inside `runNonInteractive`, or by\n * giving this function its own body.\n */\nexport function runWizardHeadless(\n config: ProgramConfig,\n options: Record<string, unknown>,\n): void {\n runNonInteractive(config, options, 'headless');\n}\n","/**\n * Per-command options shared by every skill-based program command\n * (`audit events`, `migrate statsig`, `revenue`, `source-maps`, …).\n *\n * Only flags unique to skill commands live here. Global flags are declared\n * once in `wizard.ts` — both in `GLOBAL_OPTIONS` and, for the dev-only ones,\n * the `Wizard` constructor — and apply to every command automatically.\n */\nexport const skillProgramOptions = {\n 'install-dir': {\n describe: 'Directory to install in',\n type: 'string' as const,\n },\n};\n","import type { Arguments, Options } from 'yargs';\n\nimport { runWizard, runWizardCI, runWizardHeadless } from '@lib/runners';\nimport { isHeadless } from '@lib/headless-mode';\nimport type { ProgramConfig } from '@lib/programs/program-step';\n\nimport { skillProgramOptions } from '../skill-program-options';\nimport { ErrorCodes } from '@lib/errors';\nimport { emitWizardError } from '@lib/errors';\n\n/**\n * Dispatch a parsed yargs invocation to the wizard runner. Applies the\n * program's `mapCliOptions` transform, then routes to `runWizardHeadless`,\n * `runWizardCI`, or `runWizard` based on the headless / `--ci` flags.\n *\n * Every command file used to inline this; the factories call it instead.\n */\n/**\n * Run a command's async body as fire-and-forget while still surfacing failures.\n * yargs handlers are synchronous, so async work kicks off a detached promise —\n * without this, a rejection becomes an unhandled promise rejection (no message,\n * wrong exit code). This awaits the work and turns any error into a clean\n * message + non-zero exit.\n */\nexport function runCommandHandler(work: () => void | Promise<void>): void {\n void (async () => {\n try {\n await work();\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`\\n\\x1b[1;91m✖ ${msg}\\x1b[0m\\n\\n`);\n emitWizardError({ code: ErrorCodes.InternalUnhandled, message: msg });\n process.exit(1);\n }\n })();\n}\n\nexport function dispatchProgram(config: ProgramConfig, argv: Arguments): void {\n const argvRecord: Record<string, unknown> = { ...argv };\n const extras = config.mapCliOptions?.(argvRecord) ?? {};\n const options = { ...argvRecord, ...extras };\n if (isHeadless(options)) {\n // Same non-interactive pipeline `--ci` uses; validation (api-key,\n // install-dir, region) is owned by runNonInteractive.\n runWizardHeadless(config, options);\n } else if (options.ci) {\n runWizardCI(config, options);\n } else {\n runWizard(config, options);\n }\n}\n\n/**\n * Merge the standard skill-program flags (`--debug`, `--install-dir`, etc.)\n * with any program-specific options declared on `cliOptions`.\n *\n * Program-specific options shadow the standard ones — that's intentional, so\n * a program can override a default flag if it ever needs to.\n */\nexport function mergeCommandOptions(\n config: ProgramConfig,\n): Record<string, Options> {\n return {\n ...skillProgramOptions,\n ...((config.cliOptions ?? {}) as Record<string, Options>),\n };\n}\n","import type { ProgramConfig } from '@lib/programs/program-step';\n\nimport type { Command } from '../command';\n\nimport { dispatchProgram, mergeCommandOptions } from './shared';\n\nexport interface NativeCommandFactoryOpts {\n /** Subcommands nested under this command. */\n children?: readonly Command[];\n}\n\n/**\n * Build a yargs `Command` from a wizard-native `ProgramConfig`.\n *\n * Collapses the previously duplicated boilerplate (read `config.command`,\n * merge skill-program flags with program-specific options, dispatch via\n * `runWizard` / `runWizardCI`) into a single call.\n */\nexport function nativeCommandFactory(\n config: ProgramConfig,\n opts: NativeCommandFactoryOpts = {},\n): Command {\n if (!config.command) {\n throw new Error(\n `nativeCommandFactory: program \"${config.id}\" has no \\`command\\` — wizard-native programs must declare a CLI name`,\n );\n }\n return {\n name: config.command,\n description: config.description,\n options: mergeCommandOptions(config),\n children: opts.children,\n handler: (argv) => dispatchProgram(config, argv),\n };\n}\n","import { mcpAnalyticsConfig } from '@lib/programs/mcp-analytics/index';\n\nimport type { Command } from './command';\nimport { nativeCommandFactory } from './factories/native-command-factory';\n\n/**\n * `wizard mcp-analytics` — flat skill command, instrument-an-MCP-server today.\n *\n * Distinct from `wizard mcp add`: this instruments the user's own MCP server\n * with the `@posthog/mcp` SDK, rather than installing the PostHog MCP server\n * into a coding agent. Stays flat while instrumenting is the only action.\n */\nexport const mcpAnalyticsCommand: Command =\n nativeCommandFactory(mcpAnalyticsConfig);\n","import { replayVisionConfig } from '@lib/programs/replay-vision/index';\n\nimport type { Command } from './command';\nimport { nativeCommandFactory } from './factories/native-command-factory';\n\n/**\n * `wizard replay-vision` — flat skill command, set up Replay vision today.\n *\n * Enables session replay recording and creates vision scanners tailored to\n * the product's key flows. Runs the `replay-vision` orchestrator flow, which\n * reuses the integration-v2 install/init mini-agents when the repo has no\n * PostHog integration yet.\n */\nexport const replayVisionCommand: Command =\n nativeCommandFactory(replayVisionConfig);\n","import { aiObservabilityConfig } from '@lib/programs/ai-observability/index';\n\nimport type { Command } from './command';\nimport { nativeCommandFactory } from './factories/native-command-factory';\n\n/**\n * `wizard ai-observability` — flat skill command, wire AI Observability into a\n * project today.\n *\n * Installs the OpenTelemetry SDK, the PostHog span processor, and the\n * provider-specific instrumentation so LLM calls emit `$ai_generation` events.\n * The `ai-observability` context-mill skill has one variant per (LLM provider ×\n * language); the agent picks the right one at run time by scanning the\n * project's manifest and (when ambiguous) asking the user via `wizard_ask`.\n * Stays flat while a single \"add AIO to a project\" flow is the only action.\n */\nexport const aiObservabilityCommand: Command = nativeCommandFactory(\n aiObservabilityConfig,\n);\n","import { metricsConfig } from '@lib/programs/metrics/index';\n\nimport type { Command } from './command';\nimport { nativeCommandFactory } from './factories/native-command-factory';\n\n/**\n * `wizard metrics` — flat skill command, wire PostHog application metrics\n * (counters, gauges, histograms via \\`posthog.metrics\\`) into a project.\n *\n * The `metrics` context-mill skill has one variant per platform (python,\n * nodejs, javascript, kubernetes, other/OTLP); the agent picks the right one\n * at run time by scanning the project's manifest and (when ambiguous) asking\n * the user via `wizard_ask`. Stays flat while a single \"add metrics to a\n * project\" flow is the only action.\n */\nexport const metricsCommand: Command = nativeCommandFactory(metricsConfig);\n","import type { Arguments } from 'yargs';\n\nimport { auditConfig } from '@lib/programs/audit/index';\nimport { AUDIT_CHECKS_FILE } from '@lib/programs/audit/types';\nimport { WIZARD_TOOL_NAMES } from '@lib/wizard-tools';\nimport { agentSkillConfig } from '@lib/programs/program-registry';\nimport { webAnalyticsDoctorConfig } from '@lib/programs/web-analytics-doctor/index';\nimport type { ProgramConfig } from '@lib/programs/program-step';\nimport { getSkillsBaseUrl } from '@lib/constants';\nimport { fetchSkillMenu, type CliEntry } from '@lib/wizard-tools';\nimport { analytics } from '@utils/analytics';\n\nimport { dispatchProgram } from '../../commands/factories/shared';\nimport type { Command } from '../../commands/command';\nimport { ErrorCodes } from '@lib/errors';\nimport { emitWizardError } from '@lib/errors';\n\n/**\n * Capture a CLI dispatch error, flush analytics, and exit. The wizard never\n * starts a run from these paths — use flush() (not shutdown()) so we don't\n * fire a \"setup wizard finished\" event for a parse error that didn't run.\n */\nasync function exitDispatchError(\n reason: string,\n properties: Record<string, unknown>,\n message: string,\n code = 1,\n): Promise<never> {\n analytics.wizardCapture('cli dispatch error', { reason, ...properties });\n try {\n await analytics.flush();\n } catch {\n /* flush is best-effort; never block the exit */\n }\n process.stderr.write(message);\n emitWizardError({ code: ErrorCodes.CliBadArgs, message: reason });\n return process.exit(code);\n}\n\n/**\n * Family commands (`wizard audit`, `wizard migrate`, ...) resolve their\n * subcommands at runtime against the published `cliEntries` inside\n * `skill-menu.json`. Adding a subcommand is a context-mill release — no\n * wizard release needed.\n *\n * Wizard-native subcommands (programs that aren't backed by a single skill,\n * e.g. `wizard audit web-analytics`) live here in code, dispatched directly\n * without touching the registry. Adding a native is a wizard PR.\n */\n\n/** Wizard-native subcommands keyed by family. */\nconst NATIVE_HANDLERS: Record<string, Record<string, ProgramConfig>> = {\n audit: { 'web-analytics': webAnalyticsDoctorConfig },\n};\n\n/**\n * Resolve a fetched CliEntry to the ProgramConfig that actually runs it.\n * Most entries run via the generic agent-skill program with the entry's\n * `skillId` injected. The comprehensive `audit all` is the one exception —\n * skillId 'audit' triggers the specialized auditConfig (custom hooks,\n * content blocks, screens).\n *\n * This is the one place that knows a subcommand belongs to `audit`, so the\n * generic skill program picks up the ledger here rather than for every skill.\n */\nfunction configForCliEntry(entry: CliEntry, family: string): ProgramConfig {\n if (entry.skillId === 'audit') return auditConfig;\n return {\n ...agentSkillConfig,\n skillId: entry.skillId,\n ...(family === 'audit'\n ? {\n auditLedgerFile: AUDIT_CHECKS_FILE,\n streamWorkflowId: family,\n allowedTools: [\n ...(agentSkillConfig.allowedTools ?? []),\n WIZARD_TOOL_NAMES.auditSeedChecks,\n WIZARD_TOOL_NAMES.auditAddChecks,\n WIZARD_TOOL_NAMES.auditResolveChecks,\n ],\n }\n : {}),\n };\n}\n\nfunction familyEntries(family: string, entries: CliEntry[]): CliEntry[] {\n return entries.filter(\n (e) =>\n e.role === 'command' && e.parentCommand === family && Boolean(e.command),\n );\n}\n\n/**\n * Dispatch `wizard <family> <sub>` to the right program.\n *\n * Order:\n * 1. Native handler for (family, sub) — runs immediately, no network.\n * 2. Fetched CliEntry — runs the resolved skill.\n * 3. Unknown — prints the available list and exits non-zero.\n */\nexport async function dispatchFamily(\n family: string,\n argv: Arguments,\n): Promise<void> {\n const sub = (argv.skill as string | undefined)?.trim();\n if (!sub) {\n // Reached only in non-TTY/CI — an interactive terminal routes the no-sub\n // case to the picker before this runs, so don't suggest opening it here.\n return exitDispatchError(\n 'missing subcommand',\n { family },\n `\\n\\x1b[1;91m✖ \\`wizard ${family}\\` requires a subcommand.\\x1b[0m\\n` +\n ` Pass one (e.g. \\`wizard ${family} <subcommand>\\`), or run it in an interactive terminal to pick from a menu.\\n\\n`,\n );\n }\n\n const native = NATIVE_HANDLERS[family]?.[sub];\n if (native) {\n dispatchProgram(native, argv);\n return;\n }\n\n const skillsBaseUrl = getSkillsBaseUrl();\n const menu = await fetchSkillMenu(skillsBaseUrl);\n if (!menu) {\n return exitDispatchError(\n 'registry unreachable',\n { family, sub, skillsBaseUrl },\n `\\n\\x1b[1;91m✖ Couldn't reach the skill registry at ${skillsBaseUrl}.\\x1b[0m\\n` +\n ` Check your network connection and try again.\\n\\n`,\n );\n }\n\n const entries = menu.cliEntries ?? [];\n const entry = familyEntries(family, entries).find((e) => e.command === sub);\n if (entry) {\n dispatchProgram(configForCliEntry(entry, family), argv);\n return;\n }\n\n const available = [\n ...Object.keys(NATIVE_HANDLERS[family] ?? {}),\n ...familyEntries(family, entries).map((e) => e.command!),\n ].sort();\n return exitDispatchError(\n 'unknown subcommand',\n { family, sub, available },\n `\\n\\x1b[1;91m✖ Unknown subcommand \"${sub}\" under \\`${family}\\`.\\x1b[0m\\n` +\n (available.length\n ? ` Available: ${available.join(', ')}\\n\\n`\n : ` No subcommands published for \"${family}\" yet.\\n\\n`),\n );\n}\n\n/**\n * Build the children list shown in the family's interactive picker.\n * Combines native handlers with skill-backed entries from the live registry.\n * Used by `familyCommandFactory`'s `interactiveDefault`.\n */\nexport function buildFamilyPickerChildren(\n family: string,\n entries: CliEntry[],\n): Command[] {\n const natives: Command[] = Object.entries(NATIVE_HANDLERS[family] ?? {}).map(\n ([cmd, program]) => ({\n name: cmd,\n description: program.description,\n handler: (argv: Arguments) => dispatchProgram(program, argv),\n }),\n );\n const live: Command[] = familyEntries(family, entries).map((entry) => ({\n name: entry.command!,\n description: entry.description,\n handler: (argv: Arguments) => {\n void dispatchFamily(family, {\n ...argv,\n skill: entry.command,\n } as Arguments);\n },\n default: entry.default,\n }));\n return [...natives, ...live];\n}\n\n/**\n * The children the family picker shows **today**: only the leaf marked\n * `default` (e.g. `audit events`). Every other subcommand stays runnable\n * directly (`wizard audit <name>`) — they just aren't listed in the picker yet.\n * Falls back to all children when nothing is marked `default`.\n *\n * Temporary: when we're ready to surface the full menu, return `children`\n * unchanged (and delete this note).\n */\nexport function pickerChildrenToShow(children: readonly Command[]): Command[] {\n const defaults = children.filter((c) => c.default);\n return defaults.length > 0 ? [...defaults] : [...children];\n}\n","/**\n * Filter-as-you-type matching for PickerMenu. Split out from the component so the\n * ranking is testable on its own — the component only decides when to call it.\n */\n\nimport Fuse, { type IFuseOptions } from 'fuse.js';\n\n/** The searchable face of a picker option. PickerMenu's `PickerOption<T>` satisfies it. */\nexport interface Searchable {\n label: string;\n hint?: string;\n description?: string;\n}\n\n/**\n * Fuzzy fallback config. `ignoreLocation` because a term matching at the end of a\n * description is as good as one at the start, and Fuse's default distance window\n * would score the late match away. 0.5 is the loosest threshold that still bottoms\n * out: below it `gthb` misses `GitHub` entirely, which is the whole point of having\n * a fuzzy pass; above it the tail grows without surfacing anything new at the top.\n */\nexport const FUSE_OPTIONS: IFuseOptions<Searchable> = {\n keys: [\n { name: 'label', weight: 3 },\n { name: 'hint', weight: 1 },\n { name: 'description', weight: 1 },\n ],\n ignoreLocation: true,\n threshold: 0.5,\n includeScore: true,\n};\n\nexport function buildPickerIndex<T extends Searchable>(options: T[]): Fuse<T> {\n return new Fuse(options, FUSE_OPTIONS as IFuseOptions<T>);\n}\n\nfunction haystack(option: Searchable): string {\n return `${option.label} ${option.hint ?? ''} ${\n option.description ?? ''\n }`.toLowerCase();\n}\n\n/**\n * Rank options against a query, best first, or `null` for an empty query.\n *\n * Two passes, literal before fuzzy. Anything that literally contains every\n * whitespace-separated term wins outright, in the list's own order — that covers how\n * people actually type (`git iss` → `GitHub issues`) and keeps the common case as\n * tight as a plain substring filter, which fuzzy matching on its own is not: Fuse at\n * a threshold loose enough to forgive `gthb` also lets a third of the list through\n * on `replay`.\n *\n * Only when nothing matches literally does Fuse get a turn, so a typo degrades to a\n * ranked guess instead of an empty list. Terms are AND-ed there too, each matched\n * fuzzily on its own — Fuse's bitap pass over the whole query would otherwise need\n * `git iss` to be a near-edit of the text it's matching. Scores are distances (0 is\n * exact) and sum across terms, hence the ascending sort; ties keep the order the\n * first term put them in, since the sort is stable.\n */\nexport function rankOptions<T extends Searchable>(\n fuse: Fuse<T>,\n options: T[],\n query: string,\n): T[] | null {\n const terms = query.toLowerCase().split(/\\s+/).filter(Boolean);\n if (!terms.length) {\n return null;\n }\n\n const literal = options.filter((option) =>\n terms.every((term) => haystack(option).includes(term)),\n );\n if (literal.length) {\n return literal;\n }\n\n let surviving: Map<T, number> | null = null;\n for (const term of terms) {\n const hits = new Map<T, number>(\n fuse.search(term).map(({ item, score }) => [item, score ?? 0]),\n );\n if (surviving === null) {\n surviving = hits;\n continue;\n }\n // Deleting the current key mid-iteration is well-defined for a Map.\n for (const [option, total] of surviving) {\n const score = hits.get(option);\n if (score === undefined) {\n surviving.delete(option);\n } else {\n surviving.set(option, total + score);\n }\n }\n }\n\n return [...(surviving ?? [])]\n .sort(([, a], [, b]) => a - b)\n .map(([option]) => option);\n}\n","/**\n * PromptLabel — Compact inline label for input prompts.\n *\n * Renders: [!] message\n * where [!] is black text on accent background.\n */\n\nimport { Box, Text } from 'ink';\nimport { Colors } from '@ui/tui/styles';\n\ninterface PromptLabelProps {\n message?: string;\n}\n\nexport const PromptLabel = ({ message }: PromptLabelProps) => {\n // No message → no row, so label-less pickers don't get a stray blank line.\n if (!message) return null;\n return (\n <Box>\n <Text bold color={Colors.accent}>\n {' '}\n {message}\n </Text>\n </Box>\n );\n};\n","/**\n * ConfirmButton — the confirm row used to submit a selection.\n *\n * Pure render. Multi-select menus (PickerMenu mode=\"multi\", GroupedPickerMenu)\n * append this below their options as the final focusable row: the user toggles\n * options with enter, then arrows down onto this row and presses enter to\n * submit. This replaces the older \"enter anywhere submits\" pattern, which\n * confused people who expected enter to toggle the focused item.\n *\n * Renders flat, mirroring the option rows — a focus triangle and the label,\n * accent and bold when focused, dimmed otherwise — so it lines up under the\n * options instead of sitting in a separate boxed target.\n */\n\nimport { Text } from 'ink';\nimport { Icons, Colors } from '@ui/tui/styles';\n\ninterface ConfirmButtonProps {\n /** Button text. Defaults to \"Confirm\". */\n label?: string;\n /** Whether the cursor is currently on the button. */\n focused: boolean;\n /** Optional selected-item count, rendered as \"Label (n)\" when > 0. */\n count?: number;\n}\n\nexport const ConfirmButton = ({\n label = 'Confirm',\n focused,\n count,\n}: ConfirmButtonProps) => {\n const text = count && count > 0 ? `${label} (${count})` : label;\n return (\n <Text\n color={focused ? Colors.accent : undefined}\n bold={focused}\n dimColor={!focused}\n >\n {focused ? Icons.triangleSmallRight : ' '} {text}\n </Text>\n );\n};\n","/**\n * useStdoutDimensions — Returns [columns, rows] and re-renders on terminal resize.\n *\n * Ink's useStdout() does not subscribe to resize events, so layout only updates\n * when something else causes a re-render. This hook listens to the stream's\n * 'resize' event (Node TTY) and updates state so the component re-renders\n * with the new dimensions.\n */\n\nimport { useStdout } from 'ink';\nimport { useState, useEffect } from 'react';\n\nexport function useStdoutDimensions(): [number, number] {\n const { stdout } = useStdout();\n const [size, setSize] = useState<[number, number]>(() => [\n stdout.columns || 80,\n stdout.rows || 24,\n ]);\n\n useEffect(() => {\n const cols = stdout.columns || 80;\n const rows = stdout.rows || 24;\n setSize([cols, rows]);\n\n const stream = stdout as NodeJS.WriteStream & {\n on?(event: string, fn: () => void): void;\n };\n if (typeof stream.on !== 'function') return;\n\n const onResize = () => {\n const c = stdout.columns || 80;\n const r = stdout.rows || 24;\n if (c > 0 && r > 0) setSize([c, r]);\n };\n stream.on('resize', onResize);\n return () => {\n stream.off?.('resize', onResize);\n };\n }, [stdout]);\n\n return size;\n}\n","/**\n * Pure utility functions for keyboard hints — no React or Ink dependencies.\n * Extracted for testability in a node Jest environment.\n */\n\nexport interface KeyboardHint {\n label: string;\n action: string;\n priority: number;\n}\n\n/** Well-known key matches corresponding to Ink's key.* properties. */\nexport enum KeyMatch {\n UpArrow = 'upArrow',\n DownArrow = 'downArrow',\n LeftArrow = 'leftArrow',\n RightArrow = 'rightArrow',\n Return = 'return',\n Escape = 'escape',\n Space = 'space',\n Backspace = 'backspace',\n /**\n * Any single printable character typed without a modifier. Broad by design,\n * so a binding using it must sit last — the first match wins, which is what\n * lets a specific char binding still take precedence over free typing.\n */\n Printable = 'printable',\n}\n\n/** A key match: either a KeyMatch enum value or a literal character string (e.g. 'a', 's'). */\nexport type KeyMatchOrChar = KeyMatch | (string & NonNullable<unknown>);\n\n/** Default priorities by key type. */\nconst DEFAULT_PRIORITY: Record<string, number> = {\n [KeyMatch.UpArrow]: 0,\n [KeyMatch.DownArrow]: 0,\n [KeyMatch.LeftArrow]: 1,\n [KeyMatch.RightArrow]: 1,\n [KeyMatch.Space]: 10,\n [KeyMatch.Printable]: 12,\n [KeyMatch.Backspace]: 13,\n [KeyMatch.Escape]: 20,\n [KeyMatch.Return]: 21,\n};\n\n/** Get the default display priority for a key match. */\nexport function getDefaultPriority(\n match: KeyMatchOrChar | KeyMatchOrChar[],\n): number {\n const first = Array.isArray(match) ? match[0] : match;\n return DEFAULT_PRIORITY[first] ?? 15;\n}\n\n/** Check if a KeyMatchOrChar matches the given input string and key flags. */\nexport function matchesKey(\n m: KeyMatchOrChar,\n input: string,\n key: { [k: string]: unknown },\n): boolean {\n switch (m) {\n case KeyMatch.UpArrow:\n return !!key.upArrow;\n case KeyMatch.DownArrow:\n return !!key.downArrow;\n case KeyMatch.LeftArrow:\n return !!key.leftArrow;\n case KeyMatch.RightArrow:\n return !!key.rightArrow;\n case KeyMatch.Return:\n return !!key.return;\n case KeyMatch.Escape:\n return !!key.escape;\n case KeyMatch.Space:\n return input === ' ';\n case KeyMatch.Backspace:\n return !!key.backspace || !!key.delete;\n case KeyMatch.Printable:\n // Ink sets a flag for every non-text key while still passing a non-empty\n // `input`, so any flag but shift rules out typing.\n // Any single non-control character, not just ASCII — a filter query can\n // hold an accented or non-Latin letter.\n return (\n input.length === 1 &&\n input >= ' ' &&\n input !== '\\x7f' &&\n Object.entries(key).every(([flag, on]) => !on || flag === 'shift')\n );\n default:\n return input === m;\n }\n}\n\n/** Serialize hints for comparison. */\nexport function hintsKey(hints: KeyboardHint[]): string {\n return hints.map((h) => `${h.label}:${h.action}`).join('|');\n}\n\n/** Deduplicate hints by label+action and sort by priority. */\nexport function deduplicateAndSort(hints: KeyboardHint[]): KeyboardHint[] {\n const seen = new Set<string>();\n const deduped: KeyboardHint[] = [];\n for (const hint of hints) {\n const k = `${hint.label}:${hint.action}`;\n if (!seen.has(k)) {\n seen.add(k);\n deduped.push(hint);\n }\n }\n deduped.sort((a, b) => a.priority - b.priority);\n return deduped;\n}\n","/**\n * KeyboardHintsProvider — Context for collecting and displaying keyboard hints.\n *\n * Input components register their hints via useKeyBindings. The provider\n * flattens, deduplicates, and sorts them. The hints bar stays visible for as\n * long as a screen has registered hints — it never auto-dismisses.\n */\n\nimport {\n createContext,\n useCallback,\n useContext,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\nimport {\n hintsKey,\n deduplicateAndSort,\n type KeyboardHint,\n} from './keyboard-hints-utils.js';\n\nexport type { KeyboardHint } from './keyboard-hints-utils.js';\n\ninterface KeyboardHintsContextValue {\n register(id: string, hints: KeyboardHint[]): void;\n unregister(id: string): void;\n hints: KeyboardHint[];\n}\n\nconst KeyboardHintsContext = createContext<KeyboardHintsContextValue>({\n register: () => undefined,\n unregister: () => undefined,\n hints: [],\n});\n\nexport const useKeyboardHintsContext = () => useContext(KeyboardHintsContext);\n\nexport const KeyboardHintsProvider = ({\n children,\n}: {\n children: ReactNode;\n}) => {\n const registrationsRef = useRef(new Map<string, KeyboardHint[]>());\n const [hints, setHints] = useState<KeyboardHint[]>([]);\n const prevHintsKeyRef = useRef('');\n\n const recompute = useCallback(() => {\n const all: KeyboardHint[] = [];\n for (const h of registrationsRef.current.values()) {\n all.push(...h);\n }\n const deduped = deduplicateAndSort(all);\n\n const newKey = hintsKey(deduped);\n if (newKey !== prevHintsKeyRef.current) {\n prevHintsKeyRef.current = newKey;\n setHints(deduped);\n }\n }, []);\n\n const register = useCallback(\n (id: string, h: KeyboardHint[]) => {\n registrationsRef.current.set(id, h);\n recompute();\n },\n [recompute],\n );\n\n const unregister = useCallback(\n (id: string) => {\n registrationsRef.current.delete(id);\n recompute();\n },\n [recompute],\n );\n\n return (\n <KeyboardHintsContext.Provider value={{ register, unregister, hints }}>\n {children}\n </KeyboardHintsContext.Provider>\n );\n};\n","/**\n * useKeyBindings — Declarative keyboard input + automatic hint registration.\n *\n * Replaces raw `useInput` in input components. Define bindings as data;\n * the hook wires up the Ink input handler AND registers hints in the\n * KeyboardHintsProvider. One source of truth for keys and their labels.\n */\n\nimport { useInput, type Key } from 'ink';\nimport { useEffect, useRef } from 'react';\nimport { useKeyboardHintsContext } from './useKeyboardHints.js';\nimport {\n matchesKey,\n getDefaultPriority,\n KeyMatch,\n type KeyboardHint,\n type KeyMatchOrChar,\n} from './keyboard-hints-utils.js';\n\nexport { KeyMatch };\nexport type { KeyMatchOrChar } from './keyboard-hints-utils.js';\n\nexport interface KeyBinding {\n /** Which key(s) trigger this binding. Array = multiple keys, one hint. */\n match: KeyMatchOrChar | KeyMatchOrChar[];\n /** Display label in hints bar (e.g. \"↑↓\", \"space\", \"enter\") */\n label: string;\n /** Description in hints bar (e.g. \"navigate\", \"toggle\") */\n action: string;\n /** Ordering priority (lower = further left). Defaults based on key type. */\n priority?: number;\n /** Handler called when the key matches. */\n handler: (input: string, key: Key) => void;\n}\n\n/**\n * Declarative key bindings hook. Replaces `useInput` in input components.\n * Registers hints automatically with the KeyboardHintsProvider.\n *\n * @param id Unique identifier for this component's hints registration\n * @param bindings Array of key binding definitions\n */\nexport function useKeyBindings(id: string, bindings: KeyBinding[]): void {\n const ctx = useKeyboardHintsContext();\n\n // Extract hints and register. Use a serialized key to avoid unnecessary updates.\n const hintsRef = useRef<string>('');\n const hints: KeyboardHint[] = bindings.map((b) => ({\n label: b.label,\n action: b.action,\n priority: b.priority ?? getDefaultPriority(b.match),\n }));\n const serialized = hints\n .map((h) => `${h.label}:${h.action}:${h.priority}`)\n .join('|');\n\n useEffect(() => {\n if (serialized !== hintsRef.current) {\n hintsRef.current = serialized;\n ctx.register(id, hints);\n }\n return () => ctx.unregister(id);\n // eslint-disable-next-line\n }, [id, serialized]);\n\n // Wire up input handling\n useInput((input, key) => {\n for (const binding of bindings) {\n const matches = Array.isArray(binding.match)\n ? binding.match\n : [binding.match];\n if (matches.some((m) => matchesKey(m, input, key))) {\n binding.handler(input, key);\n return;\n }\n }\n });\n}\n","/**\n * PickerMenu — Single and multi select.\n * Single mode: custom renderer with small triangle indicator; enter selects.\n * Multi mode: checkbox glyphs toggled with enter, plus a focusable\n * Confirm button below the options. The cursor moves onto the button and\n * enter submits — see MultiPickerMenu for the rationale.\n *\n * Key bindings are declared via useKeyBindings, which auto-registers\n * hints in the KeyboardHintsBar.\n */\n\nimport { Box, Text } from 'ink';\nimport { useEffect, useMemo, useState } from 'react';\nimport { buildPickerIndex, rankOptions } from './picker-filter.js';\nimport { Icons, Colors } from '@ui/tui/styles';\nimport { PromptLabel } from './PromptLabel.js';\nimport { ConfirmButton } from './ConfirmButton.js';\nimport { wordWrap } from './layout-helpers.js';\nimport { useStdoutDimensions } from '@ui/tui/hooks/useStdoutDimensions';\nimport {\n useKeyBindings,\n KeyMatch,\n type KeyBinding,\n type KeyMatchOrChar,\n} from '@ui/tui/hooks/useKeyBindings';\n\nexport interface PickerOption<T> {\n label: string;\n value: T;\n hint?: string;\n /**\n * Multi-select only: a secondary explanation rendered dimmed and wrapped on\n * its own line(s) beneath the label, for choices that need more than a title.\n * When unset, the row renders exactly as a label-only row.\n */\n description?: string;\n /** Glyph rendered before the label, in its own color — unaffected by\n * focus and disabled styling. */\n icon?: { glyph: string; color?: string };\n /** Dimmed and unselectable; navigation skips over it. */\n disabled?: boolean;\n /**\n * Section heading: unselectable (navigation skips it, like `disabled`) but\n * rendered as a bold header rather than a muted row. Set `disabled` too so\n * the skip logic treats it as non-selectable.\n */\n header?: boolean;\n /** Indent the label one level, e.g. items nested under a `header` row. */\n indent?: boolean;\n /**\n * Multi-select only: marks this option mutually exclusive with every other\n * option. Selecting it clears all other picks; selecting any non-exclusive\n * option clears it. Used e.g. for a browser connector that can't be\n * installed alongside local editors.\n */\n exclusive?: boolean;\n}\n\n/**\n * Step through a column's options in `dir`, wrapping, until an enabled\n * option is found. Returns `from` unchanged if the column is entirely\n * disabled.\n */\nfunction stepEnabled<T>(\n options: PickerOption<T>[],\n rows: number,\n from: number,\n dir: 1 | -1,\n): number {\n const col = Math.floor(from / rows);\n const colStart = col * rows;\n const colLen = Math.min(rows, options.length - colStart);\n let row = from % rows;\n for (let i = 0; i < colLen; i++) {\n row = (row + dir + colLen) % colLen;\n const idx = colStart + row;\n if (!options[idx]?.disabled) return idx;\n }\n return from;\n}\n\n/** First enabled option in [start, end), for initial focus and for entering\n * a page from the Confirm button. */\nfunction firstEnabled<T>(\n options: PickerOption<T>[],\n start = 0,\n end = options.length,\n): number {\n for (let i = start; i < end; i++) {\n if (!options[i]?.disabled) return i;\n }\n return start;\n}\n\n/** Last enabled option in [start, end), for wrapping from the button onto\n * the bottom of the page. */\nfunction lastEnabled<T>(\n options: PickerOption<T>[],\n start = 0,\n end = options.length,\n): number {\n for (let i = end - 1; i >= start; i--) {\n if (!options[i]?.disabled) return i;\n }\n return end - 1;\n}\n\n/**\n * Rows the surrounding screen or overlay consumes above and below a picker —\n * border + padding, title, prompt text, and the keyboard-hints bar. A\n * deliberately generous estimate: overshooting just shows a few fewer rows,\n * whereas undershooting lets a long list overflow the viewport (the bug this\n * windowing guards against). Mirrors GroupedPickerMenu's budgeting.\n */\nconst CHROME_OVERHEAD = 13;\n/**\n * Max visual rows a picker renders regardless of terminal height. Without a\n * ceiling a tall terminal lets a long list fill the whole viewport, which\n * reads as a wall of options; ~12 rows keeps the menu scannable and leaves\n * known breathing room above and below.\n */\nconst MAX_LIST_ROWS = 12;\n/** Extra rows a multi-select adds below its options: marginTop + Confirm button. */\nconst CONFIRM_CHROME = 3;\n/** Lists shorter than this never page — tall rows would split 2-3 options into pages of one. */\nconst MIN_COUNT_TO_PAGE = 5;\n/** Width the multi-select wraps option descriptions to (matches the render). */\nconst DESCRIPTION_WIDTH = 56;\n\ninterface PickerViewport {\n needsScroll: boolean;\n /** First option index on the current page. */\n start: number;\n /** One past the last option index on the current page. */\n end: number;\n hiddenAbove: number;\n hiddenBelow: number;\n /** Focus target one page over (wrapping), for the n/p keys. */\n pageStep: (focused: number, dir: 1 | -1) => number;\n}\n\n/**\n * Pages a single-column option list to the terminal height. The visible page\n * is derived from the focused index — no scroll state — so ↑/↓ flip pages as\n * focus crosses a page edge and n/p jump a whole page. Pages hold a fixed\n * option count sized to the tallest row (`rowCost`), trading a sparser page\n * on mixed-height lists for arithmetic-only paging. Engages only for\n * single-column pickers — multi-column grids already compress vertically.\n */\nfunction usePickerViewport(\n count: number,\n rowCost: number,\n chromeBelow: number,\n enabled: boolean,\n focused: number,\n): PickerViewport {\n const [, termRows] = useStdoutDimensions();\n const budget = Math.max(\n 5,\n Math.min(termRows - CHROME_OVERHEAD - chromeBelow, MAX_LIST_ROWS),\n );\n const needsScroll =\n enabled && count >= MIN_COUNT_TO_PAGE && count * rowCost > budget;\n // Reserve two rows for the \"↑/↓ N more\" indicators.\n const perPage = needsScroll\n ? Math.max(1, Math.floor((budget - 2) / rowCost))\n : count;\n const pageCount = Math.max(1, Math.ceil(count / perPage));\n const start = Math.floor(focused / perPage) * perPage;\n const end = Math.min(start + perPage, count);\n return {\n needsScroll,\n start,\n end,\n hiddenAbove: start,\n hiddenBelow: count - end,\n pageStep: (f, dir) =>\n ((Math.floor(f / perPage) + dir + pageCount) % pageCount) * perPage,\n };\n}\n\ninterface PickerMenuProps<T> {\n message?: string;\n options: PickerOption<T>[];\n mode?: 'single' | 'multi';\n centered?: boolean;\n columns?: 1 | 2 | 3 | 4;\n /**\n * Vertical space between options, in TUI rows. Defaults to 0 — i.e.\n * options stack tightly. Set to 1+ when the option labels are long\n * (wrap across multiple lines) or for visual breathing room.\n */\n optionMarginBottom?: number;\n /**\n * Filter-as-you-type. Defaults on once the list is long enough to page, where\n * finding one option means walking pages. Pass `false` to force it off.\n */\n filterable?: boolean;\n onSelect: (value: T | T[]) => void;\n}\n\n/** Lists at least this long get filtering. Shorter ones fit on a page or two,\n * where a filter row costs more rows than it saves. */\nconst FILTER_MIN_OPTIONS = 10;\n\nexport const PickerMenu = <T,>({\n message,\n options,\n mode = 'single',\n centered = false,\n columns = 1,\n optionMarginBottom = 0,\n filterable,\n onSelect,\n}: PickerMenuProps<T>) => {\n const canFilter = filterable ?? options.length >= FILTER_MIN_OPTIONS;\n const [filter, setFilter] = useState('');\n const fuse = useMemo(\n () => (canFilter ? buildPickerIndex(options) : null),\n [options, canFilter],\n );\n const visible = useMemo(\n () => (fuse ? rankOptions(fuse, options, filter) ?? options : options),\n [fuse, options, filter],\n );\n\n // Keyed by label, and owned here rather than by MultiPickerMenu: filtering\n // rewrites the list under the ticks, and the remount below would drop them.\n const [selected, setSelected] = useState<Set<string>>(new Set());\n\n const shared = {\n message,\n options: visible,\n centered,\n optionMarginBottom,\n onSelect,\n filter: canFilter ? filter : null,\n setFilter,\n totalCount: options.length,\n };\n\n // A filtered list is a fresh list with its own focus and paging, so remount on\n // each query rather than leaving stale indices to be re-validated.\n const key = String(filter);\n\n if (mode === 'multi') {\n return (\n <MultiPickerMenu\n key={key}\n {...shared}\n columns={columns}\n allOptions={options}\n selected={selected}\n setSelected={setSelected}\n />\n );\n }\n\n return <SinglePickerMenu key={key} {...shared} columns={columns} />;\n};\n\n/**\n * Backspace and free typing. Append these last: `Printable` matches almost any\n * key, and bindings resolve in order, so anything specific has to be registered\n * first to keep working. Both share a label/action so the hints bar shows one.\n */\nfunction filterBindings(\n filter: string,\n setFilter: (query: string) => void,\n): KeyBinding[] {\n return [\n {\n match: KeyMatch.Backspace,\n label: 'type',\n action: 'filter',\n handler: () => setFilter(filter.slice(0, -1)),\n },\n {\n match: KeyMatch.Printable,\n label: 'type',\n action: 'filter',\n handler: (input: string) => setFilter(filter + input),\n },\n ];\n}\n\n/** The filter row above a filterable list: what's typed, and how much it left. */\nconst FilterRow = ({\n filter,\n shown,\n total,\n}: {\n filter: string;\n shown: number;\n total: number;\n}) => (\n // Indented to sit under PromptLabel, which carries a leading space.\n <Box paddingLeft={1}>\n <Text dimColor>\n {filter\n ? `Filter: ${filter} (${shown} of ${total})`\n : `Type to filter ${total} options`}\n </Text>\n </Box>\n);\n\n/** Custom single-select with triangle indicator and accent highlight. */\nconst SinglePickerMenu = <T,>({\n message,\n options,\n centered = false,\n columns = 1,\n optionMarginBottom = 0,\n filter,\n setFilter,\n totalCount,\n onSelect,\n}: {\n message?: string;\n options: PickerOption<T>[];\n centered?: boolean;\n columns?: number;\n optionMarginBottom?: number;\n /** Current filter query, or null when this picker isn't filterable. */\n filter: string | null;\n setFilter: (query: string) => void;\n totalCount: number;\n onSelect: (value: T | T[]) => void;\n}) => {\n const [focused, setFocused] = useState(() => firstEnabled(options));\n const rows = Math.ceil(options.length / columns);\n // Single-select rows are label-only (no descriptions): one line plus margin.\n const viewport = usePickerViewport(\n options.length,\n 1 + optionMarginBottom,\n filter !== null ? 1 : 0,\n columns === 1,\n focused,\n );\n\n // Re-validate focus when the options change while mounted \\u2014 a list\n // that shrinks or disables entries can leave `focused` pointing at a\n // missing or disabled option, which would make enter a no-op.\n useEffect(() => {\n if (focused >= options.length || options[focused]?.disabled) {\n setFocused(firstEnabled(options));\n }\n }, [options, focused]);\n\n const bindings: KeyBinding[] = [\n {\n match: [KeyMatch.UpArrow, KeyMatch.DownArrow],\n label: '\\u2191\\u2193',\n action: 'navigate',\n handler: (_input, key) => {\n const dir = key.upArrow ? -1 : 1;\n // `start`/`end` derive from `focused`, so stepping past a page edge\n // flips the page rather than needing a bound here.\n setFocused(stepEnabled(options, rows, focused, dir));\n },\n },\n // Only on a non-filterable list. Once a filter row exists `n` and `p` are\n // characters, not commands — so they go for good, not just once a query is\n // typed, and the arrows carry paging instead by walking the whole list.\n ...(viewport.needsScroll && filter === null\n ? [\n {\n match: ['n', 'p'] as KeyMatchOrChar[],\n label: 'n/p',\n action: 'page',\n handler: (input: string) => {\n const target = viewport.pageStep(focused, input === 'n' ? 1 : -1);\n setFocused(\n options[target]?.disabled\n ? stepEnabled(options, rows, target, 1)\n : target,\n );\n },\n },\n ]\n : []),\n {\n match: KeyMatch.Return,\n label: 'enter',\n action: 'select',\n handler: () => {\n const selected = options[focused];\n if (selected && !selected.disabled) {\n onSelect(selected.value);\n }\n },\n },\n ];\n\n if (columns > 1) {\n bindings.splice(1, 0, {\n match: [KeyMatch.LeftArrow, KeyMatch.RightArrow],\n label: '\\u2190\\u2192',\n action: 'navigate',\n handler: (_input, key) => {\n const col = Math.floor(focused / rows);\n const row = focused % rows;\n\n let next = focused;\n if (key.leftArrow) {\n const prevCol = col > 0 ? col - 1 : columns - 1;\n next = Math.min(prevCol * rows + row, options.length - 1);\n }\n if (key.rightArrow) {\n const nextCol = col < columns - 1 ? col + 1 : 0;\n next = Math.min(nextCol * rows + row, options.length - 1);\n }\n // Landing on a disabled option slides to the column's nearest\n // enabled one.\n if (options[next]?.disabled) {\n next = stepEnabled(options, rows, next, 1);\n }\n setFocused(next);\n },\n });\n }\n\n if (filter !== null) {\n bindings.push(...filterBindings(filter, setFilter));\n }\n\n useKeyBindings('single-picker', bindings);\n\n // Chunk options into columns (column-first ordering)\n const columnArrays: PickerOption<T>[][] = [];\n for (let c = 0; c < columns; c++) {\n columnArrays.push(options.slice(c * rows, c * rows + rows));\n }\n\n const align = centered ? 'center' : undefined;\n\n const renderOption = (opt: PickerOption<T>, flatIdx: number) => {\n const isFocused = flatIdx === focused;\n const base = opt.hint ? `${opt.label} (${opt.hint})` : opt.label;\n const label = opt.indent ? ` ${base}` : base;\n return (\n <Box key={flatIdx} gap={1} marginBottom={optionMarginBottom}>\n <Text\n color={isFocused ? Colors.accent : undefined}\n dimColor={!isFocused}\n >\n {isFocused && !opt.header ? Icons.triangleSmallRight : ' '}\n </Text>\n {opt.icon && <Text color={opt.icon.color}>{opt.icon.glyph}</Text>}\n <Text\n color={\n opt.header\n ? undefined\n : opt.disabled\n ? Colors.muted\n : isFocused\n ? Colors.accent\n : undefined\n }\n bold={opt.header || (isFocused && !opt.disabled)}\n dimColor={!opt.header && (!isFocused || opt.disabled)}\n >\n {label}\n </Text>\n </Box>\n );\n };\n\n return (\n <Box flexDirection=\"column\" alignItems={align}>\n <PromptLabel message={message} />\n {filter !== null && (\n <FilterRow filter={filter} shown={options.length} total={totalCount} />\n )}\n {filter && options.length === 0 ? (\n <Text dimColor>No options match. Backspace to widen the filter.</Text>\n ) : viewport.needsScroll ? (\n <Box flexDirection=\"column\">\n <Text dimColor>\n {viewport.hiddenAbove > 0\n ? `↑ ${viewport.hiddenAbove} more${\n filter === null ? ' [P] for previous page' : ''\n }`\n : ' '}\n </Text>\n {options\n .slice(viewport.start, viewport.end)\n .map((opt, relIdx) => renderOption(opt, viewport.start + relIdx))}\n <Text dimColor>\n {viewport.hiddenBelow > 0\n ? `↓ ${viewport.hiddenBelow} more${\n filter === null ? ' [N] for next page' : ''\n }`\n : ' '}\n </Text>\n </Box>\n ) : (\n <Box flexDirection=\"row\" gap={4}>\n {columnArrays.map((colOpts, colIdx) => (\n <Box key={colIdx} flexDirection=\"column\">\n {colOpts.map((opt, rowIdx) =>\n renderOption(opt, colIdx * rows + rowIdx),\n )}\n </Box>\n ))}\n </Box>\n )}\n </Box>\n );\n};\n\n/**\n * Custom multi-select with checkbox glyphs and accent highlight.\n *\n * Interaction model (shared with GroupedPickerMenu):\n * - \\u2191\\u2193 move the cursor through the options AND onto the Confirm button,\n * which lives just past the last option.\n * - enter toggles the focused option (no more \"space toggles but enter\n * advances\" split that tripped people up). Space is kept as an\n * undocumented alias, but the hints bar advertises only enter.\n * - moving onto the Confirm button and pressing enter submits the\n * current selection.\n */\nconst MultiPickerMenu = <T,>({\n message,\n options,\n centered = false,\n columns = 1,\n optionMarginBottom = 0,\n filter,\n setFilter,\n totalCount,\n allOptions,\n selected,\n setSelected,\n onSelect,\n}: {\n message?: string;\n options: PickerOption<T>[];\n centered?: boolean;\n columns?: number;\n optionMarginBottom?: number;\n /** Current filter query, or null when this picker isn't filterable. */\n filter: string | null;\n setFilter: (query: string) => void;\n totalCount: number;\n /** Every option, filtered or not. Ticks outlive the query, so resolving and\n * submitting them has to happen against the full list. */\n allOptions: PickerOption<T>[];\n selected: Set<string>;\n setSelected: (update: (prev: Set<string>) => Set<string>) => void;\n onSelect: (value: T | T[]) => void;\n}) => {\n const [focused, setFocused] = useState(() => firstEnabled(options));\n // When true, the cursor is on the Confirm button rather than an option.\n const [onButton, setOnButton] = useState(false);\n const rows = Math.ceil(options.length / columns);\n // A row is its label line plus any margin; a description adds one line per\n // wrapped line beneath the label. Pages size to the tallest row.\n const rowCost = options.reduce(\n (max, opt) =>\n Math.max(\n max,\n 1 +\n optionMarginBottom +\n (opt.description\n ? wordWrap(opt.description, DESCRIPTION_WIDTH).length\n : 0),\n ),\n 1,\n );\n const viewport = usePickerViewport(\n options.length,\n rowCost,\n CONFIRM_CHROME + (filter !== null ? 1 : 0),\n columns === 1,\n focused,\n );\n\n // Re-validate focus when the options change while mounted — a list\n // that shrinks or disables entries can leave `focused` pointing at a\n // missing or disabled option, which would make enter a no-op.\n useEffect(() => {\n if (focused >= options.length || options[focused]?.disabled) {\n setFocused(firstEnabled(options));\n }\n }, [options, focused]);\n\n const confirm = () => {\n // In `allOptions` order, so a pick made under one filter still submits\n // after the query moved on.\n const values = allOptions\n .filter((option) => selected.has(option.label))\n .map((option) => option.value);\n onSelect(values);\n };\n\n const bindings: KeyBinding[] = [\n {\n match: [KeyMatch.UpArrow, KeyMatch.DownArrow],\n label: '\\u2191\\u2193',\n action: 'navigate',\n handler: (_input, key) => {\n const dir = key.upArrow ? -1 : 1;\n if (onButton) {\n // Button \\u2192 back onto the current page (bottom for \\u2191, top for \\u2193).\n setOnButton(false);\n setFocused(\n dir === -1\n ? lastEnabled(options, viewport.start, viewport.end)\n : firstEnabled(options, viewport.start, viewport.end),\n );\n return;\n }\n const col = Math.floor(focused / rows);\n const row = focused % rows;\n const colLen = Math.min(rows, options.length - col * rows);\n // Nearest enabled option above/below in this column; leaving the\n // column lands on the button.\n let r = row + dir;\n while (r >= 0 && r < colLen && options[col * rows + r]?.disabled) {\n r += dir;\n }\n if (r >= 0 && r < colLen) {\n setFocused(col * rows + r);\n } else {\n setOnButton(true);\n }\n },\n },\n // Only on a non-filterable list. Once a filter row exists `n` and `p` are\n // characters, not commands — so they go for good, not just once a query is\n // typed, and the arrows carry paging instead by walking the whole list.\n ...(viewport.needsScroll && filter === null\n ? [\n {\n match: ['n', 'p'] as KeyMatchOrChar[],\n label: 'n/p',\n action: 'page',\n handler: (input: string) => {\n const target = viewport.pageStep(focused, input === 'n' ? 1 : -1);\n setOnButton(false);\n setFocused(\n options[target]?.disabled\n ? stepEnabled(options, rows, target, 1)\n : target,\n );\n },\n },\n ]\n : []),\n {\n // Space is only an alias for enter when there's no filter to type into.\n match:\n filter !== null ? KeyMatch.Return : [KeyMatch.Space, KeyMatch.Return],\n label: 'enter',\n action: 'select',\n handler: () => {\n if (onButton) {\n confirm();\n return;\n }\n // `focused` can point past the end: filtering to zero matches leaves\n // nothing under the cursor, and enter is the natural thing to try there.\n const option = options[focused];\n if (!option || option.disabled) return;\n const label = option.label;\n setSelected((prev) => {\n const next = new Set(prev);\n if (next.has(label)) {\n next.delete(label);\n return next;\n }\n // Enforce mutual exclusivity: an exclusive option clears every other\n // pick; any other option clears previously-picked exclusive ones.\n if (option.exclusive) {\n return new Set([label]);\n }\n // Against `allOptions`: the pick being cleared may be off-screen\n // under the current query.\n for (const picked of next) {\n if (allOptions.find((o) => o.label === picked)?.exclusive) {\n next.delete(picked);\n }\n }\n next.add(label);\n return next;\n });\n },\n },\n ];\n\n if (columns > 1) {\n bindings.splice(1, 0, {\n match: [KeyMatch.LeftArrow, KeyMatch.RightArrow],\n label: '\\u2190\\u2192',\n action: 'navigate',\n handler: (_input, key) => {\n if (onButton) return;\n const col = Math.floor(focused / rows);\n const row = focused % rows;\n\n let next = focused;\n if (key.leftArrow) {\n const prevCol = col > 0 ? col - 1 : columns - 1;\n next = Math.min(prevCol * rows + row, options.length - 1);\n }\n if (key.rightArrow) {\n const nextCol = col < columns - 1 ? col + 1 : 0;\n next = Math.min(nextCol * rows + row, options.length - 1);\n }\n // Landing on a disabled option slides to the column's nearest\n // enabled one.\n if (options[next]?.disabled) {\n next = stepEnabled(options, rows, next, 1);\n }\n setFocused(next);\n },\n });\n }\n\n if (filter !== null) {\n bindings.push(...filterBindings(filter, setFilter));\n }\n\n useKeyBindings('multi-picker', bindings);\n\n const columnArrays: PickerOption<T>[][] = [];\n for (let c = 0; c < columns; c++) {\n columnArrays.push(options.slice(c * rows, c * rows + rows));\n }\n\n const renderOption = (opt: PickerOption<T>, flatIdx: number) => {\n const isFocused = !onButton && flatIdx === focused;\n const isSelected = selected.has(opt.label);\n const label = opt.hint ? `${opt.label} (${opt.hint})` : opt.label;\n const checkbox = isSelected ? Icons.squareFilled : Icons.squareOpen;\n return (\n <Box\n key={flatIdx}\n flexDirection=\"column\"\n marginBottom={optionMarginBottom}\n >\n <Box gap={1}>\n <Text\n color={isSelected ? 'white' : Colors.muted}\n dimColor={!isFocused && !isSelected}\n >\n {checkbox}\n </Text>\n {opt.icon && <Text color={opt.icon.color}>{opt.icon.glyph}</Text>}\n <Text\n color={\n opt.disabled\n ? Colors.muted\n : isFocused\n ? Colors.accent\n : undefined\n }\n bold={isFocused && !opt.disabled}\n dimColor={!isFocused || opt.disabled}\n >\n {label}\n </Text>\n </Box>\n {/* Optional dimmed, wrapped explanation under the label. The explicit\n width forces Ink to wrap (an unconstrained Box shrinks to its\n content and never wraps). Renders only when set, so label-only rows\n are byte-for-byte unchanged. */}\n {opt.description && (\n <Box marginLeft={4} width={DESCRIPTION_WIDTH}>\n <Text dimColor wrap=\"wrap\">\n {opt.description}\n </Text>\n </Box>\n )}\n </Box>\n );\n };\n\n return (\n <Box flexDirection=\"column\" alignItems={centered ? 'center' : undefined}>\n <PromptLabel message={message} />\n {filter !== null && (\n <FilterRow filter={filter} shown={options.length} total={totalCount} />\n )}\n {filter && options.length === 0 && (\n <Text dimColor>No options match. Backspace to widen the filter.</Text>\n )}\n {viewport.needsScroll ? (\n <Box\n flexDirection=\"column\"\n marginLeft={centered ? 0 : 2}\n marginTop={message ? 1 : 0}\n >\n <Text dimColor>\n {viewport.hiddenAbove > 0\n ? `↑ ${viewport.hiddenAbove} more${\n filter === null ? ' [P] for previous page' : ''\n }`\n : ' '}\n </Text>\n {options\n .slice(viewport.start, viewport.end)\n .map((opt, relIdx) => renderOption(opt, viewport.start + relIdx))}\n <Text dimColor>\n {viewport.hiddenBelow > 0\n ? `↓ ${viewport.hiddenBelow} more${\n filter === null ? ' [N] for next page' : ''\n }`\n : ' '}\n </Text>\n </Box>\n ) : (\n <Box\n flexDirection=\"row\"\n gap={4}\n marginLeft={centered ? 0 : 2}\n marginTop={message ? 1 : 0}\n >\n {columnArrays.map((colOpts, colIdx) => (\n <Box key={colIdx} flexDirection=\"column\">\n {colOpts.map((opt, rowIdx) =>\n renderOption(opt, colIdx * rows + rowIdx),\n )}\n </Box>\n ))}\n </Box>\n )}\n <Box marginTop={1} marginLeft={centered ? 0 : 2}>\n <ConfirmButton focused={onButton} count={selected.size} />\n </Box>\n </Box>\n );\n};\n","/**\n * Mount an Ink picker over a command's `children` and dispatch the\n * selected child's handler.\n *\n * Used as the `interactiveDefault` for family parents like\n * `wizard audit` — when the user invokes the parent without a leaf, this\n * shows a TUI menu instead of yargs's `demandCommand(1)` help dump.\n *\n * The picker opens when a family surfaces more than one option; the `default`\n * flag controls which one is pre-highlighted. When a family surfaces a single\n * option (today `audit` → `events`), `familyCommandFactory` runs it directly\n * instead, so the user lands on its intro screen rather than a one-item menu.\n *\n * Single-option commands aren't families — they should be flat\n * commands wired with `skillCommandFactory` / `nativeCommandFactory`\n * directly, not run through this module.\n */\n\nimport type { Arguments } from 'yargs';\nimport { Box, Text, render } from 'ink';\nimport { createElement } from 'react';\n\nimport { Colors } from '@ui/tui/styles';\nimport { PickerMenu } from '@ui/tui/primitives/PickerMenu';\n\nimport { commandKeys, type Command } from '../command';\n\ninterface FamilyPickerAppProps {\n parentLabel: string;\n options: { label: string; value: Command; hint?: string }[];\n onSelect: (cmd: Command) => void;\n}\n\nfunction FamilyPickerApp(props: FamilyPickerAppProps) {\n return createElement(\n Box,\n { flexDirection: 'column', paddingX: 1, paddingY: 1 },\n createElement(\n Text,\n { bold: true, color: Colors.accent },\n props.parentLabel,\n ),\n createElement(Box, { height: 1 }),\n createElement(PickerMenu<Command>, {\n message: 'Pick a subcommand',\n options: props.options,\n optionMarginBottom: 1,\n onSelect: (value) => {\n // PickerMenu in single mode returns one value; only the multi-mode\n // signature is the array variant. Narrow defensively.\n const cmd = Array.isArray(value) ? value[0] : value;\n if (cmd) props.onSelect(cmd);\n },\n }),\n );\n}\n\nfunction describe(child: Command): string {\n // Strip positional syntax (`search <query>` → `search`) for the picker label.\n return commandKeys(child.name)[0] ?? '';\n}\n\n/**\n * Reorder children so the `default`-marked entry is first, while\n * preserving the relative order of the rest. The picker's initial\n * focus is index 0, so this is what makes \"press Enter on\n * `wizard audit`\" run the default leaf (today `audit events`).\n *\n * Exported for testability — the ordering logic stays pure and\n * inspectable without mounting Ink.\n */\nexport function orderFamilyChildren(children: readonly Command[]): Command[] {\n const selectable = children.filter((c) => c.handler || c.children?.length);\n const defaults = selectable.filter((c) => c.default);\n const rest = selectable.filter((c) => !c.default);\n return [...defaults, ...rest];\n}\n\n/**\n * Render the picker. Resolves once the user has selected a child;\n * dispatching the child's handler is the caller's responsibility (so this\n * function stays pure-UI and easy to test by stubbing `render`).\n */\nexport function chooseFamilyChild(\n parentLabel: string,\n children: readonly Command[],\n): Promise<Command | null> {\n const ordered = orderFamilyChildren(children);\n if (ordered.length === 0) return Promise.resolve(null);\n\n const options = ordered.map((child) => ({\n label: describe(child),\n value: child,\n hint: child.description,\n }));\n\n return new Promise((resolve) => {\n let app: ReturnType<typeof render> | null = null;\n const handleSelect = (cmd: Command): void => {\n app?.unmount();\n resolve(cmd);\n };\n app = render(\n createElement(FamilyPickerApp, {\n parentLabel,\n options,\n onSelect: handleSelect,\n }),\n );\n });\n}\n\n/**\n * Returns an `interactiveDefault` handler for a family parent's no-leaf\n * invocation. Always opens the picker; the `default`-marked child is\n * shown first (pre-highlighted), so a single Enter keystroke runs it.\n *\n * Discovery + consent in one extra keystroke vs. auto-running silently.\n *\n * Wire onto a family parent:\n * export const auditCommand: Command = {\n * name: 'audit',\n * description: '...',\n * children: [...],\n * interactiveDefault: createFamilyPickerDefault('audit', auditChildren),\n * };\n */\nexport function createFamilyPickerDefault(\n parentLabel: string,\n children: readonly Command[],\n chooser: (\n label: string,\n children: readonly Command[],\n ) => Promise<Command | null> = chooseFamilyChild,\n): (argv: Arguments) => Promise<void> {\n return async (argv) => {\n const chosen = await chooser(parentLabel, children);\n if (!chosen) return;\n // We forward the PARENT's parsed argv straight to the chosen child. The\n // child's own option defaults and `check` validator do NOT run on this\n // path — they only run when the leaf is invoked directly\n // (`wizard audit events`). Harmless while leaves declare neither, but if a\n // leaf ever grows a `check` or a defaulted option, this path will skip it.\n await Promise.resolve(chosen.handler?.(argv));\n };\n}\n","import type { Arguments } from 'yargs';\n\nimport type { ProgramConfig } from '@lib/programs/program-step';\nimport {\n buildFamilyPickerChildren,\n dispatchFamily,\n pickerChildrenToShow,\n} from '@lib/programs/dispatch-family';\nimport { getSkillsBaseUrl } from '@lib/constants';\nimport { fetchSkillMenu } from '@lib/wizard-tools';\n\nimport type { Command } from '../command';\nimport { createFamilyPickerDefault } from './family-picker';\nimport { mergeCommandOptions, runCommandHandler } from './shared';\n\nexport interface FamilyCommandFactoryOpts {\n /** The family's CLI name (e.g. 'audit'). */\n family: string;\n /** Help text for `wizard <family> --help`. */\n description: string;\n /**\n * Source for shared CLI options (e.g. --install-dir) merged onto the\n * family parent. Usually the family's flagship native config, or the\n * generic agent-skill config.\n */\n optionsFrom: ProgramConfig;\n}\n\n/**\n * Build a yargs `Command` for a family parent (`wizard audit`, etc.).\n *\n * - `wizard <family> <sub>` — `dispatchFamily` resolves `<sub>` against\n * native handlers first, then the live `cliEntries` from\n * `skill-menu.json`. Unknown subs error with the available list.\n * - `wizard <family>` (no positional) — in an interactive terminal, runs the\n * family's single shown entry directly (today `audit events`, so the user\n * lands on its intro screen); opens the picker once a family shows more than\n * one. In non-TTY/CI, falls through to `dispatchFamily`, which prints\n * \"requires a subcommand\" rather than running something unprompted.\n *\n * No static yargs children. New skill-backed subcommands appear after a\n * context-mill release without a wizard release. New *native* subcommands\n * (rare) are added by updating `NATIVE_HANDLERS` in `dispatch-family.ts`.\n */\nexport function familyCommandFactory({\n family,\n description,\n optionsFrom,\n}: FamilyCommandFactoryOpts): Command {\n // Bare `wizard <family>` in an interactive terminal. With a single option\n // today (e.g. `audit events`), skip the picker and run it directly so the\n // user lands on its own intro screen rather than a one-item menu. When a\n // family grows past one shown option, this opens the picker instead — no\n // wiring change needed.\n const openFamilyEntry = async (argv: Arguments): Promise<void> => {\n const skillsBaseUrl = getSkillsBaseUrl();\n const menu = await fetchSkillMenu(skillsBaseUrl);\n const children = buildFamilyPickerChildren(family, menu?.cliEntries ?? []);\n const toShow = pickerChildrenToShow(children);\n if (toShow.length === 1 && toShow[0]?.handler) {\n await Promise.resolve(toShow[0].handler(argv));\n return;\n }\n const picker = createFamilyPickerDefault(`wizard ${family}`, toShow);\n await picker(argv);\n };\n\n return {\n name: `${family} [skill]`,\n description,\n options: mergeCommandOptions(optionsFrom),\n positionals: {\n skill: {\n type: 'string',\n describe: 'Subcommand to run (omit to run the default)',\n },\n },\n handler: (argv: Arguments) => {\n const sub = (argv.skill as string | undefined)?.trim();\n // With a subcommand, resolve and run it. Without one, run the family's\n // default entry (or open the picker if there's more than one) — but only\n // in an interactive terminal. In non-TTY/CI, fall through to\n // dispatchFamily, which prints \"requires a subcommand\" rather than\n // running something unprompted or hanging on a picker that can't render.\n // runCommandHandler awaits the async work so a rejection surfaces as a\n // clean error instead of an unhandled promise rejection.\n runCommandHandler(() =>\n sub || !process.stdout.isTTY\n ? dispatchFamily(family, argv)\n : openFamilyEntry(argv),\n );\n },\n interactiveDefault: openFamilyEntry,\n };\n}\n","import { auditConfig } from '@lib/programs/audit/index';\n\nimport type { Command } from './command';\nimport { familyCommandFactory } from './factories/family-command-factory';\n\n/**\n * The `wizard audit` family.\n *\n * Subcommands are resolved at runtime: the wizard fetches `cliEntries` from\n * `skill-menu.json` and dispatches based on `parentCommand: 'audit'`. The\n * wizard-native handler for `web-analytics` lives in `NATIVE_HANDLERS` over\n * in `dispatch-family.ts`. `wizard audit` with no positional opens the\n * family picker, which combines native + live entries.\n *\n * Adding a new skill-backed audit subcommand is a context-mill release —\n * no wizard release needed.\n */\nexport const auditCommand: Command = familyCommandFactory({\n family: 'audit',\n description: auditConfig.description,\n optionsFrom: auditConfig,\n});\n","import { getUI, setUI } from '@ui';\nimport { LoggingUI } from '@ui/logging-ui';\nimport { readApiKeyFromEnv } from '@utils/env-api-key';\nimport { ErrorCodes } from '@lib/errors';\nimport { emitWizardError } from '@lib/errors';\nimport { runWizard } from '@lib/runners';\nimport {\n posthogDoctorConfig,\n fetchHealthIssues,\n getKindMeta,\n} from '@lib/programs/posthog-doctor/index';\nimport { skillProgramOptions } from './skill-program-options';\nimport type { Command } from './command';\n\nexport const doctorCommand: Command = {\n name: 'doctor',\n description: posthogDoctorConfig.description,\n options: {\n ...skillProgramOptions,\n ...(posthogDoctorConfig.cliOptions ?? {}),\n },\n handler: (argv) => {\n const extras =\n posthogDoctorConfig.mapCliOptions?.(argv as Record<string, unknown>) ??\n {};\n const options = { ...argv, ...extras };\n // doctor is otherwise a TUI-only diagnostic (it has no agent run); in CI we\n // fetch the project's health issues headlessly and report them instead.\n if (options.ci) {\n void runDoctorCI(options);\n } else {\n runWizard(posthogDoctorConfig, options);\n }\n },\n};\n\nconst SEVERITY_ORDER = { critical: 0, warning: 1, info: 2 } as const;\n\nasync function runDoctorCI(options: Record<string, unknown>): Promise<void> {\n setUI(new LoggingUI());\n const apiKey = (options.apiKey as string) ?? readApiKeyFromEnv() ?? undefined;\n if (!apiKey) {\n getUI().intro('PostHog Wizard');\n getUI().log.error('CI mode requires --api-key (personal API key phx_xxx)');\n emitWizardError({\n code: ErrorCodes.ArgsMissingApiKey,\n message: 'CI mode requires --api-key (personal API key phx_xxx)',\n });\n process.exit(1);\n }\n\n getUI().intro('Welcome to the PostHog setup wizard');\n getUI().log.info('Running posthog-doctor in CI mode');\n\n try {\n const { getOrAskForProjectData } = await import('@utils/setup-utils');\n const { host, accessToken, projectId } = await getOrAskForProjectData({\n signup: false,\n ci: true,\n apiKey,\n projectId: options.projectId\n ? Number(options.projectId as string)\n : undefined,\n baseUrl: options.baseUrl as string | undefined,\n });\n\n const issues = await fetchHealthIssues(\n accessToken,\n host.apiHost,\n projectId,\n );\n if (issues.length === 0) {\n getUI().log.success('No active issues — your project looks healthy.');\n process.exit(0);\n }\n\n const sorted = [...issues].sort(\n (a, b) => SEVERITY_ORDER[a.severity] - SEVERITY_ORDER[b.severity],\n );\n getUI().log.warn(\n `${issues.length} active issue${issues.length === 1 ? '' : 's'} found:`,\n );\n for (const issue of sorted) {\n getUI().log.info(\n ` • [${issue.severity}] ${getKindMeta(issue.kind).title}`,\n );\n }\n process.exit(1);\n } catch (error) {\n const { ApiError } = await import('@lib/api');\n const message =\n error instanceof ApiError && error.statusCode === 401\n ? 'Your PostHog API key is invalid or expired.'\n : error instanceof Error\n ? error.message\n : String(error);\n getUI().log.error(`Doctor failed: ${message}`);\n emitWizardError({\n code:\n error instanceof ApiError && error.statusCode === 401\n ? ErrorCodes.AuthInvalidOrExpired\n : ErrorCodes.InternalUnhandled,\n message,\n });\n process.exit(1);\n }\n}\n","import { migrationConfig } from '@lib/programs/migration/index';\n\nimport type { Command } from './command';\nimport { nativeCommandFactory } from './factories/native-command-factory';\n\n/**\n * `wizard migrate` — flat skill command, Statsig today.\n *\n * Stays flat while there's only one vendor. When a second vendor lands,\n * restructure into a family with `familyCommandFactory` and publish each\n * vendor as a `cliEntries` entry with `parentCommand: 'migrate'` from\n * context-mill. That move is a deliberate breaking change for users\n * (`wizard migrate` stops running Statsig directly), so do it explicitly\n * when the second vendor arrives, not pre-emptively.\n */\nexport const migrateCommand: Command = nativeCommandFactory(migrationConfig);\n","import { revenueAnalyticsConfig } from '@lib/programs/revenue-analytics/index';\n\nimport type { Command } from './command';\nimport { nativeCommandFactory } from './factories/native-command-factory';\n\n/**\n * `wizard revenue-analytics` — flat skill command, Stripe today.\n *\n * Stays flat while there's only one provider. Restructure into a family\n * if/when a second provider lands.\n */\nexport const revenueCommand: Command = nativeCommandFactory(\n revenueAnalyticsConfig,\n);\n","import { warehouseSourceConfig } from '@lib/programs/warehouse-source/index';\n\nimport type { Command } from './command';\nimport { nativeCommandFactory } from './factories/native-command-factory';\n\n/**\n * `wizard warehouse` — detect and connect a data warehouse source.\n *\n * Mirrors `revenue-analytics`: flat skill command driven by the\n * warehouse-source program.\n */\nexport const warehouseCommand: Command = nativeCommandFactory(\n warehouseSourceConfig,\n);\n","import { runWizard, runWizardCI } from '@lib/runners';\nimport { selfDrivingConfig } from '@lib/programs/self-driving/index';\nimport { skillProgramOptions } from './skill-program-options';\nimport type { Command } from './command';\n\nexport const selfDrivingCommand: Command = {\n name: 'self-driving',\n description: selfDrivingConfig.description,\n options: {\n ...skillProgramOptions,\n integrate: {\n describe:\n 'Integrate the PostHog SDK first, then set up Self-driving — skips the integration prompt and logs you in via OAuth (no \"create an account?\" question). Use when the project isn\\'t set up yet but you already have a PostHog account.',\n type: 'boolean',\n default: false,\n },\n ...(selfDrivingConfig.cliOptions ?? {}),\n },\n check: (argv) => {\n // self-driving builds on an existing integration and is fully interactive,\n // so the modes that break it are rejected before the TUI/agent loop spins\n // up rather than failing late (a 403 on the first MCP probe under --signup,\n // or a stalled `wizard_ask` with no bridge under --ci).\n if (argv.signup) {\n throw new Error(\n '`self-driving` cannot run with --signup. Just run `wizard ' +\n 'self-driving`: when your project has no PostHog, it asks whether ' +\n 'you already have an account and offers to create one for you ' +\n '(no flag needed).',\n );\n }\n if (argv.ci) {\n throw new Error(\n '`self-driving` cannot run in CI mode — it requires interactive steps ' +\n '(GitHub connect, issue-tracker selection, custom-scout approval).',\n );\n }\n return true;\n },\n handler: (argv) => {\n const extras =\n selfDrivingConfig.mapCliOptions?.(argv as Record<string, unknown>) ?? {};\n const options = { ...argv, ...extras };\n if (options.ci) {\n runWizardCI(selfDrivingConfig, options);\n } else {\n runWizard(selfDrivingConfig, options);\n }\n },\n};\n","import type { Arguments } from 'yargs';\nimport { getUI, setUI } from '@ui';\nimport { LoggingUI } from '@ui/logging-ui';\nimport { Program } from '@lib/programs/program-registry';\nimport { VERSION } from '@lib/version';\nimport { ErrorCodes } from '@lib/errors';\nimport { emitWizardError } from '@lib/errors';\nimport type { Command } from './command';\n\nexport const slackCommand: Command = {\n name: 'slack',\n description: 'Connect PostHog to your Slack',\n handler: runSlackConnect,\n // Mirrors the mcp command family shape: `wizard slack` and\n // `wizard slack add` run the same connect flow.\n children: [\n {\n name: 'add',\n description: 'Connect PostHog to your Slack',\n handler: runSlackConnect,\n },\n ],\n};\n\nfunction runSlackConnect(argv: Arguments): void {\n void (async () => {\n const debug = argv.debug as boolean | undefined;\n\n try {\n const { startTUI } = await import('@ui/tui/start-tui');\n const { buildSession } = await import('@lib/wizard-session');\n const tui = startTUI(VERSION, Program.SlackConnect);\n tui.store.session = buildSession({\n debug,\n baseUrl: argv.baseUrl as string | undefined,\n });\n } catch (err) {\n // TUI unavailable — connecting Slack has no headless fallback.\n setUI(new LoggingUI());\n getUI().log.error(\n `Connecting Slack requires an interactive terminal. ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n emitWizardError({\n code: ErrorCodes.CliInteractiveRequired,\n message: 'Connecting Slack requires an interactive terminal.',\n });\n process.exit(1);\n }\n })();\n}\n","import { runWizard, runWizardCI } from '@lib/runners';\nimport { errorTrackingUploadSourceMapsConfig } from '@lib/programs/error-tracking-upload-source-maps/index';\nimport { skillProgramOptions } from './skill-program-options';\nimport type { Command } from './command';\n\nexport const uploadSourcemapsCommand: Command = {\n // Must match ProgramConfig.command; legacy alias kept for #489 regression.\n name: [errorTrackingUploadSourceMapsConfig.command!, 'upload-sourcemaps'],\n description: errorTrackingUploadSourceMapsConfig.description,\n options: {\n ...skillProgramOptions,\n ...(errorTrackingUploadSourceMapsConfig.cliOptions ?? {}),\n },\n handler: (argv) => {\n const extras =\n errorTrackingUploadSourceMapsConfig.mapCliOptions?.(\n argv as Record<string, unknown>,\n ) ?? {};\n const options = { ...argv, ...extras };\n if (options.ci) {\n runWizardCI(errorTrackingUploadSourceMapsConfig, options);\n } else {\n runWizard(errorTrackingUploadSourceMapsConfig, options);\n }\n },\n};\n","import { errorTrackingConfig } from '@lib/programs/error-tracking/index';\n\nimport type { Command } from './command';\nimport { nativeCommandFactory } from './factories/native-command-factory';\n\n/**\n * `wizard error-tracking` — flat skill command, set up error tracking today.\n *\n * Wires up exception capture and — where the platform needs it — source-map /\n * debug-symbol upload. Runs the `error-tracking` orchestrator flow, which\n * reuses the integration-v2 install/init mini-agents when the repo has no\n * PostHog integration yet, so it works on uninstrumented projects too.\n */\nexport const errorTrackingCommand: Command =\n nativeCommandFactory(errorTrackingConfig);\n","import type { Arguments } from 'yargs';\nimport { POSTHOG_DOCS_URL } from '@lib/constants';\nimport { runWizard, runWizardCI } from '@lib/runners';\nimport { createSkillProgram } from '@lib/programs/agent-skill/index';\n\n/** Run an arbitrary context-mill skill by id (`wizard skill <id>`, headless with `--ci`). */\nexport function runSkillMode(argv: Arguments): void {\n const skillId = argv.skill as string;\n const config = createSkillProgram({\n skillId,\n command: 'skill',\n id: 'agent-skill',\n description: `Run skill: ${skillId}`,\n integrationLabel: skillId,\n successMessage: `${skillId} completed!`,\n reportFile: `posthog-${skillId}-report.md`,\n docsUrl: POSTHOG_DOCS_URL,\n spinnerMessage: `Running ${skillId}...`,\n estimatedDurationMinutes: 5,\n });\n const options = { ...argv, skillId };\n if (argv.ci) {\n runWizardCI(config, options);\n } else {\n runWizard(config, options);\n }\n}\n","import type { Arguments } from 'yargs';\n\nimport { getSkillsBaseUrl } from '@lib/constants';\nimport { fetchSkillMenu, type CliEntry } from '@lib/wizard-tools';\nimport { analytics } from '@utils/analytics';\n\nimport { runSkillMode } from './basic-integration/skill';\nimport { skillProgramOptions } from './skill-program-options';\nimport { runCommandHandler } from './factories/shared';\nimport { ErrorCodes } from '@lib/errors';\nimport { emitWizardError } from '@lib/errors';\nimport type { Command } from './command';\n\n/** Read the `<skill-name>` positional (yargs camelCases the hyphenated key). */\nfunction readSkillName(argv: Arguments): string {\n return String(argv.skillName ?? argv['skill-name'] ?? '').trim();\n}\n\nconst BROWSABLE_ROLES: ReadonlySet<CliEntry['role']> = new Set([\n 'command',\n 'skill',\n]);\n\n/**\n * Reject an unknown skill id before the wizard authenticates.\n *\n * Without this, `readSkillName` accepts any non-empty string and the name is\n * only validated far downstream, when the agent tries to download it — after\n * the user has already logged in. A typo then costs a full auth round-trip\n * (the concern raised in review). We resolve against the same set\n * `downloadSkill` uses (`categories` flattened by `id`), so this never\n * false-rejects a skill the download would have accepted.\n *\n * If the registry is unreachable we stay silent and defer to the download\n * step's own `menu-fetch-failed` handling, rather than adding a second network\n * dependency that could block an otherwise-valid run.\n */\nasync function assertSkillExists(skillName: string): Promise<void> {\n const skillsBaseUrl = getSkillsBaseUrl();\n const menu = await fetchSkillMenu(skillsBaseUrl);\n if (!menu) return; // registry down — let the download step surface it\n const known = Object.values(menu.categories)\n .flat()\n .some((s) => s.id === skillName);\n if (known) return;\n analytics.wizardCapture('cli dispatch error', {\n reason: 'unknown skill',\n family: 'skill',\n sub: skillName,\n skillsBaseUrl,\n });\n try {\n await analytics.flush();\n } catch {\n /* best-effort */\n }\n throw new Error(\n `Unknown skill \"${skillName}\". Run \\`wizard skill list\\` to see available skills.`,\n );\n}\n\nfunction formatEntry(entry: CliEntry): string {\n const path = entry.parentCommand\n ? `wizard ${entry.parentCommand} ${entry.command}`\n : entry.command\n ? `wizard ${entry.command}`\n : `wizard skill ${entry.skillId}`;\n return ` ${entry.skillId.padEnd(38)} ${path.padEnd(36)} ${\n entry.description\n }`;\n}\n\n/**\n * `wizard skill list` — fetch and print every browsable skill in the catalog.\n *\n * Reads the live `skill-menu.json` so new skills appear immediately after a\n * context-mill release. `internal` skills are excluded from the listing.\n */\nconst listCommand: Command = {\n name: 'list',\n description: 'List every browsable skill in the catalog',\n handler: () => {\n runCommandHandler(async () => {\n const skillsBaseUrl = getSkillsBaseUrl();\n const menu = await fetchSkillMenu(skillsBaseUrl);\n if (!menu) {\n analytics.wizardCapture('cli dispatch error', {\n reason: 'registry unreachable',\n family: 'skill',\n sub: 'list',\n skillsBaseUrl,\n });\n try {\n await analytics.flush();\n } catch {\n /* best-effort */\n }\n process.stderr.write(\n `\\n\\x1b[1;91m✖ Couldn't reach the skill registry.\\x1b[0m\\n` +\n ` Check your network connection and try again.\\n\\n`,\n );\n emitWizardError({\n code: ErrorCodes.SkillMenuFetchFailed,\n message: \"Couldn't reach the skill registry.\",\n });\n process.exit(1);\n }\n const entries = (menu.cliEntries ?? []).filter((e) =>\n BROWSABLE_ROLES.has(e.role),\n );\n if (entries.length === 0) {\n process.stdout.write('No skills found.\\n');\n return;\n }\n process.stdout.write(\n `${entries.length} skill${entries.length === 1 ? '' : 's'}:\\n`,\n );\n process.stdout.write(\n ` ${'SKILL ID'.padEnd(38)} ${'COMMAND'.padEnd(36)} DESCRIPTION\\n`,\n );\n for (const entry of entries) {\n process.stdout.write(`${formatEntry(entry)}\\n`);\n }\n });\n },\n};\n\n/**\n * `wizard skill <skill-name>` — run a single context-mill skill by id.\n * `wizard skill list` — list every browsable skill in the catalog.\n *\n * Replaces the old `--skill=<id>` flag on the default command. The skill id\n * is fetched from context-mill's release at runtime (same mechanism the flag\n * used), so any published skill id works. Pass `--ci` to run headlessly.\n */\nexport const skillCommand: Command = {\n name: 'skill <skill-name>',\n description: 'Run a specific context-mill skill by name (or `list` them)',\n children: [listCommand],\n options: {\n ...skillProgramOptions,\n },\n // Under `.strictOptions()` yargs rejects a positional declared only in the\n // command string as an \"Unknown argument\" — it has to be registered via\n // `.positional()` too (see the `positionals` note on the Command interface).\n // Declare `skill-name` here so `wizard skill <id>` actually accepts its value.\n positionals: {\n 'skill-name': {\n type: 'string',\n describe: 'Skill id to run (e.g. audit-events), or `list`',\n },\n },\n // yargs already enforces the presence of the `<skill-name>` positional, but\n // an explicitly-empty value (`wizard skill \"\"`) would otherwise slip\n // through to a broken run. Reject it with the same friendly message\n // the old --skill flag gave. When `wizard skill list` matched the\n // child instead, yargs leaves the positional unset — the `null` guard\n // keeps the check from rejecting that route.\n check: (argv) => {\n if (argv.skillName == null && argv['skill-name'] == null) return true;\n if (!readSkillName(argv)) {\n throw new Error(\n 'skill needs a skill name, e.g. `wizard skill audit-events`',\n );\n }\n return true;\n },\n handler: (argv) => {\n runCommandHandler(async () => {\n const skillName = readSkillName(argv);\n await assertSkillExists(skillName);\n // runSkillMode reads `argv.skill`; bridge the positional onto it.\n runSkillMode({ ...argv, skill: skillName });\n });\n },\n};\n","import * as path from 'node:path';\nimport * as readline from 'node:readline/promises';\nimport type { Arguments } from 'yargs';\nimport { getUI, setUI } from '@ui';\nimport { LoggingUI } from '@ui/logging-ui';\nimport { analytics } from '@utils/analytics';\nimport {\n CLI_STEERING_TARGETS,\n type CliSteeringTarget,\n detectTargets,\n findTarget,\n installOrUpdatePostHogCli,\n installSteeringSnippet,\n} from '@steps/install-cli-steering';\nimport type { Command } from '../command';\n\nexport const cliAddCommand: Command = {\n name: 'add',\n description:\n \"Install or update PostHog CLI and add steering instructions to your coding agent's global instructions file\",\n options: {\n agent: {\n describe: 'Agent to install the instructions for',\n choices: CLI_STEERING_TARGETS.map((target) => target.id),\n type: 'string',\n },\n path: {\n describe:\n 'Write to an explicit instructions file instead of a detected agent',\n type: 'string',\n },\n all: {\n default: false,\n describe: 'Install for every detected agent without prompting',\n type: 'boolean',\n },\n },\n examples: [\n ['wizard cli add', 'Detect your coding agents and pick one'],\n [\n 'wizard cli add --agent claude-code',\n 'Install for Claude Code (~/.claude/CLAUDE.md)',\n ],\n ['wizard cli add --all', 'Install for every detected agent'],\n [\n 'wizard cli add --path ./AGENTS.md',\n 'Install into a specific instructions file',\n ],\n ],\n check: (argv) => {\n if (argv.all && (argv.agent || argv.path)) {\n throw new Error('--all cannot be combined with --agent or --path');\n }\n return true;\n },\n handler: (argv) => {\n void runCliAdd(argv);\n },\n};\n\nasync function runCliAdd(argv: Arguments): Promise<void> {\n setUI(new LoggingUI());\n const ui = getUI();\n ui.intro('PostHog CLI setup');\n\n const files = await resolveTargetFiles(argv);\n if (files.length === 0) {\n process.exit(1);\n return;\n }\n\n ui.log.info('Installing or updating PostHog CLI...');\n const cliInstallResult = installOrUpdatePostHogCli();\n if (!cliInstallResult.success) {\n ui.log.error(\n `Failed to install or update PostHog CLI: ${\n cliInstallResult.error ?? ''\n }`,\n );\n analytics.wizardCapture('cli steering installed', {\n files: files.length,\n failures: files.length,\n cli_install_failed: true,\n agent: typeof argv.agent === 'string' ? argv.agent : undefined,\n });\n process.exit(1);\n return;\n }\n ui.log.success('Installed or updated PostHog CLI.');\n\n let failures = 0;\n for (const file of files) {\n const result = installSteeringSnippet(file);\n if (result.success) {\n ui.log.success(`Installed PostHog steering instructions in ${file}`);\n } else {\n failures += 1;\n ui.log.error(`Failed to update ${file}: ${result.error ?? ''}`);\n }\n }\n\n analytics.wizardCapture('cli steering installed', {\n files: files.length,\n failures,\n agent: typeof argv.agent === 'string' ? argv.agent : undefined,\n });\n\n if (failures > 0) {\n process.exit(1);\n return;\n }\n ui.outro(\n 'Done. PostHog CLI is installed and your agent will now use `posthog-cli api` for PostHog tasks.',\n );\n process.exit(0);\n}\n\n/** Resolve which instruction files to write, from flags, detection, or a prompt. */\nasync function resolveTargetFiles(argv: Arguments): Promise<string[]> {\n const ui = getUI();\n\n if (typeof argv.path === 'string' && argv.path.trim()) {\n return [path.resolve(argv.path.trim())];\n }\n\n if (typeof argv.agent === 'string') {\n // yargs `choices` already rejected unknown ids.\n const target = findTarget(argv.agent);\n if (!target) {\n ui.log.error(`Unsupported agent: ${argv.agent}`);\n return [];\n }\n return [target.instructionsPath()];\n }\n\n const detected = detectTargets();\n if (detected.length === 0) {\n ui.log.error(\n 'No supported coding agents detected. Pass --agent <id> or --path <file> to choose a target.',\n );\n ui.log.info(\n `Supported agents: ${CLI_STEERING_TARGETS.map((t) => t.id).join(', ')}`,\n );\n return [];\n }\n\n if (argv.all === true) {\n ui.log.info(\n `Installing for all detected agents: ${detected\n .map((t) => t.name)\n .join(', ')}`,\n );\n return detected.map((target) => target.instructionsPath());\n }\n\n if (detected.length === 1) {\n ui.log.info(\n `Detected ${detected[0].name} (${detected[0].instructionsPath()})`,\n );\n return [detected[0].instructionsPath()];\n }\n\n // Non-interactive shells can't pick, so install for every detected agent —\n // the snippet is additive and idempotent, mirroring how MCP install treats\n // all supported clients.\n if (!process.stdin.isTTY || !process.stdout.isTTY) {\n ui.log.info(\n `Installing for all detected agents: ${detected\n .map((t) => t.name)\n .join(', ')}`,\n );\n return detected.map((target) => target.instructionsPath());\n }\n\n const selected = await promptForTargets(detected);\n return selected.map((target) => target.instructionsPath());\n}\n\n/** Minimal numbered selection — this command is intentionally not a TUI flow. */\nasync function promptForTargets(\n detected: CliSteeringTarget[],\n): Promise<CliSteeringTarget[]> {\n const ui = getUI();\n ui.log.info('Which coding agent are you using?');\n detected.forEach((target, index) => {\n ui.log.info(\n ` ${index + 1}) ${target.name} (${target.instructionsPath()})`,\n );\n });\n ui.log.info(` ${detected.length + 1}) All of the above`);\n\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n try {\n for (;;) {\n const answer = (\n await rl.question(`Select 1-${detected.length + 1}: `)\n ).trim();\n const choice = Number(answer);\n if (\n Number.isInteger(choice) &&\n choice >= 1 &&\n choice <= detected.length\n ) {\n return [detected[choice - 1]];\n }\n if (choice === detected.length + 1) {\n return detected;\n }\n ui.log.warn(`Enter a number between 1 and ${detected.length + 1}.`);\n }\n } finally {\n rl.close();\n }\n}\n","import { cliAddCommand } from './add';\nimport type { Command } from '../command';\n\nexport const cliCommand: Command = {\n name: 'cli',\n description: 'PostHog CLI agent integration commands',\n children: [cliAddCommand],\n};\n","#!/usr/bin/env node\nimport { satisfies } from 'semver';\nimport { Agent, setGlobalDispatcher } from 'undici';\nimport { ErrorCodes } from './src/lib/errors/codes.js';\nimport { emitWizardError } from './src/lib/errors/emit.js';\n\n// Keep in sync with `engines.node` in package.json. npx does not enforce\n// engines, so this preflight is the only thing standing between an old Node\n// runtime and a cryptic dependency crash (e.g. undici's markAsUncloneable\n// TypeError on Node < 22.10).\nconst NODE_VERSION_RANGE = '>=22.22.0';\n\n/*\n * TODO(#1198): remove when fetch over HTTP/2 is safe on Node 26. Remove when all\n * of these are true:\n * - nodejs/node no longer creates an orphan ClientHttp2Stream when a client\n * session gets HEADERS for a stream id it already reset. Repro: abort a fetch\n * before its response headers, then idle 4s on Node 26. Fixed when the\n * process survives.\n * - modelcontextprotocol/typescript-sdk#2526 is closed.\n * - pi-coding-agent's CLI drops `allowH2: false` from its http-dispatcher.\n * Same workaround as pi's CLI and typescript-sdk#2526: HTTP/1.1 only.\n */\nsetGlobalDispatcher(new Agent({ allowH2: false }));\n\n// Have to run this above the other imports because they are importing clack that\n// has the problematic imports.\nif (!satisfies(process.version, NODE_VERSION_RANGE)) {\n // eslint-disable-next-line no-console\n console.log(\n [\n `The PostHog wizard needs a newer version of Node.js to run.`,\n ``,\n ` You have: ${process.version}`,\n ` You need: v${NODE_VERSION_RANGE.replace('>=', '')} or later`,\n ``,\n `To update Node.js:`,\n ``,\n ` Download the latest version from https://nodejs.org/en/download`,\n ` Or, if you use nvm, run: nvm install 22 && nvm use 22`,\n ``,\n `Then run the wizard again. Stuck? Email wizard@posthog.com and we'll help.`,\n ].join('\\n'),\n );\n emitWizardError({\n code: ErrorCodes.CliNodeVersion,\n message: `Node ${process.version} is below the required range ${NODE_VERSION_RANGE}`,\n });\n process.exit(1);\n}\n\n// Test mock server — only loaded when NODE_ENV is 'test'.\n// In production builds, tsdown replaces process.env.NODE_ENV with 'production',\n// making this block dead code.\nif (process.env.NODE_ENV === 'test') {\n void (async () => {\n try {\n const { server } = await import('./e2e-tests/mocks/server.js');\n server.listen({\n onUnhandledRequest: 'bypass',\n });\n } catch (error) {\n // Mock server import failed - this can happen during non-E2E tests\n }\n })();\n}\n\nimport { Wizard } from './src/wizard';\nimport { basicIntegrationCommand } from './src/commands/basic-integration';\nimport { mcpCommand } from './src/commands/mcp';\nimport { mcpAnalyticsCommand } from './src/commands/mcp-analytics';\nimport { replayVisionCommand } from './src/commands/replay-vision';\nimport { aiObservabilityCommand } from './src/commands/ai-observability';\nimport { metricsCommand } from './src/commands/metrics';\nimport { auditCommand } from './src/commands/audit';\nimport { doctorCommand } from './src/commands/doctor';\nimport { migrateCommand } from './src/commands/migrate';\nimport { revenueCommand } from './src/commands/revenue';\nimport { warehouseCommand } from './src/commands/warehouse';\nimport { selfDrivingCommand } from './src/commands/self-driving';\nimport { slackCommand } from './src/commands/slack';\nimport { uploadSourcemapsCommand } from './src/commands/upload-sourcemaps';\nimport { errorTrackingCommand } from './src/commands/error-tracking';\nimport { skillCommand } from './src/commands/skill';\nimport { cliCommand } from './src/commands/cli';\nimport { recoverOrphanedSettingsBackups } from './src/lib/agent/claude-settings';\n\n// Heal any .claude/settings backup a previous interrupted run left orphaned,\n// before anything else reads Claude settings — conflict detection, OAuth, and\n// the agent all need to see the user's real settings file. The install dir is\n// read directly from argv/env because yargs hasn't parsed yet.\nrecoverOrphanedSettingsBackups(resolveInstallDir());\n\nfunction resolveInstallDir(): string {\n const args = process.argv.slice(2);\n const flagIndex = args.indexOf('--install-dir');\n if (flagIndex !== -1 && args[flagIndex + 1]) return args[flagIndex + 1];\n const inline = args.find((a) => a.startsWith('--install-dir='));\n if (inline) return inline.slice('--install-dir='.length);\n return process.env.POSTHOG_WIZARD_INSTALL_DIR ?? process.cwd();\n}\n\nWizard.use(basicIntegrationCommand)\n .use(mcpCommand)\n .use(mcpAnalyticsCommand)\n .use(replayVisionCommand)\n .use(aiObservabilityCommand)\n .use(metricsCommand)\n .use(cliCommand)\n .use(auditCommand)\n .use(doctorCommand)\n .use(migrateCommand)\n .use(revenueCommand)\n .use(warehouseCommand)\n .use(selfDrivingCommand)\n .use(slackCommand)\n .use(uploadSourcemapsCommand)\n .use(errorTrackingCommand)\n .use(skillCommand)\n .init();\n"],"mappings":"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"}
1
+ {"version":3,"file":"bin.js","names":["isUUID","validVersion","path"],"sources":["../src/commands/command.ts","../src/wizard.ts","../src/commands/provision.ts","../src/commands/basic-integration/index.ts","../src/commands/mcp/tui-availability.ts","../src/commands/mcp/add.ts","../src/commands/mcp/remove.ts","../src/commands/mcp/tutorial.ts","../src/commands/mcp/index.ts","../src/lib/runners/resolve-no-telemetry.ts","../src/lib/task-stream/wizard-run-sync.ts","../src/lib/runners/run-wizard.ts","../src/lib/programs/detect-map.ts","../src/lib/runners/run-non-interactive.ts","../src/lib/runners/run-wizard-ci.ts","../src/lib/runners/run-wizard-headless.ts","../src/commands/skill-program-options.ts","../src/commands/factories/shared.ts","../src/commands/factories/native-command-factory.ts","../src/commands/mcp-analytics.ts","../src/commands/replay-vision.ts","../src/commands/ai-observability.ts","../src/commands/metrics.ts","../src/lib/programs/dispatch-family.ts","../src/ui/tui/primitives/picker-filter.ts","../src/ui/tui/primitives/PromptLabel.tsx","../src/ui/tui/primitives/ConfirmButton.tsx","../src/ui/tui/hooks/useStdoutDimensions.ts","../src/ui/tui/hooks/keyboard-hints-utils.ts","../src/ui/tui/hooks/useKeyboardHints.tsx","../src/ui/tui/hooks/useKeyBindings.ts","../src/ui/tui/primitives/PickerMenu.tsx","../src/commands/factories/family-picker.tsx","../src/commands/factories/family-command-factory.ts","../src/commands/audit.ts","../src/commands/doctor.ts","../src/commands/migrate.ts","../src/commands/revenue.ts","../src/commands/warehouse.ts","../src/commands/self-driving.ts","../src/commands/slack.ts","../src/commands/upload-sourcemaps.ts","../src/commands/error-tracking.ts","../src/commands/basic-integration/skill.ts","../src/commands/skill.ts","../src/commands/cli/add.ts","../src/commands/cli/index.ts","../bin.ts"],"sourcesContent":["import type {\n Arguments,\n Argv,\n CommandModule,\n Options,\n PositionalOptions,\n} from 'yargs';\nimport { setEntryCommand } from '@utils/links';\n\nexport interface Command {\n /** Yargs command name. Use `['$0']` for the default command. */\n name: string | readonly string[];\n description: string;\n /** Flags exposed by this command. Same shape as yargs `.options()`. */\n options?: Record<string, Options>;\n /**\n * Positional arguments declared in `name` (e.g. the `id` in `skill [id]`).\n * Under `.strictOptions()`, yargs only treats a positional as a known\n * argument once it's registered via `.positional()` — a command-string\n * positional alone is rejected as `Unknown argument`. Declare each one here\n * so an optional positional like `skill [id]` actually accepts its value.\n */\n positionals?: Record<string, PositionalOptions>;\n /** Nested subcommands. */\n children?: readonly Command[];\n /** `--help` examples shown for this command. */\n examples?: ReadonlyArray<readonly [string, string]>;\n /**\n * Called synchronously by yargs when the command matches. Wrap async work in\n * `void (async () => { ... })()`. Optional only when `children` is set — in\n * that case yargs requires the user to pick a subcommand (or to set\n * `interactiveDefault` for an in-process picker).\n */\n handler?: (argv: Arguments) => void;\n /**\n * Cross-flag validation run by yargs after parsing. Throw to reject (yargs\n * prints the message and exits non-zero); return `true` to accept. Prefer\n * this over per-option `conflicts` for mutually exclusive flags: yargs\n * counts a `default`-valued flag as \"present\", so `conflicts` misfires on\n * boolean flags that default to `false` — a hand-written predicate only\n * sees what you test for (e.g. truthiness).\n */\n check?: (argv: Arguments) => boolean;\n /**\n * Optional handler invoked when this command has `children` but the user\n * supplied no subcommand. Use it to mount an interactive picker over the\n * children so `wizard audit` (no leaf) opens a TUI menu instead of yargs\n * help. When set, suppresses the implicit `demandCommand(1)`.\n *\n * May return a Promise — yargs awaits the result before exiting.\n */\n interactiveDefault?: (argv: Arguments) => void | Promise<void>;\n /**\n * When true, this child is the \"default\" leaf in its family: the\n * family picker pre-highlights it so a single Enter runs it. The picker\n * still always opens — this never auto-runs the child. At most one child\n * per parent should be marked. Propagated from the context-mill manifest\n * entry's `default` flag through `skillCommandFactory`.\n */\n default?: boolean;\n}\n\n/** Extract the bare command word(s) from a yargs name spec, dropping positionals and aliases' arg syntax. */\nexport function commandKeys(name: string | readonly string[]): string[] {\n const list: readonly string[] = typeof name === 'string' ? [name] : name;\n return list.map((n) => n.trim().split(/\\s+/)[0]);\n}\n\nexport function toCommandModule(\n cmd: Command,\n parentPath: readonly string[],\n): CommandModule {\n // `wizard slack` → 'slack', `wizard mcp add` → 'mcp-add'. The default\n // `$0` resolves to '' and is skipped — its handler reports itself.\n const entryCommand = [...parentPath, commandKeys(cmd.name)[0]]\n .filter((key) => key !== '$0')\n .join('-');\n return {\n command: cmd.name,\n describe: cmd.description,\n builder: (y: Argv) => {\n let next = cmd.options ? y.options(cmd.options) : y;\n for (const [key, opts] of Object.entries(cmd.positionals ?? {})) {\n next = next.positional(key, opts);\n }\n if (cmd.check) next = next.check(cmd.check);\n for (const [usage, description] of cmd.examples ?? []) {\n next = next.example(usage, description);\n }\n const ownPath = [...parentPath, commandKeys(cmd.name)[0]];\n for (const child of cmd.children ?? []) {\n next = next.command(toCommandModule(child, ownPath));\n }\n if (cmd.children?.length && !cmd.handler && !cmd.interactiveDefault) {\n next = next.demandCommand(1);\n }\n return next;\n },\n handler: (argv: Arguments) => {\n if (entryCommand) setEntryCommand(entryCommand);\n const run = cmd.handler ?? cmd.interactiveDefault ?? (() => undefined);\n run(argv);\n },\n };\n}\n","import yargs from 'yargs';\nimport { hideBin } from 'yargs/helpers';\nimport type { Argv } from 'yargs';\nimport { IS_PRODUCTION_BUILD } from '@env';\nimport { Harness, Sequence } from '@shared/constants';\nimport { regionOption } from '@lib/headless-mode';\nimport { initLocalDev, localMcpSkillsNotice } from '@shared/local-dev';\nimport { toCommandModule, type Command } from './commands/command';\nimport { ErrorCodes } from '@shared/errors';\nimport { emitWizardError } from '@shared/errors';\n\n/**\n * Global yargs options applied to every command. These are read from the\n * `POSTHOG_WIZARD` env prefix as well as flags.\n *\n * Options with `hidden: true` are \"internal modes\" — they don't show up in\n * `--help` but are still accepted on every command. The `--local-*` flags live\n * in the constructor's `!IS_PRODUCTION_BUILD` block instead, so published\n * builds reject them; see `docs/local-dev.md`.\n */\nexport const GLOBAL_OPTIONS = {\n debug: {\n default: false,\n describe: 'Enable verbose logging\\nenv: POSTHOG_WIZARD_DEBUG',\n type: 'boolean' as const,\n },\n signup: {\n default: false,\n describe:\n 'Create a new PostHog account during setup\\nenv: POSTHOG_WIZARD_SIGNUP',\n type: 'boolean' as const,\n },\n telemetry: {\n default: true,\n describe:\n 'Send wizard run state to PostHog (pass --no-telemetry to disable)\\nenv: POSTHOG_WIZARD_TELEMETRY',\n type: 'boolean' as const,\n },\n 'api-key': {\n describe:\n 'PostHog personal API key (phx_xxx) for authentication\\nenv: POSTHOG_WIZARD_API_KEY',\n type: 'string' as const,\n },\n 'project-id': {\n describe:\n 'PostHog project ID to use (optional; when not set, uses default from API key or OAuth)\\nenv: POSTHOG_WIZARD_PROJECT_ID',\n type: 'string' as const,\n },\n email: {\n describe:\n 'Email address for signup (used with --signup)\\nenv: POSTHOG_WIZARD_EMAIL',\n type: 'string' as const,\n },\n // ── Internal modes ─────────────────────────────────────────────────\n // Hidden from `--help`.\n // NB: the experimental headless flag is deliberately NOT global. Supported\n // commands declare it through `headlessOption` in @lib/headless-mode.\n 'base-url': {\n describe:\n 'Override the PostHog base URL (e.g. http://localhost:8010), bypassing region resolution. Pins the API host, cloud URL, and OAuth server.\\nenv: POSTHOG_WIZARD_BASE_URL',\n type: 'string' as const,\n hidden: true,\n },\n 'run-id': {\n describe: 'Assigned cloud WizardRun UUID',\n type: 'string' as const,\n hidden: true,\n },\n benchmark: {\n default: false,\n describe:\n 'Run in benchmark mode with per-phase token tracking\\nenv: POSTHOG_WIZARD_BENCHMARK',\n type: 'boolean' as const,\n hidden: true,\n },\n 'yara-report': {\n default: false,\n describe:\n 'Print YARA scanner summary after the agent run\\nenv: POSTHOG_WIZARD_YARA_REPORT',\n type: 'boolean' as const,\n hidden: true,\n },\n};\n\nexport class Wizard {\n private cli: Argv;\n\n private constructor() {\n let cli: Argv = yargs(hideBin(process.argv))\n .env('POSTHOG_WIZARD')\n .options(GLOBAL_OPTIONS);\n\n // CI mode (--ci) is only supported in dev/test. It is left undeclared in\n // published builds (NODE_ENV==='production'), so .strictOptions() rejects\n // it there as an unknown argument — exactly like any other unrecognized\n // flag. init() additionally detects it up front to print a clearer message.\n // The published-build, non-interactive path is the experimental headless\n // flag, declared per-command through `headlessOption` (see\n // @lib/headless-mode). CI needs `region` globally because the workbench\n // passes it to every command. --ci and headless stay separate so their\n // behavior can diverge.\n if (!IS_PRODUCTION_BUILD) {\n cli = cli\n .options(regionOption)\n .option('ci', {\n default: false,\n describe:\n 'Enable CI mode for non-interactive execution\\nenv: POSTHOG_WIZARD_CI',\n type: 'boolean',\n hidden: true,\n })\n // Runner overrides — dev/test only, same lifecycle as --ci.\n .option('harness', {\n describe:\n 'Override the agent harness (anthropic | pi). Wins over the PostHog runner flag.\\nenv: POSTHOG_WIZARD_HARNESS',\n choices: Object.values(Harness),\n type: 'string',\n hidden: true,\n })\n .option('sequence', {\n describe:\n 'Override the runner sequence (linear | orchestrator). Wins over the PostHog orchestrator flag.\\nenv: POSTHOG_WIZARD_SEQUENCE',\n choices: Object.values(Sequence),\n type: 'string',\n hidden: true,\n })\n .option('model', {\n describe:\n 'Override the agent model (gateway id, e.g. claude-sonnet-5 | openai/gpt-5.6-terra). Wins over the binding default.\\nenv: POSTHOG_WIZARD_MODEL',\n type: 'string',\n hidden: true,\n })\n .option('capture-aio', {\n default: false,\n describe:\n \"Capture wizard LLM calls as $ai_generation events in the authenticated project's AI Observability tab.\\nenv: POSTHOG_WIZARD_CAPTURE_AIO\",\n type: 'boolean',\n hidden: true,\n })\n // Rides beside the PostHog destination rather than replacing it, so a\n // logged run is the same run the backend sees.\n .option('task-stream-log', {\n describe:\n 'Append every task-stream payload to a local JSONL file. Pass a path, or pass the flag alone for /tmp/posthog-wizard-task-stream.jsonl\\nenv: POSTHOG_WIZARD_TASK_STREAM_LOG',\n type: 'string',\n })\n // ── Local dev targets (see docs/local-dev.md) ──────────────────\n // Not `hidden`: the build gate already keeps them from users, so\n // hiding them would only cost the dev-build help row. Deliberately not\n // named `--local`, which `wizard mcp add` already uses for something\n // unrelated.\n .option('local-dev', {\n default: false,\n describe:\n 'Point context-mill, MCP, and PostHog at local dev servers\\nenv: POSTHOG_WIZARD_LOCAL_DEV',\n type: 'boolean',\n })\n // No `default` on the three below — they must stay `undefined` when\n // absent for resolveLocalDev() to honour the umbrella and `--no-*`.\n .option('local-context-mill', {\n describe:\n 'Fetch skills from the local context-mill server (http://localhost:8765)\\nenv: POSTHOG_WIZARD_LOCAL_CONTEXT_MILL',\n type: 'boolean',\n })\n .option('local-mcp', {\n describe:\n 'Use the local MCP server (http://localhost:8787/mcp). Affects MCP only — use --local-context-mill for skills.\\nenv: POSTHOG_WIZARD_LOCAL_MCP',\n type: 'boolean',\n })\n .option('local-posthog', {\n describe:\n 'Point every PostHog origin (API, app, OAuth, gateway) at http://localhost:8010\\nenv: POSTHOG_WIZARD_LOCAL_POSTHOG',\n type: 'boolean',\n });\n }\n\n this.cli = cli\n // Middleware rather than an argv scan so the env path is covered too,\n // and it runs before any TUI takes the terminal.\n .middleware((argv) => {\n // The one place local targets are resolved; everything downstream reads\n // getLocalDev().\n initLocalDev(argv);\n\n // Temporary.\n const notice = localMcpSkillsNotice({\n localDev: argv.localDev as boolean | undefined,\n localMcp: argv.localMcp as boolean | undefined,\n localContextMill: argv.localContextMill as boolean | undefined,\n });\n if (notice) {\n process.stderr.write(`\\n\\x1b[33m! ${notice}\\x1b[0m\\n\\n`);\n }\n })\n .strictOptions()\n // Reject unrecognized commands (e.g. `wizard bogus`) instead of letting\n // them fall through to the default `$0` integration flow.\n .strictCommands()\n // Print a concise error and point to `--help`, instead of yargs' default\n // of dumping the entire usage screen under every failure.\n .fail((msg, err) => {\n const text = msg || (err && err.message) || 'Invalid arguments';\n process.stderr.write(\n `\\n\\x1b[1;91m✖ ${text}\\x1b[0m\\n` +\n ` Run \\`wizard --help\\` to see available commands and options.\\n\\n`,\n );\n emitWizardError({ code: ErrorCodes.CliBadArgs, message: text });\n process.exit(1);\n })\n .help()\n .alias('help', 'h')\n .version()\n .alias('version', 'v');\n }\n\n /** Start a chain; equivalent to `new Wizard().use(...cmds)`. */\n static use(...cmds: Command[]): Wizard {\n return new Wizard().use(...cmds);\n }\n\n /** Register one or more commands with yargs. */\n use(...cmds: Command[]): this {\n for (const cmd of cmds) {\n this.cli = this.cli.command(toCommandModule(cmd, []));\n }\n return this;\n }\n\n /** Parse argv and dispatch to the matching registered command. */\n init(): void {\n // In published builds, `--ci` is undeclared, so yargs would reject it as\n // an unknown argument — accurate but unhelpful, since --help doesn't list\n // --ci either and the user has no path forward. POSTHOG_WIZARD_CI silently\n // no-ops for the same reason (yargs only resolves env vars for declared\n // options). Detect both up front and exit with a message that explains why.\n if (IS_PRODUCTION_BUILD) {\n const args = process.argv.slice(2);\n const argvHasCI = args.some(\n (a) => a === '--ci' || a === '--no-ci' || a.startsWith('--ci='),\n );\n const envHasCI =\n process.env.POSTHOG_WIZARD_CI != null &&\n process.env.POSTHOG_WIZARD_CI !== '';\n if (argvHasCI || envHasCI) {\n process.stderr.write(\n `\\n\\x1b[1;91m✖ CI mode is not currently supported in published builds.\\x1b[0m\\n\\n`,\n );\n emitWizardError({\n code: ErrorCodes.CliFlagUnavailable,\n message: 'CI mode is not supported in published builds.',\n });\n process.exit(1);\n }\n\n // --harness / --sequence / --model / --capture-aio are dev/test-only.\n // In published builds the env vars would silently no-op, so reject them\n // explicitly instead.\n const argvHasOverride = args.some(\n (a) =>\n a === '--harness' ||\n a.startsWith('--harness=') ||\n a === '--sequence' ||\n a.startsWith('--sequence=') ||\n a === '--model' ||\n a.startsWith('--model=') ||\n a === '--capture-aio' ||\n a === '--no-capture-aio' ||\n a.startsWith('--capture-aio='),\n );\n const envHasOverride =\n (process.env.POSTHOG_WIZARD_HARNESS != null &&\n process.env.POSTHOG_WIZARD_HARNESS !== '') ||\n (process.env.POSTHOG_WIZARD_SEQUENCE != null &&\n process.env.POSTHOG_WIZARD_SEQUENCE !== '') ||\n (process.env.POSTHOG_WIZARD_MODEL != null &&\n process.env.POSTHOG_WIZARD_MODEL !== '') ||\n (process.env.POSTHOG_WIZARD_CAPTURE_AIO != null &&\n process.env.POSTHOG_WIZARD_CAPTURE_AIO !== '');\n if (argvHasOverride || envHasOverride) {\n process.stderr.write(\n `\\n\\x1b[1;91m✖ The --harness, --sequence, --model, and --capture-aio overrides are not available in published builds.\\x1b[0m\\n\\n`,\n );\n emitWizardError({\n code: ErrorCodes.CliFlagUnavailable,\n message:\n 'The --harness, --sequence, --model, and --capture-aio overrides are not available in published builds.',\n });\n process.exit(1);\n }\n\n // `--local-mcp` used to be declared unconditionally, so published builds\n // accepted it and quietly aimed the run at localhost. Reject explicitly.\n const argvHasLocalTarget = args.some((a) =>\n LOCAL_TARGET_FLAGS.some(\n (f) => a === `--${f}` || a === `--no-${f}` || a.startsWith(`--${f}=`),\n ),\n );\n const envHasLocalTarget = LOCAL_TARGET_ENV_VARS.some(\n (k) => process.env[k] != null && process.env[k] !== '',\n );\n if (argvHasLocalTarget || envHasLocalTarget) {\n process.stderr.write(\n `\\n\\x1b[1;91m✖ The --local-dev, --local-context-mill, --local-mcp, and --local-posthog targets are not available in published builds.\\x1b[0m\\n` +\n ` They point the wizard at development servers on localhost.\\n\\n`,\n );\n emitWizardError({\n code: ErrorCodes.CliFlagUnavailable,\n message:\n 'The --local-dev, --local-context-mill, --local-mcp, and --local-posthog targets are not available in published builds.',\n });\n process.exit(1);\n }\n }\n void this.cli.wrap(process.stdout.isTTY ? this.cli.terminalWidth() : 80)\n .argv;\n }\n}\n\n/** Excludes bare `local`: `wizard mcp add --local` stays available in prod. */\nconst LOCAL_TARGET_FLAGS = [\n 'local-dev',\n 'local-context-mill',\n 'local-mcp',\n 'local-posthog',\n] as const;\n\nconst LOCAL_TARGET_ENV_VARS = [\n 'POSTHOG_WIZARD_LOCAL_DEV',\n 'POSTHOG_WIZARD_LOCAL_CONTEXT_MILL',\n 'POSTHOG_WIZARD_LOCAL_MCP',\n 'POSTHOG_WIZARD_LOCAL_POSTHOG',\n] as const;\n","import type { Arguments } from 'yargs';\nimport { getUI, setUI } from '@ui';\nimport { LoggingUI } from '@ui/logging-ui';\nimport type { ProvisioningResult } from '@utils/provisioning';\nimport type { Command } from './command';\n\nexport const provisionCommand: Command = {\n name: 'provision',\n description: 'Create a new PostHog account (headless, no TUI)',\n options: {\n email: {\n describe: 'Email address for the new account',\n type: 'string',\n demandOption: true,\n },\n region: {\n describe: 'Cloud region (us or eu)',\n choices: ['us', 'eu'] as const,\n default: 'us',\n },\n name: {\n describe: 'Name for the new account',\n type: 'string',\n default: '',\n },\n json: {\n describe:\n 'Emit JSON result to stdout (defaults to true when stdout is not a TTY)',\n type: 'boolean',\n },\n },\n examples: [\n ['wizard provision --email matt+test@posthog.com --region us', ''],\n ['wizard provision --email user@example.com --region eu --json', ''],\n ],\n handler: runProvision,\n};\n\nfunction runProvision(argv: Arguments): void {\n const jsonMode =\n argv.json === undefined ? !process.stdout.isTTY : Boolean(argv.json);\n if (!jsonMode) setUI(new LoggingUI());\n\n void provision({\n email: argv.email as string,\n region: (argv.region as string).toUpperCase() as 'US' | 'EU',\n name: (argv.name as string) ?? '',\n baseUrl: argv.baseUrl as string | undefined,\n jsonMode,\n });\n}\n\ntype ProvisionArgs = {\n email: string;\n region: 'US' | 'EU';\n name: string;\n baseUrl?: string;\n jsonMode: boolean;\n};\n\nasync function provision({\n email,\n region,\n name,\n baseUrl,\n jsonMode,\n}: ProvisionArgs): Promise<void> {\n try {\n const { provisionNewAccount } = await import('@utils/provisioning');\n if (!jsonMode) {\n getUI().log.info(`Provisioning account for ${email} in ${region}...`);\n }\n const result = await provisionNewAccount(email, name, region, { baseUrl });\n emitResult(result, jsonMode);\n process.exit(0);\n } catch (error) {\n emitError(error, jsonMode);\n process.exit(1);\n }\n}\n\nfunction emitResult(result: ProvisioningResult, jsonMode: boolean): void {\n if (jsonMode) {\n process.stdout.write(`${JSON.stringify(result)}\\n`);\n return;\n }\n getUI().log.success('Account provisioned successfully:');\n getUI().log.info(` API Key: ${result.projectApiKey}`);\n getUI().log.info(` Host: ${result.host}`);\n getUI().log.info(` Project ID: ${result.projectId}`);\n getUI().log.info(` Account ID: ${result.accountId}`);\n getUI().log.info(` Access Token: ${result.accessToken}`);\n getUI().log.info(` Refresh Token: ${result.refreshToken}`);\n if (result.personalApiKey) {\n getUI().log.info(` Personal API Key: ${result.personalApiKey}`);\n }\n}\n\nfunction emitError(error: unknown, jsonMode: boolean): void {\n const msg = error instanceof Error ? error.message : String(error);\n const code = msg.includes('already associated')\n ? 'email_exists'\n : 'provisioning_failed';\n if (jsonMode) {\n process.stderr.write(`${JSON.stringify({ error: msg, code })}\\n`);\n return;\n }\n getUI().log.error(`Provisioning failed: ${msg}`);\n}\n","import { isNonInteractiveEnvironment } from '@utils/environment';\nimport { setEntryCommand } from '@utils/links';\nimport { headlessOption, isHeadless, regionOption } from '@lib/headless-mode';\nimport { provisionCommand } from '../provision';\nimport type { Command } from '../command';\n\nexport const basicIntegrationCommand: Command = {\n name: ['$0'],\n description: 'Run the PostHog setup wizard',\n // provision is a one-shot HTTP call tied to the base flow, not a wizard\n // program — it rides under the base command rather than as a peer.\n children: [provisionCommand],\n options: {\n 'install-dir': {\n describe:\n 'Directory to install PostHog in\\nenv: POSTHOG_WIZARD_INSTALL_DIR',\n type: 'string',\n },\n name: {\n describe:\n 'Name for account creation with --ci --signup\\nenv: POSTHOG_WIZARD_NAME',\n type: 'string',\n },\n // ── Internal modes ───────────────────────────────────────────────\n // Hidden from `--help`. See CONTRIBUTING.md for what each one does.\n playground: {\n default: false,\n describe: 'Launch the TUI primitives playground',\n type: 'boolean',\n hidden: true,\n },\n // The experimental headless flag — declared here (and on `audit`) rather\n // than globally. Routed by this command's handler via runHeadlessInstall.\n ...headlessOption,\n ...regionOption,\n },\n check: (argv) => {\n // --playground is the standalone TUI demo; it can't combine with a\n // non-interactive run (either --ci or the experimental headless flag).\n if (argv.playground && (argv.ci || isHeadless(argv))) {\n throw new Error('--playground cannot be combined with a headless run.');\n }\n return true;\n },\n handler: (argv) => {\n // The bare run is the integrate flow.\n setEntryCommand('integrate');\n // Each mode file is loaded only when its branch is taken, so a plain\n // `npx @posthog/wizard` never pulls in the CI or playground paths.\n void (async () => {\n // ── The CI / headless division ───────────────────────────────────\n // --ci (dev/test only) and the experimental headless flag (the\n // published-build, non-interactive path; see @lib/headless-mode) both\n // request a non-interactive install, but route to dedicated entry points\n // — runHeadlessInstall vs runCIInstall (and below them runWizardHeadless\n // vs runWizardCI). Both share one pipeline today but are separate\n // functions end-to-end, so headless can diverge later without touching\n // the CI path or its callers.\n if (isHeadless(argv)) {\n const { runHeadlessInstall } = await import('./ci-install');\n return runHeadlessInstall(argv);\n }\n if (argv.ci) {\n const { runCIInstall } = await import('./ci-install');\n return runCIInstall(argv);\n }\n if (isNonInteractiveEnvironment()) {\n const { failNonInteractive } = await import('./non-interactive');\n return failNonInteractive();\n }\n if (argv.playground) {\n const { runPlayground } = await import('./playground');\n return runPlayground();\n }\n const { runInteractive } = await import('./interactive');\n runInteractive(argv);\n })();\n },\n};\n","/**\n * Ink throws \"Raw mode is not supported\" when stdin has no TTY (piped input,\n * CI, some IDE terminals). That is the only TUI failure the mcp commands\n * degrade to LoggingUI for — any other error from the TUI path is a real bug\n * and must surface rather than be silently swallowed.\n */\nexport function isTUIUnavailable(error: unknown): boolean {\n return (\n error instanceof Error && /raw mode is not supported/i.test(error.message)\n );\n}\n","import type { Arguments } from 'yargs';\nimport { setUI } from '@ui';\nimport { LoggingUI } from '@ui/logging-ui';\nimport { headlessOption, isHeadless } from '@lib/headless-mode';\nimport { Program } from '@lib/programs/program-registry';\nimport { VERSION } from '@shared/version';\nimport type { Command } from '../command';\nimport { isTUIUnavailable } from './tui-availability';\n\nexport const mcpAddCommand: Command = {\n name: 'add',\n description: 'Install PostHog MCP server to supported clients',\n options: {\n local: {\n default: false,\n describe: 'Add local development MCP server (http://localhost:8787)',\n type: 'boolean',\n },\n features: {\n describe: 'Comma-separated list of features to enable (default: all)',\n type: 'string',\n },\n 'api-key': {\n describe: 'PostHog personal API key (phx_xxx) for MCP authentication',\n type: 'string',\n },\n // Reuses the run pipeline's headless flag rather than minting a public one:\n // this stays reversible, and today the only caller is our own CI.\n ...headlessOption,\n },\n handler: runMcpAdd,\n};\n\nfunction runMcpAdd(argv: Arguments): void {\n const features = parseFeatures(argv.features);\n void (async () => {\n const { readApiKeyFromEnv } = await import('@utils/env-api-key');\n const apiKey = (argv.apiKey as string | undefined) || readApiKeyFromEnv();\n const debug = argv.debug as boolean | undefined;\n const localMcp = argv.local as boolean | undefined;\n const args = { local: localMcp, features, apiKey };\n\n // Ink renders into a pipe happily and only throws on raw-mode input, so a\n // non-TTY run reaches the confirm prompt and stalls there rather than\n // hitting the isTUIUnavailable fallback below. The headless flag is the\n // only reliable way to install from a script.\n if (isHeadless(argv)) {\n await runHeadlessAdd(args);\n return;\n }\n\n try {\n const { startTUI } = await import('@ui/tui/start-tui');\n const { buildSession } = await import('@lib/wizard-session');\n const tui = startTUI(VERSION, Program.McpAdd);\n tui.store.session = buildSession({\n debug,\n localMcp,\n mcpFeatures: features,\n apiKey,\n baseUrl: argv.baseUrl as string | undefined,\n });\n } catch (error) {\n if (!isTUIUnavailable(error)) throw error;\n await runHeadlessAdd(args);\n }\n })();\n}\n\nasync function runHeadlessAdd(args: {\n local?: boolean;\n features?: string[];\n apiKey?: string;\n}): Promise<void> {\n setUI(new LoggingUI());\n const { addMCPServerToClientsStep } = await import(\n '@steps/add-mcp-server-to-clients/index'\n );\n // Never forwards `ci`: headless implies session.ci elsewhere, and the step\n // reads that as \"skip MCP entirely\" — the opposite of what we're here to do.\n const { installed, failed } = await addMCPServerToClientsStep(args);\n // A scripted caller has no screen to read, so this has to be an exit code.\n // Any failure counts, not just a total wipeout: the step installs to every\n // detected client, so one succeeding would otherwise mask the rest.\n if (failed.length > 0 || installed.length === 0) process.exitCode = 1;\n}\n\nfunction parseFeatures(raw: unknown): string[] | undefined {\n if (typeof raw !== 'string') return undefined;\n return raw\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean);\n}\n","import type { Arguments } from 'yargs';\nimport { setUI } from '@ui';\nimport { LoggingUI } from '@ui/logging-ui';\nimport { headlessOption, isHeadless } from '@lib/headless-mode';\nimport { Program } from '@lib/programs/program-registry';\nimport { VERSION } from '@shared/version';\nimport type { Command } from '../command';\nimport { isTUIUnavailable } from './tui-availability';\n\nexport const mcpRemoveCommand: Command = {\n name: 'remove',\n description: 'Remove PostHog MCP server from supported clients',\n options: {\n local: {\n default: false,\n describe: 'Remove local development MCP server (http://localhost:8787)',\n type: 'boolean',\n },\n // Mirrors `mcp add` — see the note there on reusing the run pipeline's flag.\n ...headlessOption,\n },\n handler: runMcpRemove,\n};\n\nfunction runMcpRemove(argv: Arguments): void {\n void (async () => {\n const debug = argv.debug as boolean | undefined;\n const localMcp = argv.local as boolean | undefined;\n\n // See the note in add.ts: a non-TTY run stalls on the confirm prompt\n // instead of falling back, so scripts need an explicit flag.\n if (isHeadless(argv)) {\n await runHeadlessRemove(localMcp);\n return;\n }\n\n try {\n const { startTUI } = await import('@ui/tui/start-tui');\n const { buildSession } = await import('@lib/wizard-session');\n const tui = startTUI(VERSION, Program.McpRemove);\n tui.store.session = buildSession({\n debug,\n localMcp,\n baseUrl: argv.baseUrl as string | undefined,\n });\n } catch (error) {\n // Same guard as `mcp add`: only a missing TTY falls back to LoggingUI,\n // so a genuine TUI bug surfaces instead of looking like a plain shell.\n if (!isTUIUnavailable(error)) throw error;\n await runHeadlessRemove(localMcp);\n }\n })();\n}\n\n/** No exit code on an empty result: nothing to remove is the requested end state. */\nasync function runHeadlessRemove(local?: boolean): Promise<void> {\n setUI(new LoggingUI());\n const { removeMCPServerFromClientsStep } = await import(\n '@steps/add-mcp-server-to-clients/index'\n );\n await removeMCPServerFromClientsStep({ local });\n}\n","import type { Arguments } from 'yargs';\nimport { getUI, setUI } from '@ui';\nimport { LoggingUI } from '@ui/logging-ui';\nimport { Program } from '@lib/programs/program-registry';\nimport { VERSION } from '@shared/version';\nimport { ErrorCodes } from '@shared/errors';\nimport { emitWizardError } from '@shared/errors';\nimport type { Command } from '../command';\n\nexport const mcpTutorialCommand: Command = {\n name: 'tutorial',\n description: 'Try the PostHog MCP with your agent (no install needed)',\n options: {\n local: {\n default: false,\n describe:\n 'Point the tutorial at the local MCP server (http://localhost:8787)',\n type: 'boolean',\n },\n },\n handler: runMcpTutorial,\n};\n\nfunction runMcpTutorial(argv: Arguments): void {\n void (async () => {\n const debug = argv.debug as boolean | undefined;\n const localMcp = argv.local as boolean | undefined;\n\n try {\n const { startTUI } = await import('@ui/tui/start-tui');\n const { buildSession } = await import('@lib/wizard-session');\n const tui = startTUI(VERSION, Program.McpTutorial);\n tui.store.session = buildSession({\n debug,\n localMcp,\n baseUrl: argv.baseUrl as string | undefined,\n });\n } catch (err) {\n // TUI unavailable — the tutorial has no headless fallback.\n setUI(new LoggingUI());\n getUI().log.error(\n `The MCP tutorial requires an interactive terminal. ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n emitWizardError({\n code: ErrorCodes.CliInteractiveRequired,\n message: 'The MCP tutorial requires an interactive terminal.',\n });\n process.exit(1);\n }\n })();\n}\n","import { mcpAddCommand } from './add';\nimport { mcpRemoveCommand } from './remove';\nimport { mcpTutorialCommand } from './tutorial';\nimport type { Command } from '../command';\n\nexport const mcpCommand: Command = {\n name: 'mcp',\n description: 'MCP server management commands',\n children: [mcpAddCommand, mcpRemoveCommand, mcpTutorialCommand],\n};\n","/**\n * `--no-telemetry` flips `telemetry: false` via yargs negation;\n * `POSTHOG_WIZARD_NO_TELEMETRY` is honoured separately so the env-var\n * form documented in the README keeps working.\n */\nexport function resolveNoTelemetry(options: Record<string, unknown>): boolean {\n if (options.telemetry === false) return true;\n const env = process.env.POSTHOG_WIZARD_NO_TELEMETRY;\n if (env == null || env === '') return false;\n const norm = env.toLowerCase();\n return norm !== '0' && norm !== 'false';\n}\n","import { randomUUID } from 'node:crypto';\nimport { basename, resolve } from 'node:path';\nimport { validate as isUUID } from 'uuid';\nimport { valid as validVersion } from 'semver';\nimport { VERSION } from '@shared/version';\nimport {\n RunPhase,\n type Credentials,\n type WizardSession,\n} from '@lib/wizard-session';\nimport { currentCredentials } from '@shared/oauth-session';\nimport { isGrantRevoked } from '@shared/auth-session-state';\nimport { logToFile } from '@utils/debug';\nimport { parseRetryAfter } from './destinations/posthog';\n\nexport type RunOutcome = 'completed' | 'failed' | 'cancelled';\ntype RunTask = {\n name: string;\n status: 'created' | 'running' | 'completed' | 'failed';\n};\n// The task fields a snapshot reads, local so task-stream stays off the TUI store.\ntype TaskItem = {\n id?: string;\n source?: string;\n sourceStatus?: string;\n label: string;\n status: string;\n};\ntype Options = {\n mode: 'local' | 'cloud';\n programId: string;\n assignedId?: string;\n getSession: () => WizardSession;\n fetchImpl?: typeof fetch;\n onError?: (message: string) => void;\n};\n\nconst STATUS: Record<string, RunTask['status']> = {\n pending: 'created',\n in_progress: 'running',\n completed: 'completed',\n failed: 'failed',\n skipped: 'completed',\n};\n\nexport class RunTaskNames {\n private names = new Map<string, string>();\n private used = new Set<string>();\n\n snapshot(items: readonly TaskItem[]): RunTask[] {\n if (items.length > 100) throw new Error('task limit exceeded (100)');\n const occurrences = new Map<string, number>();\n const ids = new Set<string>();\n return items.map((item) => {\n const subject = item.label.trim();\n if (!subject) throw new Error('blank task name');\n const rawStatus = item.sourceStatus ?? item.status;\n const status = STATUS[rawStatus];\n if (!Object.hasOwn(STATUS, rawStatus))\n throw new Error('invalid task status');\n const occurrence = (occurrences.get(subject) ?? 0) + 1;\n occurrences.set(subject, occurrence);\n const id = item.id\n ? JSON.stringify([item.source, item.id])\n : JSON.stringify([subject, occurrence]);\n if (ids.has(id)) throw new Error('duplicate task identity');\n ids.add(id);\n let name = this.names.get(id);\n if (!name) {\n name = subject.slice(0, 255);\n for (let n = 2; this.used.has(name); n++) {\n const suffix = ` (${n})`;\n name = subject.slice(0, 255 - suffix.length) + suffix;\n }\n this.names.set(id, name);\n this.used.add(name);\n }\n return { name, status };\n });\n }\n}\n\nexport function createWizardRunSync(\n options: Omit<Options, 'mode'> & {\n mode: 'local' | 'headless' | 'ci';\n noTelemetry: boolean;\n },\n): WizardRunSync | undefined {\n if (options.noTelemetry || options.mode === 'ci') return;\n if (options.mode === 'headless' && options.assignedId === undefined) return;\n return new WizardRunSync({\n ...options,\n mode: options.assignedId !== undefined ? 'cloud' : 'local',\n });\n}\n\nexport class WizardRunSync {\n private readonly names = new RunTaskNames();\n private readonly tasksAbort = new AbortController();\n private readonly reported = new Set<string>();\n private context?: {\n apiHost: string;\n projectId: number;\n programId: string;\n mode: Options['mode'];\n id?: string;\n };\n private queue: Promise<void> = Promise.resolve();\n private lastBody?: string;\n private stopped = false;\n private tasksDisabled = false;\n private authDisabled = false;\n private closing?: Promise<void>;\n\n constructor(private readonly options: Options) {}\n\n capture(items: readonly TaskItem[] | undefined): void {\n if (this.stopped || this.tasksDisabled || !items) return;\n if (\n this.options.mode === 'cloud' &&\n !isUUID(this.options.assignedId ?? '')\n ) {\n this.tasksDisabled = true;\n this.report('invalid cloud run assignment');\n return;\n }\n const session = this.options.getSession();\n if (session.runPhase === RunPhase.Idle) return;\n if (!this.context) {\n if (session.runPhase !== RunPhase.Running || !session.credentials) return;\n const { host, projectId } = session.credentials;\n this.context = {\n apiHost: host.appHost.replace(/\\/$/, ''),\n projectId,\n programId: this.options.programId,\n mode: this.options.mode,\n id: this.options.assignedId,\n };\n this.queue = this.initialize(session);\n }\n try {\n const body = JSON.stringify({ tasks: this.names.snapshot(items) });\n if (body === this.lastBody) return;\n this.lastBody = body;\n this.queue = this.queue.then(async () => {\n if (\n this.tasksDisabled ||\n this.tasksAbort.signal.aborted ||\n !this.context?.id\n )\n return;\n const ok = await this.request(\n 'PUT',\n `${this.context.id}/tasks/`,\n body,\n this.tasksAbort.signal,\n );\n if (!ok) this.tasksDisabled = true;\n });\n } catch {\n this.report(\n 'invalid task snapshot (names, statuses, identities or 100-task limit)',\n );\n }\n }\n\n shutdown(outcome: RunOutcome, timeoutMs: number): Promise<void> {\n if (this.closing) return this.closing;\n this.stopped = true;\n this.closing = this.finish(outcome, Math.max(0, timeoutMs));\n return this.closing;\n }\n\n private async initialize(session: WizardSession): Promise<void> {\n const context = this.context;\n if (!context || context.mode === 'cloud') return;\n const projectName = basename(resolve(session.installDir))\n .trim()\n .slice(0, 255);\n if (!projectName) {\n this.tasksDisabled = true;\n this.report('unsupported program or workspace configuration');\n return;\n }\n const body = JSON.stringify({\n program_id: context.programId,\n environment: 'local',\n workspace: { type: 'local_folder', project_name: projectName },\n ...(validVersion(VERSION) ? { wizard_version: VERSION } : {}),\n idempotency_key: randomUUID(),\n });\n // POST retries remain disabled until deployed local idempotency is verified.\n const result = await this.request('POST', '', body, this.tasksAbort.signal);\n if (\n result &&\n typeof result === 'object' &&\n 'id' in result &&\n typeof result.id === 'string' &&\n isUUID(result.id)\n ) {\n context.id = result.id;\n } else {\n this.tasksDisabled = true;\n this.report(\n 'local creation failed or returned an invalid ID; creation was not retried',\n );\n }\n }\n\n private credentials(\n creds = this.options.getSession().credentials,\n ): Credentials | undefined {\n const context = this.context;\n if (!context) return;\n if (\n !creds ||\n creds.host.appHost.replace(/\\/$/, '') !== context.apiHost ||\n creds.projectId !== context.projectId\n ) {\n this.report('execution credentials changed host or project');\n return;\n }\n if (\n creds.missingScopes?.includes('wizard_run:write') ||\n !creds.accessToken.startsWith('pha_')\n ) {\n this.authDisabled = true;\n this.report('wizard_run:write OAuth grant required; authorize again');\n return;\n }\n return creds;\n }\n\n private async request(\n method: 'POST' | 'PUT' | 'PATCH',\n suffix: string,\n body: string,\n signal: AbortSignal,\n ): Promise<unknown> {\n const context = this.context;\n if (!context || this.authDisabled || signal.aborted) return;\n let refreshed = false;\n let rateLimited = false;\n const attempts = method === 'POST' ? 1 : 3;\n for (let attempt = 0; attempt < attempts && !signal.aborted; attempt++) {\n let retryMs = 500 * 2 ** attempt;\n try {\n const creds = this.credentials();\n if (!creds) return;\n const response = await this.bounded(\n async (requestSignal) => {\n // The run's OAuth session owns refresh, so the agent reads the same rotated token.\n const current = this.credentials(await currentCredentials(creds));\n if (!current) throw new Error('credentials unavailable');\n const res = await (this.options.fetchImpl ?? fetch)(\n `${context.apiHost}/api/projects/${context.projectId}/wizard/runs/${suffix}`,\n {\n method,\n body,\n signal: requestSignal,\n headers: {\n Authorization: `Bearer ${current.accessToken}`,\n 'Content-Type': 'application/json',\n },\n },\n );\n const data: unknown =\n method === 'POST' && (res.status === 200 || res.status === 201)\n ? await res.json()\n : undefined;\n return { res, data, current };\n },\n signal,\n 5000,\n );\n const { res, data, current } = response;\n if (\n (method === 'POST' && [200, 201].includes(res.status)) ||\n (method === 'PUT' && res.status === 204) ||\n (method === 'PATCH' && res.status === 200)\n )\n return data ?? true;\n if (\n res.status === 401 &&\n current.refreshToken &&\n !isGrantRevoked() &&\n !refreshed &&\n method !== 'POST'\n ) {\n refreshed = true;\n const rotated = await this.bounded(\n () => currentCredentials(current, true),\n signal,\n 5000,\n );\n if (rotated.accessToken === current.accessToken) {\n this.authDisabled = true;\n this.report(\n 'OAuth refresh could not recover the grant; authorize again',\n );\n return;\n }\n continue;\n }\n if (res.status === 401 || res.status === 403) this.authDisabled = true;\n if (res.status === 429 && !rateLimited) {\n rateLimited = true;\n retryMs = parseRetryAfter(res.headers.get('Retry-After'));\n } else if (res.status < 500 || res.status >= 600) {\n this.report(\n `${method} rejected (${res.status}); check assignment, grant and program configuration`,\n );\n return;\n }\n } catch {\n if (signal.aborted) return;\n }\n if (attempt + 1 < attempts) {\n try {\n await this.sleep(retryMs, signal);\n } catch {\n return;\n }\n }\n }\n this.report(`${method} delivery exhausted`);\n }\n\n private async finish(outcome: RunOutcome, timeoutMs: number): Promise<void> {\n const deadline = Date.now() + timeoutMs;\n try {\n await this.bounded(\n () => this.queue,\n new AbortController().signal,\n Math.floor(timeoutMs * 0.75),\n );\n } catch {\n this.report('task drain timed out');\n }\n this.tasksAbort.abort();\n if (this.context?.mode !== 'local' || !this.context.id || this.authDisabled)\n return;\n if (Date.now() >= deadline) {\n this.report('terminal update budget exhausted');\n return;\n }\n const finalAbort = new AbortController();\n const timer = setTimeout(\n () => finalAbort.abort(),\n Math.max(0, deadline - Date.now()),\n );\n try {\n await this.request(\n 'PATCH',\n `${this.context.id}/`,\n JSON.stringify({ status: outcome }),\n finalAbort.signal,\n );\n } finally {\n clearTimeout(timer);\n finalAbort.abort();\n }\n }\n\n private async bounded<T>(\n operation: (signal: AbortSignal) => Promise<T>,\n parent: AbortSignal,\n ms: number,\n ): Promise<T> {\n const controller = new AbortController();\n const abort = () => controller.abort();\n parent.addEventListener('abort', abort, { once: true });\n if (parent.aborted) controller.abort();\n const timer = setTimeout(abort, ms);\n let onAbort: () => void = () => undefined;\n const cancelled = new Promise<never>((_, reject) => {\n onAbort = () => reject(new Error('request cancelled'));\n controller.signal.addEventListener('abort', onAbort, { once: true });\n if (controller.signal.aborted) onAbort();\n });\n try {\n return await Promise.race([operation(controller.signal), cancelled]);\n } finally {\n clearTimeout(timer);\n parent.removeEventListener('abort', abort);\n controller.signal.removeEventListener('abort', onAbort);\n controller.abort();\n }\n }\n\n private sleep(ms: number, signal: AbortSignal): Promise<void> {\n return new Promise((resolve) => {\n const finish = () => {\n clearTimeout(timer);\n signal.removeEventListener('abort', finish);\n resolve();\n };\n const timer = setTimeout(finish, ms);\n signal.addEventListener('abort', finish, { once: true });\n if (signal.aborted) finish();\n });\n }\n\n private report(message: string): void {\n if (this.reported.has(message)) return;\n this.reported.add(message);\n (this.options.onError ?? ((m) => logToFile(`[wizard-run-sync] ${m}`)))(\n message,\n );\n }\n}\n","import { VERSION } from '@shared/version';\nimport { logToFile, getLogFilePath } from '@utils/debug';\nimport { runProgramAgent } from '@lib/programs/run-agent-legacy';\nimport { authenticate } from '@lib/programs/authenticate';\nimport { getProgramConfig } from '@lib/programs/program-registry';\nimport { getAuditChecks } from '@lib/programs/audit/types';\nimport { maybeStampAiSdkDetected } from '@lib/programs/posthog-integration/detect';\nimport type { ProgramConfig } from '@lib/programs/program-step';\nimport type { Harness, Sequence } from '@shared/constants';\nimport type { startTUI as StartTUIFn } from '@ui/tui/start-tui';\nimport type { WizardStore } from '@ui/tui/store';\nimport { OutroKind, type WizardSession } from '@lib/wizard-session';\nimport type { TaskStreamPush as TaskStreamPushClass } from '@lib/task-stream/task-stream-push';\nimport { resolveNoTelemetry } from './resolve-no-telemetry';\nimport { checkLocalServices, getLocalDev } from '@shared/local-dev';\nimport { createWizardRunSync } from '@lib/task-stream/wizard-run-sync';\nimport { runtimeEnv } from '@env';\nimport { runCleanups, registerShutdown } from '@utils/wizard-abort';\nimport { classifyRunFailure, emitWizardError } from '@shared/errors';\nimport { isRunFailure } from '@ui/mint-failure';\nimport { getUI } from '@ui';\nimport { analytics } from '@utils/analytics';\nimport { join } from 'node:path';\n\nconst WIZARD_VERSION = VERSION;\n\ntype Step = ProgramConfig['steps'][number];\n\n/** The session a run step's agent runs in: scoped to the step's target dir\n * (e.g. a monorepo sub-app) with its own framework context, after any prep.\n * A step without `targetDir` runs in the live session, unchanged.\n * The frameworkContext copy is shallow and unfiltered — name keys per owning program. */\nasync function prepareRunSession(\n step: Step,\n live: WizardSession,\n): Promise<WizardSession> {\n const session = step.targetDir\n ? {\n ...live,\n installDir: step.targetDir(live),\n frameworkContext: { ...live.frameworkContext },\n }\n : live;\n if (step.onRunPrep) await step.onRunPrep(session);\n return session;\n}\n\n/** Advance one step of a composed run to completion: the auth screen\n * authenticates (every later run reuses it); a step carrying its own `run`\n * thunk runs that agent in its dir and is recorded in `completedRuns`; the\n * host program's own run screen runs `config.run`; any other screen waits for\n * the user to satisfy `isComplete`. */\nasync function advanceStep(\n step: Step,\n store: WizardStore,\n config: ProgramConfig,\n): Promise<void> {\n if (step.screenId === 'auth') {\n await authenticate(store.session, config.id);\n maybeStampAiSdkDetected(store.session);\n } else if (step.run) {\n await step.run(await prepareRunSession(step, store.session));\n store.completeRunStep(step.id);\n } else if (step.screenId === 'run') {\n await runProgramAgent(config, await prepareRunSession(step, store.session));\n } else if (step.isComplete) {\n await store.waitUntil(step.isComplete);\n }\n}\n\n/**\n * Run a full wizard program in the TUI. Handles the full lifecycle: start TUI,\n * build session, run detection, wait for intro gate, execute the\n * agent pipeline, wait for outro dismissal, then exit.\n */\nexport function runWizard(\n config: ProgramConfig,\n options: Record<string, unknown>,\n): void {\n let tui: ReturnType<typeof StartTUIFn> | null = null;\n let taskStream: TaskStreamPushClass | null = null;\n let onSignal: (() => void) | null = null;\n let exitInProgress = false;\n let signalled = false;\n let unregisterShutdown: (() => void) | undefined;\n\n void (async () => {\n try {\n const installDir = (options.installDir as string) || process.cwd();\n\n const { startTUI } = await import('@ui/tui/start-tui');\n const { buildSession, RunPhase } = await import('@lib/wizard-session');\n const { TaskStreamPush } = await import('@lib/task-stream/index');\n const { PostHogDestination } = await import(\n '@lib/task-stream/destinations/posthog'\n );\n const { createFileDestination } = await import(\n '@lib/task-stream/destinations/file'\n );\n\n // Before the TUI mounts: once Ink owns the alt screen, anything written\n // to it is wiped on unmount (see the catch block below), so an abort here\n // would leave the user on a loading screen with no message.\n const local = getLocalDev();\n const localServicesError = await checkLocalServices({\n ...local,\n // An explicit --base-url wins over --local-posthog (see buildSession),\n // so don't probe :8010 when one was given.\n localPosthog: local.localPosthog && !options.baseUrl,\n });\n if (localServicesError) {\n const { wizardAbort } = await import('@utils/wizard-abort');\n await wizardAbort({ message: localServicesError });\n return;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n tui = startTUI(WIZARD_VERSION, config.id as any, () => onSignal?.());\n const activeTui = tui;\n\n const session = buildSession({\n debug: options.debug as boolean | undefined,\n localDev: options.localDev as boolean | undefined,\n localMcp: options.localMcp as boolean | undefined,\n localPosthog: options.localPosthog as boolean | undefined,\n installDir,\n ci: false,\n signup: options.signup as boolean | undefined,\n apiKey: options.apiKey as string | undefined,\n projectId: options.projectId as string | undefined,\n email: options.email as string | undefined,\n baseUrl: options.baseUrl as string | undefined,\n benchmark: options.benchmark as boolean | undefined,\n yaraReport: options.yaraReport as boolean | undefined,\n noTelemetry: resolveNoTelemetry(options),\n harness: options.harness as Harness | undefined,\n sequence: options.sequence as Sequence | undefined,\n model: options.model as string | undefined,\n integrate: options.integrate as boolean | undefined,\n captureAio: options.captureAio as boolean | undefined,\n });\n session.programLabel = config.id;\n if (options.skillId) {\n session.skillId = options.skillId as string;\n } else if (config.skillId) {\n session.skillId = config.skillId;\n }\n\n activeTui.store.session = session;\n\n // Flush a terminal-phase push on Ctrl-C so the web app sees the\n // run ended in error rather than hanging on the last \"running\"\n // snapshot. Registered before the stream exists: Ctrl-C on the intro\n // must still restore the terminal and run the cleanups, and there is\n // no run to report yet.\n onSignal = (): void => {\n if (signalled || exitInProgress) return;\n signalled = true;\n logToFile('[run-wizard] signal received, flushing task stream');\n // Run cleanups synchronously first — settings restore is sync fs work\n // and must complete even if the stream shutdown below times out.\n runCleanups();\n if (activeTui.store.session.runPhase === RunPhase.Running) {\n activeTui.store.setRunPhase(RunPhase.Error);\n }\n const teardown = (): void => {\n unregisterShutdown?.();\n if (onSignal) {\n process.off('SIGINT', onSignal);\n process.off('SIGTERM', onSignal);\n }\n try {\n activeTui.unmount();\n } catch {\n // terminal may already be torn down\n }\n process.exit(130);\n };\n void Promise.all([\n taskStream?.shutdown(2000, 'cancelled'),\n analytics.shutdown('cancelled'),\n ])\n .catch(() => logToFile('[run-wizard] cancellation shutdown failed'))\n .finally(teardown);\n };\n process.on('SIGINT', onSignal);\n process.on('SIGTERM', onSignal);\n\n for (;;) {\n await activeTui.store.runReadyHooks();\n // Settle the pre-run screens; `integration-check` is a no-op gate here.\n await activeTui.store.getGate('intro');\n\n const active = activeTui.store.router.activeProgram;\n if (active === config.id) break;\n config = getProgramConfig(active);\n }\n\n // After the switch loop, not before: the stream bakes its program id,\n // session id, and event-plan path in at construction, so a stream built\n // for the launch program would report the whole run under a program the\n // user left on the intro screen. Nothing before this point produces a\n // task to push.\n // Consent gates the push, not the dump: `--no-telemetry` still logs.\n const fileDestination = createFileDestination(options.taskStreamLog);\n const destinations = [\n ...(session.noTelemetry\n ? []\n : [\n new PostHogDestination({\n getCredentials: () => activeTui.store.session.credentials,\n onError: (err) => logToFile('[task-stream-push]', err.message),\n }),\n ]),\n ...(fileDestination ? [fileDestination] : []),\n ];\n const taskStreamEnabled = destinations.length > 0;\n const activeStream = new TaskStreamPush({\n store: activeTui.store,\n getFlags: () => analytics.getCachedWizardFlags(),\n programId: config.streamWorkflowId ?? config.id,\n runSync: createWizardRunSync({\n mode: 'local',\n programId: config.id,\n assignedId:\n (options.runId as string | undefined) ??\n runtimeEnv('POSTHOG_WIZARD_RUN_ID'),\n noTelemetry: session.noTelemetry,\n getSession: () => activeTui.store.session,\n }),\n destinations,\n eventPlanPath: config.eventPlanFile\n ? join(session.installDir, config.eventPlanFile)\n : undefined,\n auditChecks: config.auditLedgerFile\n ? () => getAuditChecks(activeTui.store.session)\n : undefined,\n enabled: taskStreamEnabled,\n });\n taskStream = activeStream;\n activeStream.attach();\n unregisterShutdown = registerShutdown((outcome) => {\n if (activeTui.store.session.runPhase === RunPhase.Running) {\n activeTui.store.setRunPhase(RunPhase.Error);\n }\n return activeStream.shutdown(2000, outcome);\n });\n\n await activeTui.store.getGate('integration-check');\n await activeTui.store.getGate('health-check');\n\n const skipAgent = config.run == null;\n const shown = (s: ProgramConfig['steps'][number]) =>\n !s.show || s.show(activeTui.store.session);\n\n if (config.steps.some((s) => s.run || s.targetDir)) {\n // A composed program: its step list splices in run steps that carry\n // their own agent (self-driving runs the integration before its own\n // run), or scopes its own run to a picked project (error-tracking).\n // Walk the list once, advancing each step to completion.\n for (const step of config.steps) {\n if (step.screenId === 'outro') break; // run-completion wait owns it\n if (shown(step)) await advanceStep(step, activeTui.store, config);\n }\n } else if (skipAgent) {\n const { getOrAskForProjectData } = await import('@utils/setup-utils');\n const { projectApiKey, host, accessToken, projectId } =\n await getOrAskForProjectData({\n signup: session.signup,\n ci: session.ci,\n apiKey: session.apiKey,\n projectId: session.projectId,\n baseUrl: session.baseUrl,\n programId: config.id,\n });\n activeTui.store.setCredentials({\n accessToken,\n projectApiKey,\n host,\n projectId,\n });\n } else {\n try {\n await runProgramAgent(config, activeTui.store.session);\n } catch (error) {\n // The run threw before its own error handling rendered an outro.\n // Show the handoff screen and let the user's agent take over.\n const failure = classifyRunFailure(error);\n logToFile('[run-wizard] run failed, handing off:', error);\n runCleanups();\n analytics.captureException(\n error instanceof Error ? error : new Error(String(error)),\n { error_code: failure.code },\n );\n getUI().outroError({\n kind: OutroKind.Error,\n errorCode: failure.code,\n message: failure.message,\n });\n }\n }\n\n if (signalled) return;\n const runFailed = isRunFailure(activeTui.store.session);\n await activeStream.finishRun(runFailed ? 'failed' : 'completed');\n await activeTui.store.waitUntil((s) => {\n if (s.mintHandoff === 'exit') return true;\n if (skipAgent && !runFailed) return s.outroDismissed;\n return s.skillsComplete;\n });\n\n exitInProgress = true;\n await activeStream.shutdown(2000);\n unregisterShutdown?.();\n process.off('SIGINT', onSignal);\n process.off('SIGTERM', onSignal);\n if (runFailed) await analytics.shutdown('error');\n activeTui.unmount();\n process.exit(runFailed ? 1 : 0);\n } catch (err) {\n if (signalled) return;\n // File-log first — the cleanup below can throw or exit.\n logToFile('[run-wizard] FATAL:', err);\n // Run cleanups before anything async so settings are restored even if\n // the stream shutdown hangs.\n runCleanups();\n // The task-stream debounce timer keeps the event loop alive, so\n // we have to drain it before exiting on the error path.\n exitInProgress = true;\n if (onSignal) {\n process.off('SIGINT', onSignal);\n process.off('SIGTERM', onSignal);\n }\n if (taskStream) {\n try {\n await taskStream.shutdown(2000, 'failed');\n } catch {\n // ignore\n }\n }\n unregisterShutdown?.();\n if (tui) {\n try {\n tui.unmount();\n } catch {\n // ignore\n }\n }\n // Print after unmount: anything printed into the alt screen is wiped.\n // A coded failure is a decision with its own message; anything else is\n // unexpected and goes out whole.\n const failure = classifyRunFailure(err);\n if (failure.coded) {\n // eslint-disable-next-line no-console\n console.error(failure.message);\n } else {\n // eslint-disable-next-line no-console\n console.error('Wizard run failed:', err);\n }\n // eslint-disable-next-line no-console\n console.error(`Full logs: ${getLogFilePath()}`);\n emitWizardError({ code: failure.code, message: failure.message });\n process.exit(1);\n }\n })();\n}\n","import { ErrorCodes, type ErrorCode } from '@shared/errors';\nimport type { RevenueDetectError } from '@lib/programs/revenue-analytics/detect';\nimport type { SelfDrivingDetectError } from '@lib/programs/self-driving/detect';\nimport type { SourceMapsDetectError } from '@lib/programs/error-tracking-upload-source-maps/detect';\nimport type { WarehouseDetectError } from '@lib/programs/warehouse-source/detect';\nimport type { WebAnalyticsDetectError } from '@lib/programs/web-analytics-doctor/detect';\n\n/**\n * Every `kind` a program detect step can write into\n * `frameworkContext.detectError`, assembled from the programs' own unions.\n * Type-only imports, so this adds no runtime edge from the catalog to the\n * programs (same shape as `skill-map.ts` keying on `InstallSkillResult`).\n *\n * The point is the compile error: add a kind to any program's `DetectError`\n * and `DETECT_CODES` stops type-checking until it gets a code.\n */\nexport type DetectErrorKind =\n | RevenueDetectError['kind']\n | SelfDrivingDetectError['kind']\n | SourceMapsDetectError['kind']\n | WarehouseDetectError['kind']\n | WebAnalyticsDetectError['kind'];\n\nconst DETECT_CODES: Record<DetectErrorKind, ErrorCode> = {\n 'bad-directory': ErrorCodes.DetectBadDirectory,\n 'unsupported-platform': ErrorCodes.DetectUnsupportedPlatform,\n 'no-project-files': ErrorCodes.DetectNoProjectFiles,\n 'no-sources': ErrorCodes.DetectNoSources,\n 'no-package-json': ErrorCodes.DetectNoPackageJson,\n 'no-sdks': ErrorCodes.DetectNoSdks,\n 'missing-stripe': ErrorCodes.DetectMissingStripe,\n // Three kinds, one failure class: the program needs a PostHog SDK and the\n // project has none. Hosts that care which program asked read `detail.kind`.\n 'no-posthog-sdk': ErrorCodes.DetectNoPosthogSdk,\n 'no-posthog': ErrorCodes.DetectNoPosthogSdk,\n 'missing-posthog': ErrorCodes.DetectNoPosthogSdk,\n};\n\n/**\n * `kind` arrives as a bare string — `frameworkContext.detectError` is untyped\n * storage — so the lookup can still miss. It falls back to a detect-group code\n * with `retry: 'no'`, never to `InternalUnhandled`: an unrecognized precondition\n * failure is still a precondition failure, and telling a sandbox to retry one\n * costs it the whole budget.\n */\nexport function detectErrorCode(kind: string): ErrorCode {\n return DETECT_CODES[kind as DetectErrorKind] ?? ErrorCodes.DetectUnclassified;\n}\n","import {\n POSTHOG_DOCS_URL,\n type Harness,\n type Sequence,\n} from '@shared/constants';\nimport {\n createWizardRunSync,\n type RunOutcome,\n} from '@lib/task-stream/wizard-run-sync';\nimport { runtimeEnv } from '@env';\nimport { registerShutdown, runCleanups } from '@utils/wizard-abort';\nimport {\n checkLocalServices,\n getLocalDev,\n POSTHOG_LOCAL_URL,\n} from '@shared/local-dev';\nimport type { CloudRegion } from '@utils/types';\nimport { getUI, setUI } from '@ui';\nimport { LoggingUI } from '@ui/logging-ui';\nimport type { ProgramConfig } from '@lib/programs/program-step';\nimport { getAuditChecks } from '@lib/programs/audit/types';\nimport { analytics } from '@utils/analytics';\nimport { resolveNoTelemetry } from './resolve-no-telemetry';\nimport type { WizardStore } from '@ui/tui/store';\nimport type { TaskStreamPush } from '@lib/task-stream/task-stream-push';\nimport { join } from 'node:path';\nimport {\n ErrorCodes,\n classifyRunFailure,\n emitWizardError,\n} from '@shared/errors';\nimport { detectErrorCode } from '@lib/programs/detect-map';\nimport type { OutroData, RunPhase as RunPhaseT } from '@lib/wizard-session';\n\n/**\n * The two non-interactive run modes. Both drive the same pipeline today; the\n * mode is threaded explicitly (rather than sniffed from a flag) so the dispatch\n * picks an entry point — runWizardCI vs runWizardHeadless — and this core stays\n * mode-agnostic except at the few documented forks. The string values double as\n * the analytics `build` tag, so they segment runs in analytics and on\n * LLM-gateway traces (which read analytics.build).\n */\nexport type NonInteractiveMode = 'ci' | 'headless';\n\n/** User-facing label for a non-interactive mode. */\nfunction modeLabel(mode: NonInteractiveMode): string {\n return mode === 'headless' ? 'Headless' : 'CI';\n}\n\n/** The credentials every non-interactive mode accepts, for error messages. */\nexport const API_KEY_HINT =\n 'personal API key phx_xxx or wizard-app OAuth access token pha_xxx';\n\n/**\n * The single non-interactive validation layer: requires api-key and\n * install-dir. Every non-interactive entry point routes through\n * `runNonInteractive`, so this is the one place these checks live. UI must be\n * initialized before calling.\n */\nexport function validateNonInteractiveOptions(\n options: Record<string, unknown>,\n mode: NonInteractiveMode,\n): void {\n const label = modeLabel(mode);\n if (!options.apiKey) {\n getUI().intro('PostHog Wizard');\n getUI().log.error(`${label} mode requires --api-key (${API_KEY_HINT})`);\n emitWizardError({\n code: ErrorCodes.ArgsMissingApiKey,\n message: `${label} mode requires --api-key (${API_KEY_HINT})`,\n });\n process.exit(1);\n }\n if (!options.installDir) {\n getUI().intro('PostHog Wizard');\n getUI().log.error(\n `${label} mode requires --install-dir (directory to install in)`,\n );\n emitWizardError({\n code: ErrorCodes.ArgsMissingInstallDir,\n message: `${label} mode requires --install-dir`,\n });\n process.exit(1);\n }\n}\n\n/**\n * Non-interactive pipeline shared by CI (`runWizardCI`) and headless\n * (`runWizardHeadless`) runs.\n *\n * Validates flags, builds a `ci:true` session, runs `config.ciPreRun` (or the\n * program's `onReady` hooks by default), executes `runProgramAgent`, and routes any\n * failure through `wizardAbort`. `wizardAbort` owns all exits — never add a\n * raw `process.exit` here.\n *\n * `mode` is the only difference between the two callers today (it sets the\n * analytics build tag and the user-facing label). Keeping it a parameter is\n * what lets CI and headless share this body now and diverge later — branch on\n * `mode` here, or stop sharing this function entirely.\n */\nexport function runNonInteractive(\n config: ProgramConfig,\n options: Record<string, unknown>,\n mode: NonInteractiveMode,\n): void {\n setUI(new LoggingUI());\n validateNonInteractiveOptions(options, mode);\n // Upgrade the build tag so runs segment cleanly in analytics (and on\n // LLM-gateway traces, which read analytics.build). A published headless run\n // (cloud / CI/CD) tags 'headless'; a dev/test `--ci` run upgrades 'dev' to\n // 'ci'. The mode string is the tag value.\n analytics.setTag('build', mode);\n\n void (async () => {\n const path = await import('path');\n const { buildSession, RunPhase, OutroKind } = await import(\n '@lib/wizard-session'\n );\n const { readEnvironment } = await import('@utils/environment');\n const { readApiKeyFromEnv } = await import('@utils/env-api-key');\n const { configureLogFileFromEnvironment, logToFile } = await import(\n '@utils/debug'\n );\n const { wizardAbort, WizardError } = await import('@utils/wizard-abort');\n\n configureLogFileFromEnvironment();\n\n const env = readEnvironment();\n const apiKey =\n (options.apiKey as string) ?? readApiKeyFromEnv() ?? undefined;\n const installDir = path.isAbsolute(options.installDir as string)\n ? (options.installDir as string)\n : path.join(process.cwd(), options.installDir as string);\n\n const session = buildSession({\n debug: options.debug as boolean | undefined,\n installDir,\n ci: true,\n signup: options.signup as boolean | undefined,\n localDev: options.localDev as boolean | undefined,\n localMcp: options.localMcp as boolean | undefined,\n localPosthog: options.localPosthog as boolean | undefined,\n apiKey,\n email: options.email as string | undefined,\n projectId: options.projectId as string | undefined,\n baseUrl: options.baseUrl as string | undefined,\n benchmark: options.benchmark as boolean | undefined,\n yaraReport: options.yaraReport as boolean | undefined,\n noTelemetry: resolveNoTelemetry(options),\n harness: options.harness as Harness | undefined,\n sequence: options.sequence as Sequence | undefined,\n model: options.model as string | undefined,\n captureAio: options.captureAio as boolean | undefined,\n ...env,\n // After the spread: yargs already resolves flag-over-env for --region,\n // so the parsed value must win over the raw env bag.\n region: (options.region ?? env.region) as CloudRegion | undefined,\n });\n session.programLabel = config.id;\n if (config.skillId) {\n session.skillId = config.skillId;\n }\n const runDef = typeof config.run === 'object' ? config.run : null;\n\n getUI().intro('Welcome to the PostHog setup wizard');\n getUI().log.info(`Running ${config.id} in ${modeLabel(mode)} mode`);\n\n // Before auth: a dead local PostHog otherwise surfaces as \"Failed to fetch\n // user data\". Aborts even non-interactively — a CI run pointed at a local\n // server that isn't there is testing nothing.\n const localServicesError = await checkLocalServices({\n ...getLocalDev(),\n localMcp: session.localMcp,\n localPosthog: session.baseUrl === POSTHOG_LOCAL_URL,\n });\n if (localServicesError) {\n await wizardAbort({\n code: ErrorCodes.EnvLocalServicesDown,\n message: localServicesError,\n });\n return;\n }\n\n // Headless streams run state to the PostHog backend so the web app can show\n // live progress. Reuses the interactive TaskStreamPush + WizardStore (no Ink\n // render): HeadlessUI keeps LoggingUI's output and feeds task updates into\n // the store; this runner drives the phase transitions. Headless pushes to\n // PostHog (the web app is that run's only UI); `--ci` is synthetic, so it\n // dumps locally and pushes nothing. Telemetry consent gates the push only.\n let store: WizardStore | null = null;\n let taskStream: TaskStreamPush | null = null;\n {\n const { WizardStore } = await import('@ui/tui/store');\n const { HeadlessUI } = await import('@ui/headless-ui');\n const { TaskStreamPush, PostHogDestination, createFileDestination } =\n await import('@lib/task-stream/index');\n\n // `''` resolves to the default path, so `--ci` always dumps.\n const logTarget =\n mode === 'ci' ? options.taskStreamLog ?? '' : options.taskStreamLog;\n const fileDestination = createFileDestination(logTarget);\n const posthogDestination =\n mode === 'headless' && !session.noTelemetry\n ? new PostHogDestination({\n getCredentials: () =>\n store?.session.credentials ?? session.credentials,\n onError: (e) => logToFile('[headless task-stream]', e.message),\n })\n : null;\n const destinations = [\n ...(posthogDestination ? [posthogDestination] : []),\n ...(fileDestination ? [fileDestination] : []),\n ];\n\n const headlessStore = new WizardStore(config.id);\n store = headlessStore;\n headlessStore.session = session;\n setUI(new HeadlessUI(headlessStore));\n taskStream = new TaskStreamPush({\n store: headlessStore,\n getFlags: () => analytics.getCachedWizardFlags(),\n programId: config.streamWorkflowId ?? config.id,\n runSync: createWizardRunSync({\n mode,\n programId: config.id,\n assignedId:\n (options.runId as string | undefined) ??\n runtimeEnv('POSTHOG_WIZARD_RUN_ID'),\n noTelemetry: session.noTelemetry,\n getSession: () => headlessStore.session,\n }),\n destinations,\n eventPlanPath: config.eventPlanFile\n ? join(session.installDir, config.eventPlanFile)\n : undefined,\n auditChecks: config.auditLedgerFile\n ? () => getAuditChecks(headlessStore.session)\n : undefined,\n enabled: destinations.length > 0,\n });\n taskStream.attach();\n\n if (fileDestination) {\n logToFile(`[task-stream] ${mode} dump: ${fileDestination.path}`);\n }\n }\n\n // wizardAbort exits via process.exit, so flush the terminal phase before any\n // exit. No-op for CI.\n const settleStream = async (\n phase: RunPhaseT,\n outroData?: OutroData,\n outcome: RunOutcome = phase === RunPhase.Completed\n ? 'completed'\n : 'failed',\n ): Promise<void> => {\n if (!store || !taskStream) return;\n if (outroData) store.setOutroData(outroData);\n store.setRunPhase(phase);\n await taskStream.shutdown(2000, outcome);\n process.off('SIGINT', onSignal);\n process.off('SIGTERM', onSignal);\n unregisterShutdown();\n };\n\n const unregisterShutdown = registerShutdown((outcome) =>\n settleStream(RunPhase.Error, undefined, outcome),\n );\n let signalled = false;\n const onSignal = (): void => {\n if (signalled) return;\n signalled = true;\n runCleanups();\n void settleStream(RunPhase.Error, undefined, 'cancelled').then(() =>\n wizardAbort({ exitCode: 130 }),\n );\n };\n process.on('SIGINT', onSignal);\n process.on('SIGTERM', onSignal);\n\n try {\n if (mode === 'ci') {\n const { configureGatewayFromCIEnvironment } = await import('@agent');\n configureGatewayFromCIEnvironment(\n Number(session.projectId),\n session.region ?? 'us',\n );\n }\n if (config.ciPreRun) {\n await config.ciPreRun(session);\n } else {\n const readyCtx = {\n session,\n setFrameworkContext: (key: string, value: unknown) => {\n session.frameworkContext[key] = value;\n },\n setFrameworkConfig: () => undefined,\n setDetectedFramework: () => undefined,\n // Non-interactive session is a plain object (no nanostore\n // copy-on-write), so direct assignment is safe here.\n setSkillId: (skillId: string | null) => {\n session.skillId = skillId;\n },\n setUnsupportedVersion: (info: {\n current: string;\n minimum: string;\n docsUrl: string;\n }) => {\n session.unsupportedVersion = info;\n },\n addDiscoveredFeature: () => undefined,\n setDetectionComplete: () => undefined,\n setPosthogSdkDetected: (detected: boolean) => {\n session.posthogSdkDetected = detected;\n },\n };\n for (const step of config.steps) {\n if (step.onReady) {\n await step.onReady(readyCtx);\n }\n }\n\n const detectError = session.frameworkContext.detectError as\n | { kind: string; [k: string]: unknown }\n | undefined;\n if (session.unsupportedVersion) {\n const { current, minimum, docsUrl } = session.unsupportedVersion;\n const message = `Detected framework version ${current} is not supported. Minimum supported version is ${minimum}.`;\n await settleStream(RunPhase.Error, {\n kind: OutroKind.Error,\n message,\n errorCode: ErrorCodes.DetectUnsupportedVersion,\n });\n await wizardAbort({\n code: ErrorCodes.DetectUnsupportedVersion,\n message: `${message}\\n\\nSee ${docsUrl}`,\n error: new WizardError(\n `${config.id} unsupported framework version`,\n {\n integration: config.id,\n current,\n minimum,\n },\n ErrorCodes.DetectUnsupportedVersion,\n ),\n });\n }\n if (detectError) {\n const code = detectErrorCode(detectError.kind);\n const detectKind = detectError.kind;\n // `kind` stays in the detail: several kinds share one code, so it is\n // the only thing telling a host which precondition actually failed.\n const detail = { ...detectError };\n await settleStream(RunPhase.Error, {\n kind: OutroKind.Error,\n message: `Prerequisites not met: ${detectKind}`,\n errorCode: code,\n errorDetail: detail,\n });\n await wizardAbort({\n code,\n detail,\n message: `Prerequisites not met: ${detectKind}\\n\\nSee ${\n runDef?.docsUrl ?? POSTHOG_DOCS_URL\n }`,\n error: new WizardError(\n `${config.id} prerequisites failed`,\n {\n integration: config.id,\n detect_error_kind: detectKind,\n },\n code,\n ),\n });\n }\n }\n\n const { runProgramAgent } = await import(\n '@lib/programs/run-agent-legacy'\n );\n await runProgramAgent(config, session);\n if (signalled) return;\n await settleStream(RunPhase.Completed);\n } catch (error) {\n if (signalled) return;\n const errorMessage =\n error instanceof Error ? error.message : String(error);\n const errorStack =\n error instanceof Error && error.stack ? error.stack : undefined;\n\n logToFile(`[${mode}] ERROR: ${errorMessage}`);\n if (errorStack) logToFile(`[${mode}] STACK: ${errorStack}`);\n\n const debugInfo = session.debug && errorStack ? `\\n\\n${errorStack}` : '';\n const docsUrl =\n session.frameworkConfig?.metadata.docsUrl ??\n runDef?.docsUrl ??\n POSTHOG_DOCS_URL;\n // A coded failure is a decision with its own message; anything else is\n // unexpected and gets the generic framing.\n const failure = classifyRunFailure(error);\n await settleStream(RunPhase.Error, {\n kind: OutroKind.Error,\n message: errorMessage,\n errorCode: failure.code,\n });\n await wizardAbort({\n code: failure.code,\n message: failure.coded\n ? `${errorMessage}${debugInfo}`\n : `Something went wrong: ${errorMessage}\\n\\nYou can read the documentation at ${docsUrl} to set up manually.${debugInfo}`,\n error: error as Error,\n });\n }\n })().catch((error: unknown) => {\n emitWizardError({\n code: ErrorCodes.InternalUnhandled,\n message: error instanceof Error ? error.message : String(error),\n });\n process.exit(1);\n });\n}\n","import type { ProgramConfig } from '@lib/programs/program-step';\nimport { runNonInteractive } from './run-non-interactive';\n\n/**\n * CI-mode entry point (`--ci`, dev/test builds). A thin shell over the shared\n * non-interactive pipeline — see `runNonInteractive`. Kept as its own function\n * so CI and headless (`runWizardHeadless`) can diverge without re-threading the\n * many callers that route here.\n */\nexport function runWizardCI(\n config: ProgramConfig,\n options: Record<string, unknown>,\n): void {\n runNonInteractive(config, options, 'ci');\n}\n","import type { ProgramConfig } from '@lib/programs/program-step';\nimport { runNonInteractive } from './run-non-interactive';\n\n/**\n * Headless entry point (the experimental published-build, non-interactive run\n * path; see @lib/headless-mode). A thin shell over the shared non-interactive\n * pipeline — see `runNonInteractive`. Today it behaves exactly like\n * `runWizardCI`; it exists as a separate function so headless can diverge later\n * (its own auth handling, telemetry, prompts, …) without touching CI or its\n * callers. Diverge by branching on the mode inside `runNonInteractive`, or by\n * giving this function its own body.\n */\nexport function runWizardHeadless(\n config: ProgramConfig,\n options: Record<string, unknown>,\n): void {\n runNonInteractive(config, options, 'headless');\n}\n","/**\n * Per-command options shared by every skill-based program command\n * (`audit events`, `migrate statsig`, `revenue`, `source-maps`, …).\n *\n * Only flags unique to skill commands live here. Global flags are declared\n * once in `wizard.ts` — both in `GLOBAL_OPTIONS` and, for the dev-only ones,\n * the `Wizard` constructor — and apply to every command automatically.\n */\nexport const skillProgramOptions = {\n 'install-dir': {\n describe: 'Directory to install in',\n type: 'string' as const,\n },\n};\n","import type { Arguments, Options } from 'yargs';\n\nimport { runWizard, runWizardCI, runWizardHeadless } from '@lib/runners';\nimport { isHeadless } from '@lib/headless-mode';\nimport type { ProgramConfig } from '@lib/programs/program-step';\n\nimport { skillProgramOptions } from '../skill-program-options';\nimport { ErrorCodes } from '@shared/errors';\nimport { emitWizardError } from '@shared/errors';\n\n/**\n * Dispatch a parsed yargs invocation to the wizard runner. Applies the\n * program's `mapCliOptions` transform, then routes to `runWizardHeadless`,\n * `runWizardCI`, or `runWizard` based on the headless / `--ci` flags.\n *\n * Every command file used to inline this; the factories call it instead.\n */\n/**\n * Run a command's async body as fire-and-forget while still surfacing failures.\n * yargs handlers are synchronous, so async work kicks off a detached promise —\n * without this, a rejection becomes an unhandled promise rejection (no message,\n * wrong exit code). This awaits the work and turns any error into a clean\n * message + non-zero exit.\n */\nexport function runCommandHandler(work: () => void | Promise<void>): void {\n void (async () => {\n try {\n await work();\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`\\n\\x1b[1;91m✖ ${msg}\\x1b[0m\\n\\n`);\n emitWizardError({ code: ErrorCodes.InternalUnhandled, message: msg });\n process.exit(1);\n }\n })();\n}\n\nexport function dispatchProgram(config: ProgramConfig, argv: Arguments): void {\n const argvRecord: Record<string, unknown> = { ...argv };\n const extras = config.mapCliOptions?.(argvRecord) ?? {};\n const options = { ...argvRecord, ...extras };\n if (isHeadless(options)) {\n // Same non-interactive pipeline `--ci` uses; validation (api-key,\n // install-dir, region) is owned by runNonInteractive.\n runWizardHeadless(config, options);\n } else if (options.ci) {\n runWizardCI(config, options);\n } else {\n runWizard(config, options);\n }\n}\n\n/**\n * Merge the standard skill-program flags (`--debug`, `--install-dir`, etc.)\n * with any program-specific options declared on `cliOptions`.\n *\n * Program-specific options shadow the standard ones — that's intentional, so\n * a program can override a default flag if it ever needs to.\n */\nexport function mergeCommandOptions(\n config: ProgramConfig,\n): Record<string, Options> {\n return {\n ...skillProgramOptions,\n ...((config.cliOptions ?? {}) as Record<string, Options>),\n };\n}\n","import type { ProgramConfig } from '@lib/programs/program-step';\n\nimport type { Command } from '../command';\n\nimport { dispatchProgram, mergeCommandOptions } from './shared';\n\nexport interface NativeCommandFactoryOpts {\n /** Subcommands nested under this command. */\n children?: readonly Command[];\n}\n\n/**\n * Build a yargs `Command` from a wizard-native `ProgramConfig`.\n *\n * Collapses the previously duplicated boilerplate (read `config.command`,\n * merge skill-program flags with program-specific options, dispatch via\n * `runWizard` / `runWizardCI`) into a single call.\n */\nexport function nativeCommandFactory(\n config: ProgramConfig,\n opts: NativeCommandFactoryOpts = {},\n): Command {\n if (!config.command) {\n throw new Error(\n `nativeCommandFactory: program \"${config.id}\" has no \\`command\\` — wizard-native programs must declare a CLI name`,\n );\n }\n return {\n name: config.command,\n description: config.description,\n options: mergeCommandOptions(config),\n children: opts.children,\n handler: (argv) => dispatchProgram(config, argv),\n };\n}\n","import { mcpAnalyticsConfig } from '@lib/programs/mcp-analytics/index';\n\nimport type { Command } from './command';\nimport { nativeCommandFactory } from './factories/native-command-factory';\n\n/**\n * `wizard mcp-analytics` — flat skill command, instrument-an-MCP-server today.\n *\n * Distinct from `wizard mcp add`: this instruments the user's own MCP server\n * with the `@posthog/mcp` SDK, rather than installing the PostHog MCP server\n * into a coding agent. Stays flat while instrumenting is the only action.\n */\nexport const mcpAnalyticsCommand: Command =\n nativeCommandFactory(mcpAnalyticsConfig);\n","import { replayVisionConfig } from '@lib/programs/replay-vision/index';\n\nimport type { Command } from './command';\nimport { nativeCommandFactory } from './factories/native-command-factory';\n\n/**\n * `wizard replay-vision` — flat skill command, set up Replay vision today.\n *\n * Enables session replay recording and creates vision scanners tailored to\n * the product's key flows. Runs the `replay-vision` orchestrator flow, which\n * reuses the integration-v2 install/init mini-agents when the repo has no\n * PostHog integration yet.\n */\nexport const replayVisionCommand: Command =\n nativeCommandFactory(replayVisionConfig);\n","import { aiObservabilityConfig } from '@lib/programs/ai-observability/index';\n\nimport type { Command } from './command';\nimport { nativeCommandFactory } from './factories/native-command-factory';\n\n/**\n * `wizard ai-observability` — flat skill command, wire AI Observability into a\n * project today.\n *\n * Installs the OpenTelemetry SDK, the PostHog span processor, and the\n * provider-specific instrumentation so LLM calls emit `$ai_generation` events.\n * The `ai-observability` context-mill skill has one variant per (LLM provider ×\n * language); the agent picks the right one at run time by scanning the\n * project's manifest and (when ambiguous) asking the user via `wizard_ask`.\n * Stays flat while a single \"add AIO to a project\" flow is the only action.\n */\nexport const aiObservabilityCommand: Command = nativeCommandFactory(\n aiObservabilityConfig,\n);\n","import { metricsConfig } from '@lib/programs/metrics/index';\n\nimport type { Command } from './command';\nimport { nativeCommandFactory } from './factories/native-command-factory';\n\n/**\n * `wizard metrics` — flat skill command, wire PostHog application metrics\n * (counters, gauges, histograms via \\`posthog.metrics\\`) into a project.\n *\n * The `metrics` context-mill skill has one variant per platform (python,\n * nodejs, javascript, kubernetes, other/OTLP); the agent picks the right one\n * at run time by scanning the project's manifest and (when ambiguous) asking\n * the user via `wizard_ask`. Stays flat while a single \"add metrics to a\n * project\" flow is the only action.\n */\nexport const metricsCommand: Command = nativeCommandFactory(metricsConfig);\n","import type { Arguments } from 'yargs';\n\nimport { auditConfig } from '@lib/programs/audit/index';\nimport { AUDIT_CHECKS_FILE } from '@lib/programs/audit/types';\nimport { WIZARD_TOOL_NAMES } from '@agent';\nimport { agentSkillConfig } from '@lib/programs/program-registry';\nimport { webAnalyticsDoctorConfig } from '@lib/programs/web-analytics-doctor/index';\nimport type { ProgramConfig } from '@lib/programs/program-step';\nimport { getSkillsBaseUrl } from '@shared/constants';\nimport { fetchSkillMenu, type CliEntry } from '@shared/skill-menu';\nimport { analytics } from '@utils/analytics';\n\nimport { dispatchProgram } from '../../commands/factories/shared';\nimport type { Command } from '../../commands/command';\nimport { ErrorCodes } from '@shared/errors';\nimport { emitWizardError } from '@shared/errors';\n\n/**\n * Capture a CLI dispatch error, flush analytics, and exit. The wizard never\n * starts a run from these paths — use flush() (not shutdown()) so we don't\n * fire a \"setup wizard finished\" event for a parse error that didn't run.\n */\nasync function exitDispatchError(\n reason: string,\n properties: Record<string, unknown>,\n message: string,\n code = 1,\n): Promise<never> {\n analytics.wizardCapture('cli dispatch error', { reason, ...properties });\n try {\n await analytics.flush();\n } catch {\n /* flush is best-effort; never block the exit */\n }\n process.stderr.write(message);\n emitWizardError({ code: ErrorCodes.CliBadArgs, message: reason });\n return process.exit(code);\n}\n\n/**\n * Family commands (`wizard audit`, `wizard migrate`, ...) resolve their\n * subcommands at runtime against the published `cliEntries` inside\n * `skill-menu.json`. Adding a subcommand is a context-mill release — no\n * wizard release needed.\n *\n * Wizard-native subcommands (programs that aren't backed by a single skill,\n * e.g. `wizard audit web-analytics`) live here in code, dispatched directly\n * without touching the registry. Adding a native is a wizard PR.\n */\n\n/** Wizard-native subcommands keyed by family. */\nconst NATIVE_HANDLERS: Record<string, Record<string, ProgramConfig>> = {\n audit: { 'web-analytics': webAnalyticsDoctorConfig },\n};\n\n/**\n * Resolve a fetched CliEntry to the ProgramConfig that actually runs it.\n * Most entries run via the generic agent-skill program with the entry's\n * `skillId` injected. The comprehensive `audit all` is the one exception —\n * skillId 'audit' triggers the specialized auditConfig (custom hooks,\n * content blocks, screens).\n *\n * This is the one place that knows a subcommand belongs to `audit`, so the\n * generic skill program picks up the ledger here rather than for every skill.\n */\nfunction configForCliEntry(entry: CliEntry, family: string): ProgramConfig {\n if (entry.skillId === 'audit') return auditConfig;\n return {\n ...agentSkillConfig,\n skillId: entry.skillId,\n ...(family === 'audit'\n ? {\n auditLedgerFile: AUDIT_CHECKS_FILE,\n streamWorkflowId: family,\n allowedTools: [\n ...(agentSkillConfig.allowedTools ?? []),\n WIZARD_TOOL_NAMES.auditSeedChecks,\n WIZARD_TOOL_NAMES.auditAddChecks,\n WIZARD_TOOL_NAMES.auditResolveChecks,\n ],\n }\n : {}),\n };\n}\n\nfunction familyEntries(family: string, entries: CliEntry[]): CliEntry[] {\n return entries.filter(\n (e) =>\n e.role === 'command' && e.parentCommand === family && Boolean(e.command),\n );\n}\n\n/**\n * Dispatch `wizard <family> <sub>` to the right program.\n *\n * Order:\n * 1. Native handler for (family, sub) — runs immediately, no network.\n * 2. Fetched CliEntry — runs the resolved skill.\n * 3. Unknown — prints the available list and exits non-zero.\n */\nexport async function dispatchFamily(\n family: string,\n argv: Arguments,\n): Promise<void> {\n const sub = (argv.skill as string | undefined)?.trim();\n if (!sub) {\n // Reached only in non-TTY/CI — an interactive terminal routes the no-sub\n // case to the picker before this runs, so don't suggest opening it here.\n return exitDispatchError(\n 'missing subcommand',\n { family },\n `\\n\\x1b[1;91m✖ \\`wizard ${family}\\` requires a subcommand.\\x1b[0m\\n` +\n ` Pass one (e.g. \\`wizard ${family} <subcommand>\\`), or run it in an interactive terminal to pick from a menu.\\n\\n`,\n );\n }\n\n const native = NATIVE_HANDLERS[family]?.[sub];\n if (native) {\n dispatchProgram(native, argv);\n return;\n }\n\n const skillsBaseUrl = getSkillsBaseUrl();\n const menu = await fetchSkillMenu(skillsBaseUrl);\n if (!menu) {\n return exitDispatchError(\n 'registry unreachable',\n { family, sub, skillsBaseUrl },\n `\\n\\x1b[1;91m✖ Couldn't reach the skill registry at ${skillsBaseUrl}.\\x1b[0m\\n` +\n ` Check your network connection and try again.\\n\\n`,\n );\n }\n\n const entries = menu.cliEntries ?? [];\n const entry = familyEntries(family, entries).find((e) => e.command === sub);\n if (entry) {\n dispatchProgram(configForCliEntry(entry, family), argv);\n return;\n }\n\n const available = [\n ...Object.keys(NATIVE_HANDLERS[family] ?? {}),\n ...familyEntries(family, entries).map((e) => e.command!),\n ].sort();\n return exitDispatchError(\n 'unknown subcommand',\n { family, sub, available },\n `\\n\\x1b[1;91m✖ Unknown subcommand \"${sub}\" under \\`${family}\\`.\\x1b[0m\\n` +\n (available.length\n ? ` Available: ${available.join(', ')}\\n\\n`\n : ` No subcommands published for \"${family}\" yet.\\n\\n`),\n );\n}\n\n/**\n * Build the children list shown in the family's interactive picker.\n * Combines native handlers with skill-backed entries from the live registry.\n * Used by `familyCommandFactory`'s `interactiveDefault`.\n */\nexport function buildFamilyPickerChildren(\n family: string,\n entries: CliEntry[],\n): Command[] {\n const natives: Command[] = Object.entries(NATIVE_HANDLERS[family] ?? {}).map(\n ([cmd, program]) => ({\n name: cmd,\n description: program.description,\n handler: (argv: Arguments) => dispatchProgram(program, argv),\n }),\n );\n const live: Command[] = familyEntries(family, entries).map((entry) => ({\n name: entry.command!,\n description: entry.description,\n handler: (argv: Arguments) => {\n void dispatchFamily(family, {\n ...argv,\n skill: entry.command,\n } as Arguments);\n },\n default: entry.default,\n }));\n return [...natives, ...live];\n}\n\n/**\n * The children the family picker shows **today**: only the leaf marked\n * `default` (e.g. `audit events`). Every other subcommand stays runnable\n * directly (`wizard audit <name>`) — they just aren't listed in the picker yet.\n * Falls back to all children when nothing is marked `default`.\n *\n * Temporary: when we're ready to surface the full menu, return `children`\n * unchanged (and delete this note).\n */\nexport function pickerChildrenToShow(children: readonly Command[]): Command[] {\n const defaults = children.filter((c) => c.default);\n return defaults.length > 0 ? [...defaults] : [...children];\n}\n","/**\n * Filter-as-you-type matching for PickerMenu. Split out from the component so the\n * ranking is testable on its own — the component only decides when to call it.\n */\n\nimport Fuse, { type IFuseOptions } from 'fuse.js';\n\n/** The searchable face of a picker option. PickerMenu's `PickerOption<T>` satisfies it. */\nexport interface Searchable {\n label: string;\n hint?: string;\n description?: string;\n}\n\n/**\n * Fuzzy fallback config. `ignoreLocation` because a term matching at the end of a\n * description is as good as one at the start, and Fuse's default distance window\n * would score the late match away. 0.5 is the loosest threshold that still bottoms\n * out: below it `gthb` misses `GitHub` entirely, which is the whole point of having\n * a fuzzy pass; above it the tail grows without surfacing anything new at the top.\n */\nexport const FUSE_OPTIONS: IFuseOptions<Searchable> = {\n keys: [\n { name: 'label', weight: 3 },\n { name: 'hint', weight: 1 },\n { name: 'description', weight: 1 },\n ],\n ignoreLocation: true,\n threshold: 0.5,\n includeScore: true,\n};\n\nexport function buildPickerIndex<T extends Searchable>(options: T[]): Fuse<T> {\n return new Fuse(options, FUSE_OPTIONS as IFuseOptions<T>);\n}\n\nfunction haystack(option: Searchable): string {\n return `${option.label} ${option.hint ?? ''} ${\n option.description ?? ''\n }`.toLowerCase();\n}\n\n/**\n * Rank options against a query, best first, or `null` for an empty query.\n *\n * Two passes, literal before fuzzy. Anything that literally contains every\n * whitespace-separated term wins outright, in the list's own order — that covers how\n * people actually type (`git iss` → `GitHub issues`) and keeps the common case as\n * tight as a plain substring filter, which fuzzy matching on its own is not: Fuse at\n * a threshold loose enough to forgive `gthb` also lets a third of the list through\n * on `replay`.\n *\n * Only when nothing matches literally does Fuse get a turn, so a typo degrades to a\n * ranked guess instead of an empty list. Terms are AND-ed there too, each matched\n * fuzzily on its own — Fuse's bitap pass over the whole query would otherwise need\n * `git iss` to be a near-edit of the text it's matching. Scores are distances (0 is\n * exact) and sum across terms, hence the ascending sort; ties keep the order the\n * first term put them in, since the sort is stable.\n */\nexport function rankOptions<T extends Searchable>(\n fuse: Fuse<T>,\n options: T[],\n query: string,\n): T[] | null {\n const terms = query.toLowerCase().split(/\\s+/).filter(Boolean);\n if (!terms.length) {\n return null;\n }\n\n const literal = options.filter((option) =>\n terms.every((term) => haystack(option).includes(term)),\n );\n if (literal.length) {\n return literal;\n }\n\n let surviving: Map<T, number> | null = null;\n for (const term of terms) {\n const hits = new Map<T, number>(\n fuse.search(term).map(({ item, score }) => [item, score ?? 0]),\n );\n if (surviving === null) {\n surviving = hits;\n continue;\n }\n // Deleting the current key mid-iteration is well-defined for a Map.\n for (const [option, total] of surviving) {\n const score = hits.get(option);\n if (score === undefined) {\n surviving.delete(option);\n } else {\n surviving.set(option, total + score);\n }\n }\n }\n\n return [...(surviving ?? [])]\n .sort(([, a], [, b]) => a - b)\n .map(([option]) => option);\n}\n","/**\n * PromptLabel — Compact inline label for input prompts.\n *\n * Renders: [!] message\n * where [!] is black text on accent background.\n */\n\nimport { Box, Text } from 'ink';\nimport { Colors } from '@ui/tui/styles';\n\ninterface PromptLabelProps {\n message?: string;\n}\n\nexport const PromptLabel = ({ message }: PromptLabelProps) => {\n // No message → no row, so label-less pickers don't get a stray blank line.\n if (!message) return null;\n return (\n <Box>\n <Text bold color={Colors.accent}>\n {' '}\n {message}\n </Text>\n </Box>\n );\n};\n","/**\n * ConfirmButton — the confirm row used to submit a selection.\n *\n * Pure render. Multi-select menus (PickerMenu mode=\"multi\", GroupedPickerMenu)\n * append this below their options as the final focusable row: the user toggles\n * options with enter, then arrows down onto this row and presses enter to\n * submit. This replaces the older \"enter anywhere submits\" pattern, which\n * confused people who expected enter to toggle the focused item.\n *\n * Renders flat, mirroring the option rows — a focus triangle and the label,\n * accent and bold when focused, dimmed otherwise — so it lines up under the\n * options instead of sitting in a separate boxed target.\n */\n\nimport { Text } from 'ink';\nimport { Icons, Colors } from '@ui/tui/styles';\n\ninterface ConfirmButtonProps {\n /** Button text. Defaults to \"Confirm\". */\n label?: string;\n /** Whether the cursor is currently on the button. */\n focused: boolean;\n /** Optional selected-item count, rendered as \"Label (n)\" when > 0. */\n count?: number;\n}\n\nexport const ConfirmButton = ({\n label = 'Confirm',\n focused,\n count,\n}: ConfirmButtonProps) => {\n const text = count && count > 0 ? `${label} (${count})` : label;\n return (\n <Text\n color={focused ? Colors.accent : undefined}\n bold={focused}\n dimColor={!focused}\n >\n {focused ? Icons.triangleSmallRight : ' '} {text}\n </Text>\n );\n};\n","/**\n * useStdoutDimensions — Returns [columns, rows] and re-renders on terminal resize.\n *\n * Ink's useStdout() does not subscribe to resize events, so layout only updates\n * when something else causes a re-render. This hook listens to the stream's\n * 'resize' event (Node TTY) and updates state so the component re-renders\n * with the new dimensions.\n */\n\nimport { useStdout } from 'ink';\nimport { useState, useEffect } from 'react';\n\nexport function useStdoutDimensions(): [number, number] {\n const { stdout } = useStdout();\n const [size, setSize] = useState<[number, number]>(() => [\n stdout.columns || 80,\n stdout.rows || 24,\n ]);\n\n useEffect(() => {\n const cols = stdout.columns || 80;\n const rows = stdout.rows || 24;\n setSize([cols, rows]);\n\n const stream = stdout as NodeJS.WriteStream & {\n on?(event: string, fn: () => void): void;\n };\n if (typeof stream.on !== 'function') return;\n\n const onResize = () => {\n const c = stdout.columns || 80;\n const r = stdout.rows || 24;\n if (c > 0 && r > 0) setSize([c, r]);\n };\n stream.on('resize', onResize);\n return () => {\n stream.off?.('resize', onResize);\n };\n }, [stdout]);\n\n return size;\n}\n","/**\n * Pure utility functions for keyboard hints — no React or Ink dependencies.\n * Extracted for testability in a node Jest environment.\n */\n\nexport interface KeyboardHint {\n label: string;\n action: string;\n priority: number;\n}\n\n/** Well-known key matches corresponding to Ink's key.* properties. */\nexport enum KeyMatch {\n UpArrow = 'upArrow',\n DownArrow = 'downArrow',\n LeftArrow = 'leftArrow',\n RightArrow = 'rightArrow',\n Return = 'return',\n Escape = 'escape',\n Space = 'space',\n Backspace = 'backspace',\n /**\n * Any single printable character typed without a modifier. Broad by design,\n * so a binding using it must sit last — the first match wins, which is what\n * lets a specific char binding still take precedence over free typing.\n */\n Printable = 'printable',\n}\n\n/** A key match: either a KeyMatch enum value or a literal character string (e.g. 'a', 's'). */\nexport type KeyMatchOrChar = KeyMatch | (string & NonNullable<unknown>);\n\n/** Default priorities by key type. */\nconst DEFAULT_PRIORITY: Record<string, number> = {\n [KeyMatch.UpArrow]: 0,\n [KeyMatch.DownArrow]: 0,\n [KeyMatch.LeftArrow]: 1,\n [KeyMatch.RightArrow]: 1,\n [KeyMatch.Space]: 10,\n [KeyMatch.Printable]: 12,\n [KeyMatch.Backspace]: 13,\n [KeyMatch.Escape]: 20,\n [KeyMatch.Return]: 21,\n};\n\n/** Get the default display priority for a key match. */\nexport function getDefaultPriority(\n match: KeyMatchOrChar | KeyMatchOrChar[],\n): number {\n const first = Array.isArray(match) ? match[0] : match;\n return DEFAULT_PRIORITY[first] ?? 15;\n}\n\n/** Check if a KeyMatchOrChar matches the given input string and key flags. */\nexport function matchesKey(\n m: KeyMatchOrChar,\n input: string,\n key: { [k: string]: unknown },\n): boolean {\n switch (m) {\n case KeyMatch.UpArrow:\n return !!key.upArrow;\n case KeyMatch.DownArrow:\n return !!key.downArrow;\n case KeyMatch.LeftArrow:\n return !!key.leftArrow;\n case KeyMatch.RightArrow:\n return !!key.rightArrow;\n case KeyMatch.Return:\n return !!key.return;\n case KeyMatch.Escape:\n return !!key.escape;\n case KeyMatch.Space:\n return input === ' ';\n case KeyMatch.Backspace:\n return !!key.backspace || !!key.delete;\n case KeyMatch.Printable:\n // Ink sets a flag for every non-text key while still passing a non-empty\n // `input`, so any flag but shift rules out typing.\n // Any single non-control character, not just ASCII — a filter query can\n // hold an accented or non-Latin letter.\n return (\n input.length === 1 &&\n input >= ' ' &&\n input !== '\\x7f' &&\n Object.entries(key).every(([flag, on]) => !on || flag === 'shift')\n );\n default:\n return input === m;\n }\n}\n\n/** Serialize hints for comparison. */\nexport function hintsKey(hints: KeyboardHint[]): string {\n return hints.map((h) => `${h.label}:${h.action}`).join('|');\n}\n\n/** Deduplicate hints by label+action and sort by priority. */\nexport function deduplicateAndSort(hints: KeyboardHint[]): KeyboardHint[] {\n const seen = new Set<string>();\n const deduped: KeyboardHint[] = [];\n for (const hint of hints) {\n const k = `${hint.label}:${hint.action}`;\n if (!seen.has(k)) {\n seen.add(k);\n deduped.push(hint);\n }\n }\n deduped.sort((a, b) => a.priority - b.priority);\n return deduped;\n}\n","/**\n * KeyboardHintsProvider — Context for collecting and displaying keyboard hints.\n *\n * Input components register their hints via useKeyBindings. The provider\n * flattens, deduplicates, and sorts them. The hints bar stays visible for as\n * long as a screen has registered hints — it never auto-dismisses.\n */\n\nimport {\n createContext,\n useCallback,\n useContext,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\nimport {\n hintsKey,\n deduplicateAndSort,\n type KeyboardHint,\n} from './keyboard-hints-utils.js';\n\nexport type { KeyboardHint } from './keyboard-hints-utils.js';\n\ninterface KeyboardHintsContextValue {\n register(id: string, hints: KeyboardHint[]): void;\n unregister(id: string): void;\n hints: KeyboardHint[];\n}\n\nconst KeyboardHintsContext = createContext<KeyboardHintsContextValue>({\n register: () => undefined,\n unregister: () => undefined,\n hints: [],\n});\n\nexport const useKeyboardHintsContext = () => useContext(KeyboardHintsContext);\n\nexport const KeyboardHintsProvider = ({\n children,\n}: {\n children: ReactNode;\n}) => {\n const registrationsRef = useRef(new Map<string, KeyboardHint[]>());\n const [hints, setHints] = useState<KeyboardHint[]>([]);\n const prevHintsKeyRef = useRef('');\n\n const recompute = useCallback(() => {\n const all: KeyboardHint[] = [];\n for (const h of registrationsRef.current.values()) {\n all.push(...h);\n }\n const deduped = deduplicateAndSort(all);\n\n const newKey = hintsKey(deduped);\n if (newKey !== prevHintsKeyRef.current) {\n prevHintsKeyRef.current = newKey;\n setHints(deduped);\n }\n }, []);\n\n const register = useCallback(\n (id: string, h: KeyboardHint[]) => {\n registrationsRef.current.set(id, h);\n recompute();\n },\n [recompute],\n );\n\n const unregister = useCallback(\n (id: string) => {\n registrationsRef.current.delete(id);\n recompute();\n },\n [recompute],\n );\n\n return (\n <KeyboardHintsContext.Provider value={{ register, unregister, hints }}>\n {children}\n </KeyboardHintsContext.Provider>\n );\n};\n","/**\n * useKeyBindings — Declarative keyboard input + automatic hint registration.\n *\n * Replaces raw `useInput` in input components. Define bindings as data;\n * the hook wires up the Ink input handler AND registers hints in the\n * KeyboardHintsProvider. One source of truth for keys and their labels.\n */\n\nimport { useInput, type Key } from 'ink';\nimport { useEffect, useRef } from 'react';\nimport { useKeyboardHintsContext } from './useKeyboardHints.js';\nimport {\n matchesKey,\n getDefaultPriority,\n KeyMatch,\n type KeyboardHint,\n type KeyMatchOrChar,\n} from './keyboard-hints-utils.js';\n\nexport { KeyMatch };\nexport type { KeyMatchOrChar } from './keyboard-hints-utils.js';\n\nexport interface KeyBinding {\n /** Which key(s) trigger this binding. Array = multiple keys, one hint. */\n match: KeyMatchOrChar | KeyMatchOrChar[];\n /** Display label in hints bar (e.g. \"↑↓\", \"space\", \"enter\") */\n label: string;\n /** Description in hints bar (e.g. \"navigate\", \"toggle\") */\n action: string;\n /** Ordering priority (lower = further left). Defaults based on key type. */\n priority?: number;\n /** Handler called when the key matches. */\n handler: (input: string, key: Key) => void;\n}\n\n/**\n * Declarative key bindings hook. Replaces `useInput` in input components.\n * Registers hints automatically with the KeyboardHintsProvider.\n *\n * @param id Unique identifier for this component's hints registration\n * @param bindings Array of key binding definitions\n */\nexport function useKeyBindings(id: string, bindings: KeyBinding[]): void {\n const ctx = useKeyboardHintsContext();\n\n // Extract hints and register. Use a serialized key to avoid unnecessary updates.\n const hintsRef = useRef<string>('');\n const hints: KeyboardHint[] = bindings.map((b) => ({\n label: b.label,\n action: b.action,\n priority: b.priority ?? getDefaultPriority(b.match),\n }));\n const serialized = hints\n .map((h) => `${h.label}:${h.action}:${h.priority}`)\n .join('|');\n\n useEffect(() => {\n if (serialized !== hintsRef.current) {\n hintsRef.current = serialized;\n ctx.register(id, hints);\n }\n return () => ctx.unregister(id);\n // eslint-disable-next-line\n }, [id, serialized]);\n\n // Wire up input handling\n useInput((input, key) => {\n for (const binding of bindings) {\n const matches = Array.isArray(binding.match)\n ? binding.match\n : [binding.match];\n if (matches.some((m) => matchesKey(m, input, key))) {\n binding.handler(input, key);\n return;\n }\n }\n });\n}\n","/**\n * PickerMenu — Single and multi select.\n * Single mode: custom renderer with small triangle indicator; enter selects.\n * Multi mode: checkbox glyphs toggled with enter, plus a focusable\n * Confirm button below the options. The cursor moves onto the button and\n * enter submits — see MultiPickerMenu for the rationale.\n *\n * Key bindings are declared via useKeyBindings, which auto-registers\n * hints in the KeyboardHintsBar.\n */\n\nimport { Box, Text } from 'ink';\nimport { useEffect, useMemo, useState } from 'react';\nimport { buildPickerIndex, rankOptions } from './picker-filter.js';\nimport { Icons, Colors } from '@ui/tui/styles';\nimport { PromptLabel } from './PromptLabel.js';\nimport { ConfirmButton } from './ConfirmButton.js';\nimport { wordWrap } from './layout-helpers.js';\nimport { useStdoutDimensions } from '@ui/tui/hooks/useStdoutDimensions';\nimport {\n useKeyBindings,\n KeyMatch,\n type KeyBinding,\n type KeyMatchOrChar,\n} from '@ui/tui/hooks/useKeyBindings';\n\nexport interface PickerOption<T> {\n label: string;\n value: T;\n hint?: string;\n /**\n * Multi-select only: a secondary explanation rendered dimmed and wrapped on\n * its own line(s) beneath the label, for choices that need more than a title.\n * When unset, the row renders exactly as a label-only row.\n */\n description?: string;\n /** Glyph rendered before the label, in its own color — unaffected by\n * focus and disabled styling. */\n icon?: { glyph: string; color?: string };\n /** Dimmed and unselectable; navigation skips over it. */\n disabled?: boolean;\n /**\n * Section heading: unselectable (navigation skips it, like `disabled`) but\n * rendered as a bold header rather than a muted row. Set `disabled` too so\n * the skip logic treats it as non-selectable.\n */\n header?: boolean;\n /** Indent the label one level, e.g. items nested under a `header` row. */\n indent?: boolean;\n /**\n * Multi-select only: marks this option mutually exclusive with every other\n * option. Selecting it clears all other picks; selecting any non-exclusive\n * option clears it. Used e.g. for a browser connector that can't be\n * installed alongside local editors.\n */\n exclusive?: boolean;\n}\n\n/**\n * Step through a column's options in `dir`, wrapping, until an enabled\n * option is found. Returns `from` unchanged if the column is entirely\n * disabled.\n */\nfunction stepEnabled<T>(\n options: PickerOption<T>[],\n rows: number,\n from: number,\n dir: 1 | -1,\n): number {\n const col = Math.floor(from / rows);\n const colStart = col * rows;\n const colLen = Math.min(rows, options.length - colStart);\n let row = from % rows;\n for (let i = 0; i < colLen; i++) {\n row = (row + dir + colLen) % colLen;\n const idx = colStart + row;\n if (!options[idx]?.disabled) return idx;\n }\n return from;\n}\n\n/** First enabled option in [start, end), for initial focus and for entering\n * a page from the Confirm button. */\nfunction firstEnabled<T>(\n options: PickerOption<T>[],\n start = 0,\n end = options.length,\n): number {\n for (let i = start; i < end; i++) {\n if (!options[i]?.disabled) return i;\n }\n return start;\n}\n\n/** Last enabled option in [start, end), for wrapping from the button onto\n * the bottom of the page. */\nfunction lastEnabled<T>(\n options: PickerOption<T>[],\n start = 0,\n end = options.length,\n): number {\n for (let i = end - 1; i >= start; i--) {\n if (!options[i]?.disabled) return i;\n }\n return end - 1;\n}\n\n/**\n * Rows the surrounding screen or overlay consumes above and below a picker —\n * border + padding, title, prompt text, and the keyboard-hints bar. A\n * deliberately generous estimate: overshooting just shows a few fewer rows,\n * whereas undershooting lets a long list overflow the viewport (the bug this\n * windowing guards against). Mirrors GroupedPickerMenu's budgeting.\n */\nconst CHROME_OVERHEAD = 13;\n/**\n * Max visual rows a picker renders regardless of terminal height. Without a\n * ceiling a tall terminal lets a long list fill the whole viewport, which\n * reads as a wall of options; ~12 rows keeps the menu scannable and leaves\n * known breathing room above and below.\n */\nconst MAX_LIST_ROWS = 12;\n/** Extra rows a multi-select adds below its options: marginTop + Confirm button. */\nconst CONFIRM_CHROME = 3;\n/** Lists shorter than this never page — tall rows would split 2-3 options into pages of one. */\nconst MIN_COUNT_TO_PAGE = 5;\n/** Width the multi-select wraps option descriptions to (matches the render). */\nconst DESCRIPTION_WIDTH = 56;\n\ninterface PickerViewport {\n needsScroll: boolean;\n /** First option index on the current page. */\n start: number;\n /** One past the last option index on the current page. */\n end: number;\n hiddenAbove: number;\n hiddenBelow: number;\n /** Focus target one page over (wrapping), for the n/p keys. */\n pageStep: (focused: number, dir: 1 | -1) => number;\n}\n\n/**\n * Pages a single-column option list to the terminal height. The visible page\n * is derived from the focused index — no scroll state — so ↑/↓ flip pages as\n * focus crosses a page edge and n/p jump a whole page. Pages hold a fixed\n * option count sized to the tallest row (`rowCost`), trading a sparser page\n * on mixed-height lists for arithmetic-only paging. Engages only for\n * single-column pickers — multi-column grids already compress vertically.\n */\nfunction usePickerViewport(\n count: number,\n rowCost: number,\n chromeBelow: number,\n enabled: boolean,\n focused: number,\n): PickerViewport {\n const [, termRows] = useStdoutDimensions();\n const budget = Math.max(\n 5,\n Math.min(termRows - CHROME_OVERHEAD - chromeBelow, MAX_LIST_ROWS),\n );\n const needsScroll =\n enabled && count >= MIN_COUNT_TO_PAGE && count * rowCost > budget;\n // Reserve two rows for the \"↑/↓ N more\" indicators.\n const perPage = needsScroll\n ? Math.max(1, Math.floor((budget - 2) / rowCost))\n : count;\n const pageCount = Math.max(1, Math.ceil(count / perPage));\n const start = Math.floor(focused / perPage) * perPage;\n const end = Math.min(start + perPage, count);\n return {\n needsScroll,\n start,\n end,\n hiddenAbove: start,\n hiddenBelow: count - end,\n pageStep: (f, dir) =>\n ((Math.floor(f / perPage) + dir + pageCount) % pageCount) * perPage,\n };\n}\n\ninterface PickerMenuProps<T> {\n message?: string;\n options: PickerOption<T>[];\n mode?: 'single' | 'multi';\n centered?: boolean;\n columns?: 1 | 2 | 3 | 4;\n /**\n * Vertical space between options, in TUI rows. Defaults to 0 — i.e.\n * options stack tightly. Set to 1+ when the option labels are long\n * (wrap across multiple lines) or for visual breathing room.\n */\n optionMarginBottom?: number;\n /**\n * Filter-as-you-type. Defaults on once the list is long enough to page, where\n * finding one option means walking pages. Pass `false` to force it off.\n */\n filterable?: boolean;\n onSelect: (value: T | T[]) => void;\n}\n\n/** Lists at least this long get filtering. Shorter ones fit on a page or two,\n * where a filter row costs more rows than it saves. */\nconst FILTER_MIN_OPTIONS = 10;\n\nexport const PickerMenu = <T,>({\n message,\n options,\n mode = 'single',\n centered = false,\n columns = 1,\n optionMarginBottom = 0,\n filterable,\n onSelect,\n}: PickerMenuProps<T>) => {\n const canFilter = filterable ?? options.length >= FILTER_MIN_OPTIONS;\n const [filter, setFilter] = useState('');\n const fuse = useMemo(\n () => (canFilter ? buildPickerIndex(options) : null),\n [options, canFilter],\n );\n const visible = useMemo(\n () => (fuse ? rankOptions(fuse, options, filter) ?? options : options),\n [fuse, options, filter],\n );\n\n // Keyed by label, and owned here rather than by MultiPickerMenu: filtering\n // rewrites the list under the ticks, and the remount below would drop them.\n const [selected, setSelected] = useState<Set<string>>(new Set());\n\n const shared = {\n message,\n options: visible,\n centered,\n optionMarginBottom,\n onSelect,\n filter: canFilter ? filter : null,\n setFilter,\n totalCount: options.length,\n };\n\n // A filtered list is a fresh list with its own focus and paging, so remount on\n // each query rather than leaving stale indices to be re-validated.\n const key = String(filter);\n\n if (mode === 'multi') {\n return (\n <MultiPickerMenu\n key={key}\n {...shared}\n columns={columns}\n allOptions={options}\n selected={selected}\n setSelected={setSelected}\n />\n );\n }\n\n return <SinglePickerMenu key={key} {...shared} columns={columns} />;\n};\n\n/**\n * Backspace and free typing. Append these last: `Printable` matches almost any\n * key, and bindings resolve in order, so anything specific has to be registered\n * first to keep working. Both share a label/action so the hints bar shows one.\n */\nfunction filterBindings(\n filter: string,\n setFilter: (query: string) => void,\n): KeyBinding[] {\n return [\n {\n match: KeyMatch.Backspace,\n label: 'type',\n action: 'filter',\n handler: () => setFilter(filter.slice(0, -1)),\n },\n {\n match: KeyMatch.Printable,\n label: 'type',\n action: 'filter',\n handler: (input: string) => setFilter(filter + input),\n },\n ];\n}\n\n/** The filter row above a filterable list: what's typed, and how much it left. */\nconst FilterRow = ({\n filter,\n shown,\n total,\n}: {\n filter: string;\n shown: number;\n total: number;\n}) => (\n // Indented to sit under PromptLabel, which carries a leading space.\n <Box paddingLeft={1}>\n <Text dimColor>\n {filter\n ? `Filter: ${filter} (${shown} of ${total})`\n : `Type to filter ${total} options`}\n </Text>\n </Box>\n);\n\n/** Custom single-select with triangle indicator and accent highlight. */\nconst SinglePickerMenu = <T,>({\n message,\n options,\n centered = false,\n columns = 1,\n optionMarginBottom = 0,\n filter,\n setFilter,\n totalCount,\n onSelect,\n}: {\n message?: string;\n options: PickerOption<T>[];\n centered?: boolean;\n columns?: number;\n optionMarginBottom?: number;\n /** Current filter query, or null when this picker isn't filterable. */\n filter: string | null;\n setFilter: (query: string) => void;\n totalCount: number;\n onSelect: (value: T | T[]) => void;\n}) => {\n const [focused, setFocused] = useState(() => firstEnabled(options));\n const rows = Math.ceil(options.length / columns);\n // Single-select rows are label-only (no descriptions): one line plus margin.\n const viewport = usePickerViewport(\n options.length,\n 1 + optionMarginBottom,\n filter !== null ? 1 : 0,\n columns === 1,\n focused,\n );\n\n // Re-validate focus when the options change while mounted \\u2014 a list\n // that shrinks or disables entries can leave `focused` pointing at a\n // missing or disabled option, which would make enter a no-op.\n useEffect(() => {\n if (focused >= options.length || options[focused]?.disabled) {\n setFocused(firstEnabled(options));\n }\n }, [options, focused]);\n\n const bindings: KeyBinding[] = [\n {\n match: [KeyMatch.UpArrow, KeyMatch.DownArrow],\n label: '\\u2191\\u2193',\n action: 'navigate',\n handler: (_input, key) => {\n const dir = key.upArrow ? -1 : 1;\n // `start`/`end` derive from `focused`, so stepping past a page edge\n // flips the page rather than needing a bound here.\n setFocused(stepEnabled(options, rows, focused, dir));\n },\n },\n // Only on a non-filterable list. Once a filter row exists `n` and `p` are\n // characters, not commands — so they go for good, not just once a query is\n // typed, and the arrows carry paging instead by walking the whole list.\n ...(viewport.needsScroll && filter === null\n ? [\n {\n match: ['n', 'p'] as KeyMatchOrChar[],\n label: 'n/p',\n action: 'page',\n handler: (input: string) => {\n const target = viewport.pageStep(focused, input === 'n' ? 1 : -1);\n setFocused(\n options[target]?.disabled\n ? stepEnabled(options, rows, target, 1)\n : target,\n );\n },\n },\n ]\n : []),\n {\n match: KeyMatch.Return,\n label: 'enter',\n action: 'select',\n handler: () => {\n const selected = options[focused];\n if (selected && !selected.disabled) {\n onSelect(selected.value);\n }\n },\n },\n ];\n\n if (columns > 1) {\n bindings.splice(1, 0, {\n match: [KeyMatch.LeftArrow, KeyMatch.RightArrow],\n label: '\\u2190\\u2192',\n action: 'navigate',\n handler: (_input, key) => {\n const col = Math.floor(focused / rows);\n const row = focused % rows;\n\n let next = focused;\n if (key.leftArrow) {\n const prevCol = col > 0 ? col - 1 : columns - 1;\n next = Math.min(prevCol * rows + row, options.length - 1);\n }\n if (key.rightArrow) {\n const nextCol = col < columns - 1 ? col + 1 : 0;\n next = Math.min(nextCol * rows + row, options.length - 1);\n }\n // Landing on a disabled option slides to the column's nearest\n // enabled one.\n if (options[next]?.disabled) {\n next = stepEnabled(options, rows, next, 1);\n }\n setFocused(next);\n },\n });\n }\n\n if (filter !== null) {\n bindings.push(...filterBindings(filter, setFilter));\n }\n\n useKeyBindings('single-picker', bindings);\n\n // Chunk options into columns (column-first ordering)\n const columnArrays: PickerOption<T>[][] = [];\n for (let c = 0; c < columns; c++) {\n columnArrays.push(options.slice(c * rows, c * rows + rows));\n }\n\n const align = centered ? 'center' : undefined;\n\n const renderOption = (opt: PickerOption<T>, flatIdx: number) => {\n const isFocused = flatIdx === focused;\n const base = opt.hint ? `${opt.label} (${opt.hint})` : opt.label;\n const label = opt.indent ? ` ${base}` : base;\n return (\n <Box key={flatIdx} gap={1} marginBottom={optionMarginBottom}>\n <Text\n color={isFocused ? Colors.accent : undefined}\n dimColor={!isFocused}\n >\n {isFocused && !opt.header ? Icons.triangleSmallRight : ' '}\n </Text>\n {opt.icon && <Text color={opt.icon.color}>{opt.icon.glyph}</Text>}\n <Text\n color={\n opt.header\n ? undefined\n : opt.disabled\n ? Colors.muted\n : isFocused\n ? Colors.accent\n : undefined\n }\n bold={opt.header || (isFocused && !opt.disabled)}\n dimColor={!opt.header && (!isFocused || opt.disabled)}\n >\n {label}\n </Text>\n </Box>\n );\n };\n\n return (\n <Box flexDirection=\"column\" alignItems={align}>\n <PromptLabel message={message} />\n {filter !== null && (\n <FilterRow filter={filter} shown={options.length} total={totalCount} />\n )}\n {filter && options.length === 0 ? (\n <Text dimColor>No options match. Backspace to widen the filter.</Text>\n ) : viewport.needsScroll ? (\n <Box flexDirection=\"column\">\n <Text dimColor>\n {viewport.hiddenAbove > 0\n ? `↑ ${viewport.hiddenAbove} more${\n filter === null ? ' [P] for previous page' : ''\n }`\n : ' '}\n </Text>\n {options\n .slice(viewport.start, viewport.end)\n .map((opt, relIdx) => renderOption(opt, viewport.start + relIdx))}\n <Text dimColor>\n {viewport.hiddenBelow > 0\n ? `↓ ${viewport.hiddenBelow} more${\n filter === null ? ' [N] for next page' : ''\n }`\n : ' '}\n </Text>\n </Box>\n ) : (\n <Box flexDirection=\"row\" gap={4}>\n {columnArrays.map((colOpts, colIdx) => (\n <Box key={colIdx} flexDirection=\"column\">\n {colOpts.map((opt, rowIdx) =>\n renderOption(opt, colIdx * rows + rowIdx),\n )}\n </Box>\n ))}\n </Box>\n )}\n </Box>\n );\n};\n\n/**\n * Custom multi-select with checkbox glyphs and accent highlight.\n *\n * Interaction model (shared with GroupedPickerMenu):\n * - \\u2191\\u2193 move the cursor through the options AND onto the Confirm button,\n * which lives just past the last option.\n * - enter toggles the focused option (no more \"space toggles but enter\n * advances\" split that tripped people up). Space is kept as an\n * undocumented alias, but the hints bar advertises only enter.\n * - moving onto the Confirm button and pressing enter submits the\n * current selection.\n */\nconst MultiPickerMenu = <T,>({\n message,\n options,\n centered = false,\n columns = 1,\n optionMarginBottom = 0,\n filter,\n setFilter,\n totalCount,\n allOptions,\n selected,\n setSelected,\n onSelect,\n}: {\n message?: string;\n options: PickerOption<T>[];\n centered?: boolean;\n columns?: number;\n optionMarginBottom?: number;\n /** Current filter query, or null when this picker isn't filterable. */\n filter: string | null;\n setFilter: (query: string) => void;\n totalCount: number;\n /** Every option, filtered or not. Ticks outlive the query, so resolving and\n * submitting them has to happen against the full list. */\n allOptions: PickerOption<T>[];\n selected: Set<string>;\n setSelected: (update: (prev: Set<string>) => Set<string>) => void;\n onSelect: (value: T | T[]) => void;\n}) => {\n const [focused, setFocused] = useState(() => firstEnabled(options));\n // When true, the cursor is on the Confirm button rather than an option.\n const [onButton, setOnButton] = useState(false);\n const rows = Math.ceil(options.length / columns);\n // A row is its label line plus any margin; a description adds one line per\n // wrapped line beneath the label. Pages size to the tallest row.\n const rowCost = options.reduce(\n (max, opt) =>\n Math.max(\n max,\n 1 +\n optionMarginBottom +\n (opt.description\n ? wordWrap(opt.description, DESCRIPTION_WIDTH).length\n : 0),\n ),\n 1,\n );\n const viewport = usePickerViewport(\n options.length,\n rowCost,\n CONFIRM_CHROME + (filter !== null ? 1 : 0),\n columns === 1,\n focused,\n );\n\n // Re-validate focus when the options change while mounted — a list\n // that shrinks or disables entries can leave `focused` pointing at a\n // missing or disabled option, which would make enter a no-op.\n useEffect(() => {\n if (focused >= options.length || options[focused]?.disabled) {\n setFocused(firstEnabled(options));\n }\n }, [options, focused]);\n\n const confirm = () => {\n // In `allOptions` order, so a pick made under one filter still submits\n // after the query moved on.\n const values = allOptions\n .filter((option) => selected.has(option.label))\n .map((option) => option.value);\n onSelect(values);\n };\n\n const bindings: KeyBinding[] = [\n {\n match: [KeyMatch.UpArrow, KeyMatch.DownArrow],\n label: '\\u2191\\u2193',\n action: 'navigate',\n handler: (_input, key) => {\n const dir = key.upArrow ? -1 : 1;\n if (onButton) {\n // Button \\u2192 back onto the current page (bottom for \\u2191, top for \\u2193).\n setOnButton(false);\n setFocused(\n dir === -1\n ? lastEnabled(options, viewport.start, viewport.end)\n : firstEnabled(options, viewport.start, viewport.end),\n );\n return;\n }\n const col = Math.floor(focused / rows);\n const row = focused % rows;\n const colLen = Math.min(rows, options.length - col * rows);\n // Nearest enabled option above/below in this column; leaving the\n // column lands on the button.\n let r = row + dir;\n while (r >= 0 && r < colLen && options[col * rows + r]?.disabled) {\n r += dir;\n }\n if (r >= 0 && r < colLen) {\n setFocused(col * rows + r);\n } else {\n setOnButton(true);\n }\n },\n },\n // Only on a non-filterable list. Once a filter row exists `n` and `p` are\n // characters, not commands — so they go for good, not just once a query is\n // typed, and the arrows carry paging instead by walking the whole list.\n ...(viewport.needsScroll && filter === null\n ? [\n {\n match: ['n', 'p'] as KeyMatchOrChar[],\n label: 'n/p',\n action: 'page',\n handler: (input: string) => {\n const target = viewport.pageStep(focused, input === 'n' ? 1 : -1);\n setOnButton(false);\n setFocused(\n options[target]?.disabled\n ? stepEnabled(options, rows, target, 1)\n : target,\n );\n },\n },\n ]\n : []),\n {\n // Space is only an alias for enter when there's no filter to type into.\n match:\n filter !== null ? KeyMatch.Return : [KeyMatch.Space, KeyMatch.Return],\n label: 'enter',\n action: 'select',\n handler: () => {\n if (onButton) {\n confirm();\n return;\n }\n // `focused` can point past the end: filtering to zero matches leaves\n // nothing under the cursor, and enter is the natural thing to try there.\n const option = options[focused];\n if (!option || option.disabled) return;\n const label = option.label;\n setSelected((prev) => {\n const next = new Set(prev);\n if (next.has(label)) {\n next.delete(label);\n return next;\n }\n // Enforce mutual exclusivity: an exclusive option clears every other\n // pick; any other option clears previously-picked exclusive ones.\n if (option.exclusive) {\n return new Set([label]);\n }\n // Against `allOptions`: the pick being cleared may be off-screen\n // under the current query.\n for (const picked of next) {\n if (allOptions.find((o) => o.label === picked)?.exclusive) {\n next.delete(picked);\n }\n }\n next.add(label);\n return next;\n });\n },\n },\n ];\n\n if (columns > 1) {\n bindings.splice(1, 0, {\n match: [KeyMatch.LeftArrow, KeyMatch.RightArrow],\n label: '\\u2190\\u2192',\n action: 'navigate',\n handler: (_input, key) => {\n if (onButton) return;\n const col = Math.floor(focused / rows);\n const row = focused % rows;\n\n let next = focused;\n if (key.leftArrow) {\n const prevCol = col > 0 ? col - 1 : columns - 1;\n next = Math.min(prevCol * rows + row, options.length - 1);\n }\n if (key.rightArrow) {\n const nextCol = col < columns - 1 ? col + 1 : 0;\n next = Math.min(nextCol * rows + row, options.length - 1);\n }\n // Landing on a disabled option slides to the column's nearest\n // enabled one.\n if (options[next]?.disabled) {\n next = stepEnabled(options, rows, next, 1);\n }\n setFocused(next);\n },\n });\n }\n\n if (filter !== null) {\n bindings.push(...filterBindings(filter, setFilter));\n }\n\n useKeyBindings('multi-picker', bindings);\n\n const columnArrays: PickerOption<T>[][] = [];\n for (let c = 0; c < columns; c++) {\n columnArrays.push(options.slice(c * rows, c * rows + rows));\n }\n\n const renderOption = (opt: PickerOption<T>, flatIdx: number) => {\n const isFocused = !onButton && flatIdx === focused;\n const isSelected = selected.has(opt.label);\n const label = opt.hint ? `${opt.label} (${opt.hint})` : opt.label;\n const checkbox = isSelected ? Icons.squareFilled : Icons.squareOpen;\n return (\n <Box\n key={flatIdx}\n flexDirection=\"column\"\n marginBottom={optionMarginBottom}\n >\n <Box gap={1}>\n <Text\n color={isSelected ? 'white' : Colors.muted}\n dimColor={!isFocused && !isSelected}\n >\n {checkbox}\n </Text>\n {opt.icon && <Text color={opt.icon.color}>{opt.icon.glyph}</Text>}\n <Text\n color={\n opt.disabled\n ? Colors.muted\n : isFocused\n ? Colors.accent\n : undefined\n }\n bold={isFocused && !opt.disabled}\n dimColor={!isFocused || opt.disabled}\n >\n {label}\n </Text>\n </Box>\n {/* Optional dimmed, wrapped explanation under the label. The explicit\n width forces Ink to wrap (an unconstrained Box shrinks to its\n content and never wraps). Renders only when set, so label-only rows\n are byte-for-byte unchanged. */}\n {opt.description && (\n <Box marginLeft={4} width={DESCRIPTION_WIDTH}>\n <Text dimColor wrap=\"wrap\">\n {opt.description}\n </Text>\n </Box>\n )}\n </Box>\n );\n };\n\n return (\n <Box flexDirection=\"column\" alignItems={centered ? 'center' : undefined}>\n <PromptLabel message={message} />\n {filter !== null && (\n <FilterRow filter={filter} shown={options.length} total={totalCount} />\n )}\n {filter && options.length === 0 && (\n <Text dimColor>No options match. Backspace to widen the filter.</Text>\n )}\n {viewport.needsScroll ? (\n <Box\n flexDirection=\"column\"\n marginLeft={centered ? 0 : 2}\n marginTop={message ? 1 : 0}\n >\n <Text dimColor>\n {viewport.hiddenAbove > 0\n ? `↑ ${viewport.hiddenAbove} more${\n filter === null ? ' [P] for previous page' : ''\n }`\n : ' '}\n </Text>\n {options\n .slice(viewport.start, viewport.end)\n .map((opt, relIdx) => renderOption(opt, viewport.start + relIdx))}\n <Text dimColor>\n {viewport.hiddenBelow > 0\n ? `↓ ${viewport.hiddenBelow} more${\n filter === null ? ' [N] for next page' : ''\n }`\n : ' '}\n </Text>\n </Box>\n ) : (\n <Box\n flexDirection=\"row\"\n gap={4}\n marginLeft={centered ? 0 : 2}\n marginTop={message ? 1 : 0}\n >\n {columnArrays.map((colOpts, colIdx) => (\n <Box key={colIdx} flexDirection=\"column\">\n {colOpts.map((opt, rowIdx) =>\n renderOption(opt, colIdx * rows + rowIdx),\n )}\n </Box>\n ))}\n </Box>\n )}\n <Box marginTop={1} marginLeft={centered ? 0 : 2}>\n <ConfirmButton focused={onButton} count={selected.size} />\n </Box>\n </Box>\n );\n};\n","/**\n * Mount an Ink picker over a command's `children` and dispatch the\n * selected child's handler.\n *\n * Used as the `interactiveDefault` for family parents like\n * `wizard audit` — when the user invokes the parent without a leaf, this\n * shows a TUI menu instead of yargs's `demandCommand(1)` help dump.\n *\n * The picker opens when a family surfaces more than one option; the `default`\n * flag controls which one is pre-highlighted. When a family surfaces a single\n * option (today `audit` → `events`), `familyCommandFactory` runs it directly\n * instead, so the user lands on its intro screen rather than a one-item menu.\n *\n * Single-option commands aren't families — they should be flat\n * commands wired with `skillCommandFactory` / `nativeCommandFactory`\n * directly, not run through this module.\n */\n\nimport type { Arguments } from 'yargs';\nimport { Box, Text, render } from 'ink';\nimport { createElement } from 'react';\n\nimport { Colors } from '@ui/tui/styles';\nimport { PickerMenu } from '@ui/tui/primitives/PickerMenu';\n\nimport { commandKeys, type Command } from '../command';\n\ninterface FamilyPickerAppProps {\n parentLabel: string;\n options: { label: string; value: Command; hint?: string }[];\n onSelect: (cmd: Command) => void;\n}\n\nfunction FamilyPickerApp(props: FamilyPickerAppProps) {\n return createElement(\n Box,\n { flexDirection: 'column', paddingX: 1, paddingY: 1 },\n createElement(\n Text,\n { bold: true, color: Colors.accent },\n props.parentLabel,\n ),\n createElement(Box, { height: 1 }),\n createElement(PickerMenu<Command>, {\n message: 'Pick a subcommand',\n options: props.options,\n optionMarginBottom: 1,\n onSelect: (value) => {\n // PickerMenu in single mode returns one value; only the multi-mode\n // signature is the array variant. Narrow defensively.\n const cmd = Array.isArray(value) ? value[0] : value;\n if (cmd) props.onSelect(cmd);\n },\n }),\n );\n}\n\nfunction describe(child: Command): string {\n // Strip positional syntax (`search <query>` → `search`) for the picker label.\n return commandKeys(child.name)[0] ?? '';\n}\n\n/**\n * Reorder children so the `default`-marked entry is first, while\n * preserving the relative order of the rest. The picker's initial\n * focus is index 0, so this is what makes \"press Enter on\n * `wizard audit`\" run the default leaf (today `audit events`).\n *\n * Exported for testability — the ordering logic stays pure and\n * inspectable without mounting Ink.\n */\nexport function orderFamilyChildren(children: readonly Command[]): Command[] {\n const selectable = children.filter((c) => c.handler || c.children?.length);\n const defaults = selectable.filter((c) => c.default);\n const rest = selectable.filter((c) => !c.default);\n return [...defaults, ...rest];\n}\n\n/**\n * Render the picker. Resolves once the user has selected a child;\n * dispatching the child's handler is the caller's responsibility (so this\n * function stays pure-UI and easy to test by stubbing `render`).\n */\nexport function chooseFamilyChild(\n parentLabel: string,\n children: readonly Command[],\n): Promise<Command | null> {\n const ordered = orderFamilyChildren(children);\n if (ordered.length === 0) return Promise.resolve(null);\n\n const options = ordered.map((child) => ({\n label: describe(child),\n value: child,\n hint: child.description,\n }));\n\n return new Promise((resolve) => {\n let app: ReturnType<typeof render> | null = null;\n const handleSelect = (cmd: Command): void => {\n app?.unmount();\n resolve(cmd);\n };\n app = render(\n createElement(FamilyPickerApp, {\n parentLabel,\n options,\n onSelect: handleSelect,\n }),\n );\n });\n}\n\n/**\n * Returns an `interactiveDefault` handler for a family parent's no-leaf\n * invocation. Always opens the picker; the `default`-marked child is\n * shown first (pre-highlighted), so a single Enter keystroke runs it.\n *\n * Discovery + consent in one extra keystroke vs. auto-running silently.\n *\n * Wire onto a family parent:\n * export const auditCommand: Command = {\n * name: 'audit',\n * description: '...',\n * children: [...],\n * interactiveDefault: createFamilyPickerDefault('audit', auditChildren),\n * };\n */\nexport function createFamilyPickerDefault(\n parentLabel: string,\n children: readonly Command[],\n chooser: (\n label: string,\n children: readonly Command[],\n ) => Promise<Command | null> = chooseFamilyChild,\n): (argv: Arguments) => Promise<void> {\n return async (argv) => {\n const chosen = await chooser(parentLabel, children);\n if (!chosen) return;\n // We forward the PARENT's parsed argv straight to the chosen child. The\n // child's own option defaults and `check` validator do NOT run on this\n // path — they only run when the leaf is invoked directly\n // (`wizard audit events`). Harmless while leaves declare neither, but if a\n // leaf ever grows a `check` or a defaulted option, this path will skip it.\n await Promise.resolve(chosen.handler?.(argv));\n };\n}\n","import type { Arguments } from 'yargs';\n\nimport type { ProgramConfig } from '@lib/programs/program-step';\nimport {\n buildFamilyPickerChildren,\n dispatchFamily,\n pickerChildrenToShow,\n} from '@lib/programs/dispatch-family';\nimport { getSkillsBaseUrl } from '@shared/constants';\nimport { fetchSkillMenu } from '@shared/skill-menu';\n\nimport type { Command } from '../command';\nimport { createFamilyPickerDefault } from './family-picker';\nimport { mergeCommandOptions, runCommandHandler } from './shared';\n\nexport interface FamilyCommandFactoryOpts {\n /** The family's CLI name (e.g. 'audit'). */\n family: string;\n /** Help text for `wizard <family> --help`. */\n description: string;\n /**\n * Source for shared CLI options (e.g. --install-dir) merged onto the\n * family parent. Usually the family's flagship native config, or the\n * generic agent-skill config.\n */\n optionsFrom: ProgramConfig;\n}\n\n/**\n * Build a yargs `Command` for a family parent (`wizard audit`, etc.).\n *\n * - `wizard <family> <sub>` — `dispatchFamily` resolves `<sub>` against\n * native handlers first, then the live `cliEntries` from\n * `skill-menu.json`. Unknown subs error with the available list.\n * - `wizard <family>` (no positional) — in an interactive terminal, runs the\n * family's single shown entry directly (today `audit events`, so the user\n * lands on its intro screen); opens the picker once a family shows more than\n * one. In non-TTY/CI, falls through to `dispatchFamily`, which prints\n * \"requires a subcommand\" rather than running something unprompted.\n *\n * No static yargs children. New skill-backed subcommands appear after a\n * context-mill release without a wizard release. New *native* subcommands\n * (rare) are added by updating `NATIVE_HANDLERS` in `dispatch-family.ts`.\n */\nexport function familyCommandFactory({\n family,\n description,\n optionsFrom,\n}: FamilyCommandFactoryOpts): Command {\n // Bare `wizard <family>` in an interactive terminal. With a single option\n // today (e.g. `audit events`), skip the picker and run it directly so the\n // user lands on its own intro screen rather than a one-item menu. When a\n // family grows past one shown option, this opens the picker instead — no\n // wiring change needed.\n const openFamilyEntry = async (argv: Arguments): Promise<void> => {\n const skillsBaseUrl = getSkillsBaseUrl();\n const menu = await fetchSkillMenu(skillsBaseUrl);\n const children = buildFamilyPickerChildren(family, menu?.cliEntries ?? []);\n const toShow = pickerChildrenToShow(children);\n if (toShow.length === 1 && toShow[0]?.handler) {\n await Promise.resolve(toShow[0].handler(argv));\n return;\n }\n const picker = createFamilyPickerDefault(`wizard ${family}`, toShow);\n await picker(argv);\n };\n\n return {\n name: `${family} [skill]`,\n description,\n options: mergeCommandOptions(optionsFrom),\n positionals: {\n skill: {\n type: 'string',\n describe: 'Subcommand to run (omit to run the default)',\n },\n },\n handler: (argv: Arguments) => {\n const sub = (argv.skill as string | undefined)?.trim();\n // With a subcommand, resolve and run it. Without one, run the family's\n // default entry (or open the picker if there's more than one) — but only\n // in an interactive terminal. In non-TTY/CI, fall through to\n // dispatchFamily, which prints \"requires a subcommand\" rather than\n // running something unprompted or hanging on a picker that can't render.\n // runCommandHandler awaits the async work so a rejection surfaces as a\n // clean error instead of an unhandled promise rejection.\n runCommandHandler(() =>\n sub || !process.stdout.isTTY\n ? dispatchFamily(family, argv)\n : openFamilyEntry(argv),\n );\n },\n interactiveDefault: openFamilyEntry,\n };\n}\n","import { auditConfig } from '@lib/programs/audit/index';\n\nimport type { Command } from './command';\nimport { familyCommandFactory } from './factories/family-command-factory';\n\n/**\n * The `wizard audit` family.\n *\n * Subcommands are resolved at runtime: the wizard fetches `cliEntries` from\n * `skill-menu.json` and dispatches based on `parentCommand: 'audit'`. The\n * wizard-native handler for `web-analytics` lives in `NATIVE_HANDLERS` over\n * in `dispatch-family.ts`. `wizard audit` with no positional opens the\n * family picker, which combines native + live entries.\n *\n * Adding a new skill-backed audit subcommand is a context-mill release —\n * no wizard release needed.\n */\nexport const auditCommand: Command = familyCommandFactory({\n family: 'audit',\n description: auditConfig.description,\n optionsFrom: auditConfig,\n});\n","import { getUI, setUI } from '@ui';\nimport { LoggingUI } from '@ui/logging-ui';\nimport { readApiKeyFromEnv } from '@utils/env-api-key';\nimport { ErrorCodes } from '@shared/errors';\nimport { emitWizardError } from '@shared/errors';\nimport { runWizard } from '@lib/runners';\nimport {\n posthogDoctorConfig,\n fetchHealthIssues,\n getKindMeta,\n} from '@lib/programs/posthog-doctor/index';\nimport { skillProgramOptions } from './skill-program-options';\nimport type { Command } from './command';\n\nexport const doctorCommand: Command = {\n name: 'doctor',\n description: posthogDoctorConfig.description,\n options: {\n ...skillProgramOptions,\n ...(posthogDoctorConfig.cliOptions ?? {}),\n },\n handler: (argv) => {\n const extras =\n posthogDoctorConfig.mapCliOptions?.(argv as Record<string, unknown>) ??\n {};\n const options = { ...argv, ...extras };\n // doctor is otherwise a TUI-only diagnostic (it has no agent run); in CI we\n // fetch the project's health issues headlessly and report them instead.\n if (options.ci) {\n void runDoctorCI(options);\n } else {\n runWizard(posthogDoctorConfig, options);\n }\n },\n};\n\nconst SEVERITY_ORDER = { critical: 0, warning: 1, info: 2 } as const;\n\nasync function runDoctorCI(options: Record<string, unknown>): Promise<void> {\n setUI(new LoggingUI());\n const apiKey = (options.apiKey as string) ?? readApiKeyFromEnv() ?? undefined;\n if (!apiKey) {\n getUI().intro('PostHog Wizard');\n getUI().log.error('CI mode requires --api-key (personal API key phx_xxx)');\n emitWizardError({\n code: ErrorCodes.ArgsMissingApiKey,\n message: 'CI mode requires --api-key (personal API key phx_xxx)',\n });\n process.exit(1);\n }\n\n getUI().intro('Welcome to the PostHog setup wizard');\n getUI().log.info('Running posthog-doctor in CI mode');\n\n try {\n const { getOrAskForProjectData } = await import('@utils/setup-utils');\n const { host, accessToken, projectId } = await getOrAskForProjectData({\n signup: false,\n ci: true,\n apiKey,\n projectId: options.projectId\n ? Number(options.projectId as string)\n : undefined,\n baseUrl: options.baseUrl as string | undefined,\n });\n\n const issues = await fetchHealthIssues(\n accessToken,\n host.apiHost,\n projectId,\n );\n if (issues.length === 0) {\n getUI().log.success('No active issues — your project looks healthy.');\n process.exit(0);\n }\n\n const sorted = [...issues].sort(\n (a, b) => SEVERITY_ORDER[a.severity] - SEVERITY_ORDER[b.severity],\n );\n getUI().log.warn(\n `${issues.length} active issue${issues.length === 1 ? '' : 's'} found:`,\n );\n for (const issue of sorted) {\n getUI().log.info(\n ` • [${issue.severity}] ${getKindMeta(issue.kind).title}`,\n );\n }\n process.exit(1);\n } catch (error) {\n const { ApiError } = await import('@shared/api');\n const message =\n error instanceof ApiError && error.statusCode === 401\n ? 'Your PostHog API key is invalid or expired.'\n : error instanceof Error\n ? error.message\n : String(error);\n getUI().log.error(`Doctor failed: ${message}`);\n emitWizardError({\n code:\n error instanceof ApiError && error.statusCode === 401\n ? ErrorCodes.AuthInvalidOrExpired\n : ErrorCodes.InternalUnhandled,\n message,\n });\n process.exit(1);\n }\n}\n","import { migrationConfig } from '@lib/programs/migration/index';\n\nimport type { Command } from './command';\nimport { nativeCommandFactory } from './factories/native-command-factory';\n\n/**\n * `wizard migrate` — flat skill command, Statsig today.\n *\n * Stays flat while there's only one vendor. When a second vendor lands,\n * restructure into a family with `familyCommandFactory` and publish each\n * vendor as a `cliEntries` entry with `parentCommand: 'migrate'` from\n * context-mill. That move is a deliberate breaking change for users\n * (`wizard migrate` stops running Statsig directly), so do it explicitly\n * when the second vendor arrives, not pre-emptively.\n */\nexport const migrateCommand: Command = nativeCommandFactory(migrationConfig);\n","import { revenueAnalyticsConfig } from '@lib/programs/revenue-analytics/index';\n\nimport type { Command } from './command';\nimport { nativeCommandFactory } from './factories/native-command-factory';\n\n/**\n * `wizard revenue-analytics` — flat skill command, Stripe today.\n *\n * Stays flat while there's only one provider. Restructure into a family\n * if/when a second provider lands.\n */\nexport const revenueCommand: Command = nativeCommandFactory(\n revenueAnalyticsConfig,\n);\n","import { warehouseSourceConfig } from '@lib/programs/warehouse-source/index';\n\nimport type { Command } from './command';\nimport { nativeCommandFactory } from './factories/native-command-factory';\n\n/**\n * `wizard warehouse` — detect and connect a data warehouse source.\n *\n * Mirrors `revenue-analytics`: flat skill command driven by the\n * warehouse-source program.\n */\nexport const warehouseCommand: Command = nativeCommandFactory(\n warehouseSourceConfig,\n);\n","import { runWizard, runWizardCI } from '@lib/runners';\nimport { selfDrivingConfig } from '@lib/programs/self-driving/index';\nimport { skillProgramOptions } from './skill-program-options';\nimport type { Command } from './command';\n\nexport const selfDrivingCommand: Command = {\n name: 'self-driving',\n description: selfDrivingConfig.description,\n options: {\n ...skillProgramOptions,\n integrate: {\n describe:\n 'Integrate the PostHog SDK first, then set up Self-driving — skips the integration prompt and logs you in via OAuth (no \"create an account?\" question). Use when the project isn\\'t set up yet but you already have a PostHog account.',\n type: 'boolean',\n default: false,\n },\n ...(selfDrivingConfig.cliOptions ?? {}),\n },\n check: (argv) => {\n // self-driving builds on an existing integration and is fully interactive,\n // so the modes that break it are rejected before the TUI/agent loop spins\n // up rather than failing late (a 403 on the first MCP probe under --signup,\n // or a stalled `wizard_ask` with no bridge under --ci).\n if (argv.signup) {\n throw new Error(\n '`self-driving` cannot run with --signup. Just run `wizard ' +\n 'self-driving`: when your project has no PostHog, it asks whether ' +\n 'you already have an account and offers to create one for you ' +\n '(no flag needed).',\n );\n }\n if (argv.ci) {\n throw new Error(\n '`self-driving` cannot run in CI mode — it requires interactive steps ' +\n '(GitHub connect, issue-tracker selection, custom-scout approval).',\n );\n }\n return true;\n },\n handler: (argv) => {\n const extras =\n selfDrivingConfig.mapCliOptions?.(argv as Record<string, unknown>) ?? {};\n const options = { ...argv, ...extras };\n if (options.ci) {\n runWizardCI(selfDrivingConfig, options);\n } else {\n runWizard(selfDrivingConfig, options);\n }\n },\n};\n","import type { Arguments } from 'yargs';\nimport { getUI, setUI } from '@ui';\nimport { LoggingUI } from '@ui/logging-ui';\nimport { Program } from '@lib/programs/program-registry';\nimport { VERSION } from '@shared/version';\nimport { ErrorCodes } from '@shared/errors';\nimport { emitWizardError } from '@shared/errors';\nimport type { Command } from './command';\n\nexport const slackCommand: Command = {\n name: 'slack',\n description: 'Connect PostHog to your Slack',\n handler: runSlackConnect,\n // Mirrors the mcp command family shape: `wizard slack` and\n // `wizard slack add` run the same connect flow.\n children: [\n {\n name: 'add',\n description: 'Connect PostHog to your Slack',\n handler: runSlackConnect,\n },\n ],\n};\n\nfunction runSlackConnect(argv: Arguments): void {\n void (async () => {\n const debug = argv.debug as boolean | undefined;\n\n try {\n const { startTUI } = await import('@ui/tui/start-tui');\n const { buildSession } = await import('@lib/wizard-session');\n const tui = startTUI(VERSION, Program.SlackConnect);\n tui.store.session = buildSession({\n debug,\n baseUrl: argv.baseUrl as string | undefined,\n });\n } catch (err) {\n // TUI unavailable — connecting Slack has no headless fallback.\n setUI(new LoggingUI());\n getUI().log.error(\n `Connecting Slack requires an interactive terminal. ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n emitWizardError({\n code: ErrorCodes.CliInteractiveRequired,\n message: 'Connecting Slack requires an interactive terminal.',\n });\n process.exit(1);\n }\n })();\n}\n","import { runWizard, runWizardCI } from '@lib/runners';\nimport { errorTrackingUploadSourceMapsConfig } from '@lib/programs/error-tracking-upload-source-maps/index';\nimport { skillProgramOptions } from './skill-program-options';\nimport type { Command } from './command';\n\nexport const uploadSourcemapsCommand: Command = {\n // Must match ProgramConfig.command; legacy alias kept for #489 regression.\n name: [errorTrackingUploadSourceMapsConfig.command!, 'upload-sourcemaps'],\n description: errorTrackingUploadSourceMapsConfig.description,\n options: {\n ...skillProgramOptions,\n ...(errorTrackingUploadSourceMapsConfig.cliOptions ?? {}),\n },\n handler: (argv) => {\n const extras =\n errorTrackingUploadSourceMapsConfig.mapCliOptions?.(\n argv as Record<string, unknown>,\n ) ?? {};\n const options = { ...argv, ...extras };\n if (options.ci) {\n runWizardCI(errorTrackingUploadSourceMapsConfig, options);\n } else {\n runWizard(errorTrackingUploadSourceMapsConfig, options);\n }\n },\n};\n","import { errorTrackingConfig } from '@lib/programs/error-tracking/index';\n\nimport type { Command } from './command';\nimport { nativeCommandFactory } from './factories/native-command-factory';\n\n/**\n * `wizard error-tracking` — flat skill command, set up error tracking today.\n *\n * Wires up exception capture and — where the platform needs it — source-map /\n * debug-symbol upload. Runs the `error-tracking` orchestrator flow, which\n * reuses the integration-v2 install/init mini-agents when the repo has no\n * PostHog integration yet, so it works on uninstrumented projects too.\n */\nexport const errorTrackingCommand: Command =\n nativeCommandFactory(errorTrackingConfig);\n","import type { Arguments } from 'yargs';\nimport { POSTHOG_DOCS_URL } from '@shared/constants';\nimport { runWizard, runWizardCI } from '@lib/runners';\nimport { createSkillProgram } from '@lib/programs/agent-skill/index';\n\n/** Run an arbitrary context-mill skill by id (`wizard skill <id>`, headless with `--ci`). */\nexport function runSkillMode(argv: Arguments): void {\n const skillId = argv.skill as string;\n const config = createSkillProgram({\n skillId,\n command: 'skill',\n id: 'agent-skill',\n description: `Run skill: ${skillId}`,\n integrationLabel: skillId,\n successMessage: `${skillId} completed!`,\n reportFile: `posthog-${skillId}-report.md`,\n docsUrl: POSTHOG_DOCS_URL,\n spinnerMessage: `Running ${skillId}...`,\n estimatedDurationMinutes: 5,\n });\n const options = { ...argv, skillId };\n if (argv.ci) {\n runWizardCI(config, options);\n } else {\n runWizard(config, options);\n }\n}\n","import type { Arguments } from 'yargs';\n\nimport { getSkillsBaseUrl } from '@shared/constants';\nimport { fetchSkillMenu, type CliEntry } from '@shared/skill-menu';\nimport { analytics } from '@utils/analytics';\n\nimport { runSkillMode } from './basic-integration/skill';\nimport { skillProgramOptions } from './skill-program-options';\nimport { runCommandHandler } from './factories/shared';\nimport { ErrorCodes } from '@shared/errors';\nimport { emitWizardError } from '@shared/errors';\nimport type { Command } from './command';\n\n/** Read the `<skill-name>` positional (yargs camelCases the hyphenated key). */\nfunction readSkillName(argv: Arguments): string {\n return String(argv.skillName ?? argv['skill-name'] ?? '').trim();\n}\n\nconst BROWSABLE_ROLES: ReadonlySet<CliEntry['role']> = new Set([\n 'command',\n 'skill',\n]);\n\n/**\n * Reject an unknown skill id before the wizard authenticates.\n *\n * Without this, `readSkillName` accepts any non-empty string and the name is\n * only validated far downstream, when the agent tries to download it — after\n * the user has already logged in. A typo then costs a full auth round-trip\n * (the concern raised in review). We resolve against the same set\n * `downloadSkill` uses (`categories` flattened by `id`), so this never\n * false-rejects a skill the download would have accepted.\n *\n * If the registry is unreachable we stay silent and defer to the download\n * step's own `menu-fetch-failed` handling, rather than adding a second network\n * dependency that could block an otherwise-valid run.\n */\nasync function assertSkillExists(skillName: string): Promise<void> {\n const skillsBaseUrl = getSkillsBaseUrl();\n const menu = await fetchSkillMenu(skillsBaseUrl);\n if (!menu) return; // registry down — let the download step surface it\n const known = Object.values(menu.categories)\n .flat()\n .some((s) => s.id === skillName);\n if (known) return;\n analytics.wizardCapture('cli dispatch error', {\n reason: 'unknown skill',\n family: 'skill',\n sub: skillName,\n skillsBaseUrl,\n });\n try {\n await analytics.flush();\n } catch {\n /* best-effort */\n }\n throw new Error(\n `Unknown skill \"${skillName}\". Run \\`wizard skill list\\` to see available skills.`,\n );\n}\n\nfunction formatEntry(entry: CliEntry): string {\n const path = entry.parentCommand\n ? `wizard ${entry.parentCommand} ${entry.command}`\n : entry.command\n ? `wizard ${entry.command}`\n : `wizard skill ${entry.skillId}`;\n return ` ${entry.skillId.padEnd(38)} ${path.padEnd(36)} ${\n entry.description\n }`;\n}\n\n/**\n * `wizard skill list` — fetch and print every browsable skill in the catalog.\n *\n * Reads the live `skill-menu.json` so new skills appear immediately after a\n * context-mill release. `internal` skills are excluded from the listing.\n */\nconst listCommand: Command = {\n name: 'list',\n description: 'List every browsable skill in the catalog',\n handler: () => {\n runCommandHandler(async () => {\n const skillsBaseUrl = getSkillsBaseUrl();\n const menu = await fetchSkillMenu(skillsBaseUrl);\n if (!menu) {\n analytics.wizardCapture('cli dispatch error', {\n reason: 'registry unreachable',\n family: 'skill',\n sub: 'list',\n skillsBaseUrl,\n });\n try {\n await analytics.flush();\n } catch {\n /* best-effort */\n }\n process.stderr.write(\n `\\n\\x1b[1;91m✖ Couldn't reach the skill registry.\\x1b[0m\\n` +\n ` Check your network connection and try again.\\n\\n`,\n );\n emitWizardError({\n code: ErrorCodes.SkillMenuFetchFailed,\n message: \"Couldn't reach the skill registry.\",\n });\n process.exit(1);\n }\n const entries = (menu.cliEntries ?? []).filter((e) =>\n BROWSABLE_ROLES.has(e.role),\n );\n if (entries.length === 0) {\n process.stdout.write('No skills found.\\n');\n return;\n }\n process.stdout.write(\n `${entries.length} skill${entries.length === 1 ? '' : 's'}:\\n`,\n );\n process.stdout.write(\n ` ${'SKILL ID'.padEnd(38)} ${'COMMAND'.padEnd(36)} DESCRIPTION\\n`,\n );\n for (const entry of entries) {\n process.stdout.write(`${formatEntry(entry)}\\n`);\n }\n });\n },\n};\n\n/**\n * `wizard skill <skill-name>` — run a single context-mill skill by id.\n * `wizard skill list` — list every browsable skill in the catalog.\n *\n * Replaces the old `--skill=<id>` flag on the default command. The skill id\n * is fetched from context-mill's release at runtime (same mechanism the flag\n * used), so any published skill id works. Pass `--ci` to run headlessly.\n */\nexport const skillCommand: Command = {\n name: 'skill <skill-name>',\n description: 'Run a specific context-mill skill by name (or `list` them)',\n children: [listCommand],\n options: {\n ...skillProgramOptions,\n },\n // Under `.strictOptions()` yargs rejects a positional declared only in the\n // command string as an \"Unknown argument\" — it has to be registered via\n // `.positional()` too (see the `positionals` note on the Command interface).\n // Declare `skill-name` here so `wizard skill <id>` actually accepts its value.\n positionals: {\n 'skill-name': {\n type: 'string',\n describe: 'Skill id to run (e.g. audit-events), or `list`',\n },\n },\n // yargs already enforces the presence of the `<skill-name>` positional, but\n // an explicitly-empty value (`wizard skill \"\"`) would otherwise slip\n // through to a broken run. Reject it with the same friendly message\n // the old --skill flag gave. When `wizard skill list` matched the\n // child instead, yargs leaves the positional unset — the `null` guard\n // keeps the check from rejecting that route.\n check: (argv) => {\n if (argv.skillName == null && argv['skill-name'] == null) return true;\n if (!readSkillName(argv)) {\n throw new Error(\n 'skill needs a skill name, e.g. `wizard skill audit-events`',\n );\n }\n return true;\n },\n handler: (argv) => {\n runCommandHandler(async () => {\n const skillName = readSkillName(argv);\n await assertSkillExists(skillName);\n // runSkillMode reads `argv.skill`; bridge the positional onto it.\n runSkillMode({ ...argv, skill: skillName });\n });\n },\n};\n","import * as path from 'node:path';\nimport * as readline from 'node:readline/promises';\nimport type { Arguments } from 'yargs';\nimport { getUI, setUI } from '@ui';\nimport { LoggingUI } from '@ui/logging-ui';\nimport { analytics } from '@utils/analytics';\nimport {\n CLI_STEERING_TARGETS,\n type CliSteeringTarget,\n detectTargets,\n findTarget,\n installOrUpdatePostHogCli,\n installSteeringSnippet,\n} from '@steps/install-cli-steering';\nimport type { Command } from '../command';\n\nexport const cliAddCommand: Command = {\n name: 'add',\n description:\n \"Install or update PostHog CLI and add steering instructions to your coding agent's global instructions file\",\n options: {\n agent: {\n describe: 'Agent to install the instructions for',\n choices: CLI_STEERING_TARGETS.map((target) => target.id),\n type: 'string',\n },\n path: {\n describe:\n 'Write to an explicit instructions file instead of a detected agent',\n type: 'string',\n },\n all: {\n default: false,\n describe: 'Install for every detected agent without prompting',\n type: 'boolean',\n },\n },\n examples: [\n ['wizard cli add', 'Detect your coding agents and pick one'],\n [\n 'wizard cli add --agent claude-code',\n 'Install for Claude Code (~/.claude/CLAUDE.md)',\n ],\n ['wizard cli add --all', 'Install for every detected agent'],\n [\n 'wizard cli add --path ./AGENTS.md',\n 'Install into a specific instructions file',\n ],\n ],\n check: (argv) => {\n if (argv.all && (argv.agent || argv.path)) {\n throw new Error('--all cannot be combined with --agent or --path');\n }\n return true;\n },\n handler: (argv) => {\n void runCliAdd(argv);\n },\n};\n\nasync function runCliAdd(argv: Arguments): Promise<void> {\n setUI(new LoggingUI());\n const ui = getUI();\n ui.intro('PostHog CLI setup');\n\n const files = await resolveTargetFiles(argv);\n if (files.length === 0) {\n process.exit(1);\n return;\n }\n\n ui.log.info('Installing or updating PostHog CLI...');\n const cliInstallResult = installOrUpdatePostHogCli();\n if (!cliInstallResult.success) {\n ui.log.error(\n `Failed to install or update PostHog CLI: ${\n cliInstallResult.error ?? ''\n }`,\n );\n analytics.wizardCapture('cli steering installed', {\n files: files.length,\n failures: files.length,\n cli_install_failed: true,\n agent: typeof argv.agent === 'string' ? argv.agent : undefined,\n });\n process.exit(1);\n return;\n }\n ui.log.success('Installed or updated PostHog CLI.');\n\n let failures = 0;\n for (const file of files) {\n const result = installSteeringSnippet(file);\n if (result.success) {\n ui.log.success(`Installed PostHog steering instructions in ${file}`);\n } else {\n failures += 1;\n ui.log.error(`Failed to update ${file}: ${result.error ?? ''}`);\n }\n }\n\n analytics.wizardCapture('cli steering installed', {\n files: files.length,\n failures,\n agent: typeof argv.agent === 'string' ? argv.agent : undefined,\n });\n\n if (failures > 0) {\n process.exit(1);\n return;\n }\n ui.outro(\n 'Done. PostHog CLI is installed and your agent will now use `posthog-cli api` for PostHog tasks.',\n );\n process.exit(0);\n}\n\n/** Resolve which instruction files to write, from flags, detection, or a prompt. */\nasync function resolveTargetFiles(argv: Arguments): Promise<string[]> {\n const ui = getUI();\n\n if (typeof argv.path === 'string' && argv.path.trim()) {\n return [path.resolve(argv.path.trim())];\n }\n\n if (typeof argv.agent === 'string') {\n // yargs `choices` already rejected unknown ids.\n const target = findTarget(argv.agent);\n if (!target) {\n ui.log.error(`Unsupported agent: ${argv.agent}`);\n return [];\n }\n return [target.instructionsPath()];\n }\n\n const detected = detectTargets();\n if (detected.length === 0) {\n ui.log.error(\n 'No supported coding agents detected. Pass --agent <id> or --path <file> to choose a target.',\n );\n ui.log.info(\n `Supported agents: ${CLI_STEERING_TARGETS.map((t) => t.id).join(', ')}`,\n );\n return [];\n }\n\n if (argv.all === true) {\n ui.log.info(\n `Installing for all detected agents: ${detected\n .map((t) => t.name)\n .join(', ')}`,\n );\n return detected.map((target) => target.instructionsPath());\n }\n\n if (detected.length === 1) {\n ui.log.info(\n `Detected ${detected[0].name} (${detected[0].instructionsPath()})`,\n );\n return [detected[0].instructionsPath()];\n }\n\n // Non-interactive shells can't pick, so install for every detected agent —\n // the snippet is additive and idempotent, mirroring how MCP install treats\n // all supported clients.\n if (!process.stdin.isTTY || !process.stdout.isTTY) {\n ui.log.info(\n `Installing for all detected agents: ${detected\n .map((t) => t.name)\n .join(', ')}`,\n );\n return detected.map((target) => target.instructionsPath());\n }\n\n const selected = await promptForTargets(detected);\n return selected.map((target) => target.instructionsPath());\n}\n\n/** Minimal numbered selection — this command is intentionally not a TUI flow. */\nasync function promptForTargets(\n detected: CliSteeringTarget[],\n): Promise<CliSteeringTarget[]> {\n const ui = getUI();\n ui.log.info('Which coding agent are you using?');\n detected.forEach((target, index) => {\n ui.log.info(\n ` ${index + 1}) ${target.name} (${target.instructionsPath()})`,\n );\n });\n ui.log.info(` ${detected.length + 1}) All of the above`);\n\n const rl = readline.createInterface({\n input: process.stdin,\n output: process.stdout,\n });\n try {\n for (;;) {\n const answer = (\n await rl.question(`Select 1-${detected.length + 1}: `)\n ).trim();\n const choice = Number(answer);\n if (\n Number.isInteger(choice) &&\n choice >= 1 &&\n choice <= detected.length\n ) {\n return [detected[choice - 1]];\n }\n if (choice === detected.length + 1) {\n return detected;\n }\n ui.log.warn(`Enter a number between 1 and ${detected.length + 1}.`);\n }\n } finally {\n rl.close();\n }\n}\n","import { cliAddCommand } from './add';\nimport type { Command } from '../command';\n\nexport const cliCommand: Command = {\n name: 'cli',\n description: 'PostHog CLI agent integration commands',\n children: [cliAddCommand],\n};\n","#!/usr/bin/env node\nimport { satisfies } from 'semver';\nimport { Agent, setGlobalDispatcher } from 'undici';\nimport { ErrorCodes } from '@shared/errors/codes.js';\nimport { emitWizardError } from '@shared/errors/emit.js';\n\n// Keep in sync with `engines.node` in package.json. npx does not enforce\n// engines, so this preflight is the only thing standing between an old Node\n// runtime and a cryptic dependency crash (e.g. undici's markAsUncloneable\n// TypeError on Node < 22.10).\nconst NODE_VERSION_RANGE = '>=22.22.0';\n\n/*\n * TODO(#1198): remove when fetch over HTTP/2 is safe on Node 26. Remove when all\n * of these are true:\n * - nodejs/node no longer creates an orphan ClientHttp2Stream when a client\n * session gets HEADERS for a stream id it already reset. Repro: abort a fetch\n * before its response headers, then idle 4s on Node 26. Fixed when the\n * process survives.\n * - modelcontextprotocol/typescript-sdk#2526 is closed.\n * - pi-coding-agent's CLI drops `allowH2: false` from its http-dispatcher.\n * Same workaround as pi's CLI and typescript-sdk#2526: HTTP/1.1 only.\n */\nsetGlobalDispatcher(new Agent({ allowH2: false }));\n\n// Have to run this above the other imports because they are importing clack that\n// has the problematic imports.\nif (!satisfies(process.version, NODE_VERSION_RANGE)) {\n // eslint-disable-next-line no-console\n console.log(\n [\n `The PostHog wizard needs a newer version of Node.js to run.`,\n ``,\n ` You have: ${process.version}`,\n ` You need: v${NODE_VERSION_RANGE.replace('>=', '')} or later`,\n ``,\n `To update Node.js:`,\n ``,\n ` Download the latest version from https://nodejs.org/en/download`,\n ` Or, if you use nvm, run: nvm install 22 && nvm use 22`,\n ``,\n `Then run the wizard again. Stuck? Email wizard@posthog.com and we'll help.`,\n ].join('\\n'),\n );\n emitWizardError({\n code: ErrorCodes.CliNodeVersion,\n message: `Node ${process.version} is below the required range ${NODE_VERSION_RANGE}`,\n });\n process.exit(1);\n}\n\n// Test mock server — only loaded when NODE_ENV is 'test'.\n// In production builds, tsdown replaces process.env.NODE_ENV with 'production',\n// making this block dead code.\nif (process.env.NODE_ENV === 'test') {\n void (async () => {\n try {\n const { server } = await import('./e2e-tests/mocks/server.js');\n server.listen({\n onUnhandledRequest: 'bypass',\n });\n } catch (error) {\n // Mock server import failed - this can happen during non-E2E tests\n }\n })();\n}\n\nimport { Wizard } from './src/wizard';\nimport { basicIntegrationCommand } from './src/commands/basic-integration';\nimport { mcpCommand } from './src/commands/mcp';\nimport { mcpAnalyticsCommand } from './src/commands/mcp-analytics';\nimport { replayVisionCommand } from './src/commands/replay-vision';\nimport { aiObservabilityCommand } from './src/commands/ai-observability';\nimport { metricsCommand } from './src/commands/metrics';\nimport { auditCommand } from './src/commands/audit';\nimport { doctorCommand } from './src/commands/doctor';\nimport { migrateCommand } from './src/commands/migrate';\nimport { revenueCommand } from './src/commands/revenue';\nimport { warehouseCommand } from './src/commands/warehouse';\nimport { selfDrivingCommand } from './src/commands/self-driving';\nimport { slackCommand } from './src/commands/slack';\nimport { uploadSourcemapsCommand } from './src/commands/upload-sourcemaps';\nimport { errorTrackingCommand } from './src/commands/error-tracking';\nimport { skillCommand } from './src/commands/skill';\nimport { cliCommand } from './src/commands/cli';\nimport { recoverOrphanedSettingsBackups } from '@shared/claude-settings';\n\n// Heal any .claude/settings backup a previous interrupted run left orphaned,\n// before anything else reads Claude settings — conflict detection, OAuth, and\n// the agent all need to see the user's real settings file. The install dir is\n// read directly from argv/env because yargs hasn't parsed yet.\nrecoverOrphanedSettingsBackups(resolveInstallDir());\n\nfunction resolveInstallDir(): string {\n const args = process.argv.slice(2);\n const flagIndex = args.indexOf('--install-dir');\n if (flagIndex !== -1 && args[flagIndex + 1]) return args[flagIndex + 1];\n const inline = args.find((a) => a.startsWith('--install-dir='));\n if (inline) return inline.slice('--install-dir='.length);\n return process.env.POSTHOG_WIZARD_INSTALL_DIR ?? process.cwd();\n}\n\nWizard.use(basicIntegrationCommand)\n .use(mcpCommand)\n .use(mcpAnalyticsCommand)\n .use(replayVisionCommand)\n .use(aiObservabilityCommand)\n .use(metricsCommand)\n .use(cliCommand)\n .use(auditCommand)\n .use(doctorCommand)\n .use(migrateCommand)\n .use(revenueCommand)\n .use(warehouseCommand)\n .use(selfDrivingCommand)\n .use(slackCommand)\n .use(uploadSourcemapsCommand)\n .use(errorTrackingCommand)\n .use(skillCommand)\n .init();\n"],"mappings":"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"}