get-tbd 0.1.28 → 0.1.30

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { S as IssueTitle, b as IssueSchema, g as ISSUE_TITLE_MAX_LENGTH, n as AtticEntrySchema, t as ATTIC_ENTRY_FIELD_ORDER, x as IssueStatus, y as IssueKind } from "./schemas-C8mOQykE.mjs";
2
- import { a as insertAfterFrontmatter, c as noopLogger, i as serializeIssue, n as parseIssue, o as parseMarkdown, r as parseMarkdownWithFrontmatter, s as stripFrontmatter, t as VERSION$1 } from "./src-D2xEmH4L.mjs";
2
+ import { a as insertAfterFrontmatter, c as noopLogger, i as serializeIssue, n as parseIssue, o as parseMarkdown, r as parseMarkdownWithFrontmatter, s as stripFrontmatter, t as VERSION$1 } from "./src-BK_EF6mk.mjs";
3
3
  import { a as parseYamlWithConflictDetection, d as PAGINATION_LINE_THRESHOLD, f as PARENT_CONTEXT_MAX_LINES, l as comparisonChain, n as detectDuplicateYamlKeys, o as sortKeys, s as stringifyYaml, u as ordering } from "./yaml-utils-BPy991by.mjs";
4
- import { A as isValidWorkspaceName, C as TBD_SHORTCUTS_STANDARD, D as WORKTREE_DIR, E as WORKSPACES_DIR, M as resolveDataSyncDir, O as WORKTREE_DIR_NAME, S as TBD_GUIDELINES_DIR, T as TBD_TEMPLATES_DIR, _ as DEFAULT_SHORTCUT_PATHS, a as isInitialized, b as TBD_DIR, c as readConfigWithMigration, d as writeConfig, g as DEFAULT_GUIDELINES_PATHS, h as DATA_SYNC_DIR_NAME, i as initConfig, j as resolveAtticDir, k as getWorkspaceDir, l as readLocalState, m as DATA_SYNC_DIR, n as findTbdRoot, o as markWelcomeSeen, p as CHARS_PER_TOKEN, r as hasSeenWelcome, s as readConfig, u as updateLocalState, v as DEFAULT_TEMPLATE_PATHS, w as TBD_SHORTCUTS_SYSTEM, x as TBD_DOCS_DIR, y as SYNC_BRANCH } from "./config-B38rbI9u.mjs";
4
+ import { A as getWorkspaceDir, C as TBD_GUIDELINES_DIR, D as WORKSPACES_DIR, E as TBD_TEMPLATES_DIR, M as resolveAtticDir, N as resolveDataSyncDir, O as WORKTREE_DIR, S as TBD_DOCS_DIR, T as TBD_SHORTCUTS_SYSTEM, _ as DEFAULT_GUIDELINES_PATHS, a as isInitialized, b as SYNC_BRANCH, c as readConfigWithMigration, d as writeConfig, g as DATA_SYNC_DIR_NAME, h as DATA_SYNC_DIR, i as initConfig, j as isValidWorkspaceName, k as WORKTREE_DIR_NAME, l as readLocalState, m as CHARS_PER_TOKEN, n as findTbdRoot, o as markWelcomeSeen, p as CURRENT_FORMAT, r as hasSeenWelcome, s as readConfig, u as updateLocalState, v as DEFAULT_SHORTCUT_PATHS, w as TBD_SHORTCUTS_STANDARD, x as TBD_DIR, y as DEFAULT_TEMPLATE_PATHS } from "./config-DVap9omo.mjs";
5
5
  import { _ as formatDisplayId, a as hasShortId, b as normalizeIssueId, c as parseIdMappingFromYaml, d as resolveToInternalId, f as saveIdMapping, g as formatDebugId, h as extractUlidFromInternalId, i as generateUniqueShortId, l as reconcileMappings, m as extractShortId, o as loadIdMapping, p as extractPrefix, s as mergeIdMappings, t as addIdMapping, u as resolveIdMappingConflicts, v as generateInternalId, x as validateIssueId, y as makeInternalId } from "./id-mapping-CqrrLgeX.mjs";
6
6
  import { createRequire } from "node:module";
7
7
  import { ZodError } from "zod";
@@ -5845,9 +5845,10 @@ function renderFooter(suggestions, colors) {
5845
5845
  /**
5846
5846
  * Centralized path constants and utilities for coding agent integrations.
5847
5847
  *
5848
- * IMPORTANT: All tbd integration files (hooks, settings, skills) are installed
5849
- * to PROJECT-LOCAL directories (.claude/, AGENTS.md) ONLY. We do NOT install to
5850
- * global/user directories (~/.claude/).
5848
+ * IMPORTANT: All tbd integration files (skills, hooks, settings, scripts) are
5849
+ * installed to PROJECT-LOCAL directories (.agents/, .claude/, .codex/,
5850
+ * scripts/agent/, AGENTS.md) ONLY. We do NOT install to global/user directories
5851
+ * (~/.claude/, ~/.codex/, ~/.agents/).
5851
5852
  *
5852
5853
  * This file defines all path constants in one place to:
5853
5854
  * 1. Ensure consistency across the codebase
@@ -5855,6 +5856,19 @@ function renderFooter(suggestions, colors) {
5855
5856
  * 3. Simplify future changes to path conventions
5856
5857
  */
5857
5858
  /**
5859
+ * Format version stamped into generated agent integration artifacts (e.g. the
5860
+ * AGENTS.md managed block's begin marker: `... format=f03 surface=...`).
5861
+ *
5862
+ * UNIFIED with the `.tbd/` directory format (`tbd_format`): there is one format
5863
+ * code for all tbd-managed surfaces, sourced from `tbd-format.ts` (the single
5864
+ * source of truth). Bump `CURRENT_FORMAT` there when any managed surface — config
5865
+ * schema OR a generated agent surface — changes shape. A marked AGENTS.md block
5866
+ * with no `format=` field predates this and is treated as `f01`; a running tbd
5867
+ * that finds a HIGHER format than it knows refuses to overwrite it and tells the
5868
+ * user to upgrade tbd.
5869
+ */
5870
+ const AGENT_INTEGRATION_FORMAT = CURRENT_FORMAT;
5871
+ /**
5858
5872
  * Relative path to Claude Code settings file from project root.
5859
5873
  * This is where hooks are configured.
5860
5874
  */
@@ -5888,11 +5902,33 @@ const TBD_CLOSING_REMINDER_REL = ".claude/hooks/tbd-closing-reminder.sh";
5888
5902
  */
5889
5903
  const GH_CLI_SCRIPT_REL = ".claude/scripts/ensure-gh-cli.sh";
5890
5904
  /**
5905
+ * Canonical portable project Agent Skill, scanned by Codex, Gemini CLI, Cursor,
5906
+ * GitHub Copilot, Amp, OpenCode, pi, and other Agent Skills clients.
5907
+ */
5908
+ const AGENTS_SKILL_REL = ".agents/skills/tbd/SKILL.md";
5909
+ /**
5910
+ * Repository distribution copy of the skill, for skills.sh-style installers
5911
+ * (`npx skills add`) and direct GitHub browsing.
5912
+ */
5913
+ const SKILLS_DIST_REL = "skills/tbd/SKILL.md";
5914
+ /**
5891
5915
  * Relative path to AGENTS.md file from project root.
5892
5916
  * Used by Codex, Factory.ai, Cursor (v1.6+), and other compatible tools.
5893
5917
  */
5894
5918
  const AGENTS_MD_REL = "AGENTS.md";
5895
5919
  /**
5920
+ * Codex project-local config/hook directory.
5921
+ */
5922
+ const CODEX_DIR_REL = ".codex";
5923
+ /**
5924
+ * Codex project-local hooks file (Claude-compatible event schema).
5925
+ */
5926
+ const CODEX_HOOKS_REL = ".codex/hooks.json";
5927
+ /**
5928
+ * Codex project-local config; may also carry an inline `[hooks]` table.
5929
+ */
5930
+ const CODEX_CONFIG_REL = ".codex/config.toml";
5931
+ /**
5896
5932
  * Global Claude Code directory in user's home.
5897
5933
  * Used ONLY for detecting if Claude Code is installed (for agent detection).
5898
5934
  * All installations are project-local.
@@ -5926,6 +5962,31 @@ function getAgentsMdPath(projectRoot) {
5926
5962
  return join(projectRoot, AGENTS_MD_REL);
5927
5963
  }
5928
5964
  /**
5965
+ * Get the three SKILL.md targets: the portable Agent Skills install, the Claude
5966
+ * Code mirror, and the committed distribution copy.
5967
+ *
5968
+ * @param projectRoot - The project root directory (containing .tbd/)
5969
+ */
5970
+ function getAgentSkillPaths(projectRoot) {
5971
+ return {
5972
+ portable: join(projectRoot, AGENTS_SKILL_REL),
5973
+ claudeMirror: join(projectRoot, CLAUDE_SKILL_REL),
5974
+ distribution: join(projectRoot, SKILLS_DIST_REL)
5975
+ };
5976
+ }
5977
+ /**
5978
+ * Get project-local Codex config/hook paths.
5979
+ *
5980
+ * @param projectRoot - The project root directory
5981
+ */
5982
+ function getCodexPaths(projectRoot) {
5983
+ return {
5984
+ dir: join(projectRoot, CODEX_DIR_REL),
5985
+ hooks: join(projectRoot, CODEX_HOOKS_REL),
5986
+ config: join(projectRoot, CODEX_CONFIG_REL)
5987
+ };
5988
+ }
5989
+ /**
5929
5990
  * Display path for Claude Code settings in status/doctor output.
5930
5991
  */
5931
5992
  const CLAUDE_SETTINGS_DISPLAY = "./.claude/settings.json";
@@ -5933,6 +5994,14 @@ const CLAUDE_SETTINGS_DISPLAY = "./.claude/settings.json";
5933
5994
  * Display path for AGENTS.md in status/doctor output.
5934
5995
  */
5935
5996
  const AGENTS_MD_DISPLAY = "./AGENTS.md";
5997
+ /**
5998
+ * Display path for the portable Agent Skill in status/doctor output.
5999
+ */
6000
+ const AGENTS_SKILL_DISPLAY = "./.agents/skills/tbd/SKILL.md";
6001
+ /**
6002
+ * Display path for the Codex hooks file in status/doctor output.
6003
+ */
6004
+ const CODEX_HOOKS_DISPLAY = "./.codex/hooks.json";
5936
6005
 
5937
6006
  //#endregion
5938
6007
  //#region src/cli/commands/status.ts
@@ -5970,10 +6039,14 @@ var StatusHandler = class extends BaseCommand {
5970
6039
  worktree_healthy: null,
5971
6040
  workspaces: [],
5972
6041
  integrations: {
6042
+ portable_skill: false,
6043
+ portable_skill_path: AGENTS_SKILL_DISPLAY,
5973
6044
  claude_code: false,
5974
6045
  claude_code_path: CLAUDE_SETTINGS_DISPLAY,
5975
6046
  codex: false,
5976
- codex_path: AGENTS_MD_DISPLAY
6047
+ codex_path: AGENTS_MD_DISPLAY,
6048
+ codex_hooks: false,
6049
+ codex_hooks_path: CODEX_HOOKS_DISPLAY
5977
6050
  }
5978
6051
  };
5979
6052
  const gitInfo = await this.checkGitRepo();
@@ -6041,11 +6114,23 @@ var StatusHandler = class extends BaseCommand {
6041
6114
  const claudePaths = getClaudePaths(projectRoot);
6042
6115
  const agentsPath = getAgentsMdPath(projectRoot);
6043
6116
  const result = {
6117
+ portable_skill: false,
6118
+ portable_skill_path: AGENTS_SKILL_DISPLAY,
6044
6119
  claude_code: false,
6045
6120
  claude_code_path: CLAUDE_SETTINGS_DISPLAY,
6046
6121
  codex: false,
6047
- codex_path: AGENTS_MD_DISPLAY
6122
+ codex_path: AGENTS_MD_DISPLAY,
6123
+ codex_hooks: false,
6124
+ codex_hooks_path: CODEX_HOOKS_DISPLAY
6048
6125
  };
6126
+ try {
6127
+ await access(getAgentSkillPaths(projectRoot).portable);
6128
+ result.portable_skill = true;
6129
+ } catch {}
6130
+ try {
6131
+ await access(getCodexPaths(projectRoot).hooks);
6132
+ result.codex_hooks = true;
6133
+ } catch {}
6049
6134
  try {
6050
6135
  await access(claudePaths.settings);
6051
6136
  const content = await readFile(claudePaths.settings, "utf-8");
@@ -6094,15 +6179,28 @@ var StatusHandler = class extends BaseCommand {
6094
6179
  remote: data.remote,
6095
6180
  displayPrefix: data.display_prefix
6096
6181
  }, colors);
6097
- if (renderIntegrationsSection([{
6098
- name: "Claude Code hooks",
6099
- installed: data.integrations.claude_code,
6100
- path: data.integrations.claude_code_path
6101
- }, {
6102
- name: "Codex AGENTS.md",
6103
- installed: data.integrations.codex,
6104
- path: data.integrations.codex_path
6105
- }], colors)) {
6182
+ if (renderIntegrationsSection([
6183
+ {
6184
+ name: "Portable Agent Skill",
6185
+ installed: data.integrations.portable_skill,
6186
+ path: data.integrations.portable_skill_path
6187
+ },
6188
+ {
6189
+ name: "Claude Code hooks",
6190
+ installed: data.integrations.claude_code,
6191
+ path: data.integrations.claude_code_path
6192
+ },
6193
+ {
6194
+ name: "Codex AGENTS.md",
6195
+ installed: data.integrations.codex,
6196
+ path: data.integrations.codex_path
6197
+ },
6198
+ {
6199
+ name: "Codex hooks",
6200
+ installed: data.integrations.codex_hooks,
6201
+ path: data.integrations.codex_hooks_path
6202
+ }
6203
+ ], colors)) {
6106
6204
  console.log("");
6107
6205
  console.log(`Run ${colors.bold("tbd setup auto")} to configure detected agents`);
6108
6206
  }
@@ -6442,8 +6540,10 @@ var DoctorHandler = class extends BaseCommand {
6442
6540
  healthChecks.push(await this.checkCloneScenarios());
6443
6541
  healthChecks.push(await this.checkSyncConsistency());
6444
6542
  const integrationChecks = [];
6543
+ integrationChecks.push(await this.checkPortableSkill());
6445
6544
  integrationChecks.push(await this.checkClaudeSkill());
6446
6545
  integrationChecks.push(await this.checkCodexAgents());
6546
+ integrationChecks.push(await this.checkCodexHooks());
6447
6547
  const allChecks = [...healthChecks, ...integrationChecks];
6448
6548
  const allOk = allChecks.every((c) => c.status === "ok");
6449
6549
  const hasFixable = allChecks.some((c) => c.fixable && c.status !== "ok");
@@ -6864,7 +6964,7 @@ var DoctorHandler = class extends BaseCommand {
6864
6964
  const { parseIdMappingFromYaml, mergeIdMappings } = await import("./id-mapping-Ctfl_nc1.mjs");
6865
6965
  let historicalMapping;
6866
6966
  try {
6867
- const syncBranch = (await import("./config-C0ITTrtc.mjs").then((m) => m.readConfig(this.cwd))).sync.branch;
6967
+ const syncBranch = (await import("./config-BPHcePSm.mjs").then((m) => m.readConfig(this.cwd))).sync.branch;
6868
6968
  const logArgs = ["log", "--format=%H"];
6869
6969
  if (maxHistory > 0) logArgs.push(`-${maxHistory}`);
6870
6970
  logArgs.push(syncBranch, "--", `${DATA_SYNC_DIR}/mappings/ids.yml`);
@@ -6907,6 +7007,25 @@ var DoctorHandler = class extends BaseCommand {
6907
7007
  suggestion: "Run: tbd doctor --fix to create missing mappings"
6908
7008
  };
6909
7009
  }
7010
+ async checkPortableSkill() {
7011
+ const { portable } = getAgentSkillPaths(this.cwd);
7012
+ try {
7013
+ await access(portable);
7014
+ return {
7015
+ name: "Portable Agent Skill",
7016
+ status: "ok",
7017
+ path: AGENTS_SKILL_REL
7018
+ };
7019
+ } catch {
7020
+ return {
7021
+ name: "Portable Agent Skill",
7022
+ status: "warn",
7023
+ message: "not installed",
7024
+ path: AGENTS_SKILL_REL,
7025
+ suggestion: "Run: tbd setup --auto"
7026
+ };
7027
+ }
7028
+ }
6910
7029
  async checkClaudeSkill() {
6911
7030
  const claudePaths = getClaudePaths(this.cwd);
6912
7031
  try {
@@ -6926,6 +7045,25 @@ var DoctorHandler = class extends BaseCommand {
6926
7045
  };
6927
7046
  }
6928
7047
  }
7048
+ async checkCodexHooks() {
7049
+ const codexPaths = getCodexPaths(this.cwd);
7050
+ try {
7051
+ await access(codexPaths.hooks);
7052
+ return {
7053
+ name: "Codex hooks",
7054
+ status: "ok",
7055
+ path: CODEX_HOOKS_REL
7056
+ };
7057
+ } catch {
7058
+ return {
7059
+ name: "Codex hooks",
7060
+ status: "warn",
7061
+ message: "not installed",
7062
+ path: CODEX_HOOKS_REL,
7063
+ suggestion: "Run: tbd setup --auto"
7064
+ };
7065
+ }
7066
+ }
6929
7067
  async checkCodexAgents() {
6930
7068
  const agentsPath = getAgentsMdPath(this.cwd);
6931
7069
  try {
@@ -8823,7 +8961,7 @@ async function loadSkillContent() {
8823
8961
  const docsDir = join(dirname(fileURLToPath(import.meta.url)), "..", "..", "..", "docs");
8824
8962
  const headerPath = join(docsDir, "install", "claude-header.md");
8825
8963
  const skillPath = join(docsDir, "shortcuts", "system", "skill-baseline.md");
8826
- return await readFile(headerPath, "utf-8") + await readFile(skillPath, "utf-8");
8964
+ return await readFile(headerPath, "utf-8") + stripFrontmatter(await readFile(skillPath, "utf-8"));
8827
8965
  } catch {
8828
8966
  throw new Error("SKILL.md content file not found. Please rebuild the CLI.");
8829
8967
  }
@@ -9106,7 +9244,7 @@ var SkillHandler = class extends BaseCommand {
9106
9244
  */
9107
9245
  async composeFullSkill() {
9108
9246
  const header = await loadDocContent("install/claude-header.md");
9109
- const baseSkill = await loadDocContent("shortcuts/system/skill-baseline.md");
9247
+ const baseSkill = stripFrontmatter(await loadDocContent("shortcuts/system/skill-baseline.md"));
9110
9248
  const directory = await this.getShortcutDirectory();
9111
9249
  let result = header + baseSkill;
9112
9250
  if (directory) result = result.trimEnd() + "\n\n" + directory;
@@ -9863,16 +10001,89 @@ async function getShortcutDirectory(quiet = false) {
9863
10001
  return generateShortcutDirectory(shortcuts, guidelines);
9864
10002
  }
9865
10003
  /**
9866
- * Get the tbd section content for AGENTS.md (Codex integration).
9867
- * Loads from SKILL.md, strips frontmatter, and wraps in TBD INTEGRATION markers.
10004
+ * DO NOT EDIT marker inserted after the frontmatter of every generated SKILL.md.
10005
+ * Formatted to match flowmark output.
10006
+ */
10007
+ const SKILL_DO_NOT_EDIT_MARKER = "<!-- DO NOT EDIT: Generated by tbd setup.\nRun 'tbd setup' to update.\n-->";
10008
+ /**
10009
+ * Build the full generated SKILL.md payload: the bundled skill content with the
10010
+ * shortcut/guideline directory appended and a DO NOT EDIT marker after the
10011
+ * frontmatter. This is the single source for every skill surface (the portable
10012
+ * .agents/skills install and the .claude/skills mirror) so they stay identical.
9868
10013
  *
9869
- * @param quiet - If true, suppress auto-sync output (default: false)
10014
+ * @param quiet - If true, suppress auto-sync output.
9870
10015
  */
9871
- async function getCodexTbdSection(quiet = false) {
9872
- let content = stripFrontmatter(await loadSkillContent());
10016
+ async function buildSkillPayload(quiet = false) {
10017
+ let skillContent = await loadSkillContent();
9873
10018
  const directory = await getShortcutDirectory(quiet);
9874
- if (directory) content = content.trimEnd() + "\n\n" + directory + "\n";
9875
- return `<!-- BEGIN TBD INTEGRATION -->\n${content}<!-- END TBD INTEGRATION -->\n`;
10019
+ if (directory) skillContent = skillContent.trimEnd() + "\n\n" + directory;
10020
+ skillContent = insertAfterFrontmatter(skillContent, SKILL_DO_NOT_EDIT_MARKER);
10021
+ return skillContent.trimEnd() + "\n";
10022
+ }
10023
+ /**
10024
+ * Write a generated SKILL.md payload to a target path, creating parent dirs.
10025
+ */
10026
+ async function writeSkillFile(targetPath, payload) {
10027
+ await mkdir(dirname(targetPath), { recursive: true });
10028
+ await writeFile(targetPath, payload);
10029
+ }
10030
+ /**
10031
+ * AGENTS.md managed-block markers. `CODEX_BEGIN_MARKER` is the stable PREFIX of
10032
+ * the begin line — the metadata (`format=fNN surface=agents-md`) follows it on the
10033
+ * same line, e.g. `<!-- BEGIN TBD INTEGRATION format=f02 surface=agents-md -->`.
10034
+ * Cleanup/upgrade code matches on this prefix so it finds both legacy
10035
+ * (`<!-- BEGIN TBD INTEGRATION -->`) and current marked blocks.
10036
+ */
10037
+ const CODEX_BEGIN_MARKER = "<!-- BEGIN TBD INTEGRATION";
10038
+ const CODEX_END_MARKER = "<!-- END TBD INTEGRATION -->";
10039
+ /** The full begin marker line for newly generated blocks. */
10040
+ const CODEX_BEGIN_LINE = `${CODEX_BEGIN_MARKER} format=${AGENT_INTEGRATION_FORMAT} surface=agents-md -->`;
10041
+ /** Numeric value of an `fNN` format string, for ordering comparisons. */
10042
+ function formatToNumber(format) {
10043
+ return Number.parseInt(format.replace(/^f/, ""), 10);
10044
+ }
10045
+ /**
10046
+ * Read the integration format (`fNN`) stamped in a generated artifact's begin
10047
+ * marker. Returns `f01` for a legacy marked block with no `format=` field, or
10048
+ * null when there is no tbd-managed block at all.
10049
+ */
10050
+ function parseIntegrationFormat(content) {
10051
+ const match = /format=f(\d+)/.exec(content);
10052
+ if (match?.[1]) return `f${match[1]}`;
10053
+ return content.includes(CODEX_BEGIN_MARKER) ? "f01" : null;
10054
+ }
10055
+ /**
10056
+ * Forward-compatibility guard. If a generated artifact was written by a NEWER
10057
+ * tbd than this one understands, refuse to rewrite it and tell the user to
10058
+ * upgrade tbd — overwriting would downgrade a newer managed format. This is what
10059
+ * makes pinning safe on a team: an older tbd fails loudly instead of clobbering.
10060
+ */
10061
+ function assertNotNewerFormat(content, artifact) {
10062
+ const format = parseIntegrationFormat(content);
10063
+ if (format !== null && formatToNumber(format) > formatToNumber(AGENT_INTEGRATION_FORMAT)) throw new CLIError(`${artifact} was generated by a newer tbd (integration format ${format}; this tbd supports up to ${AGENT_INTEGRATION_FORMAT}).\nUpgrade tbd to manage it: npm install -g get-tbd@latest`);
10064
+ }
10065
+ /**
10066
+ * Get the tbd managed block for AGENTS.md.
10067
+ *
10068
+ * This is a COMPACT always-on bootstrap, not a copy of the full skill: it names
10069
+ * tbd, states the operating rule, and points to the CLI commands that provide
10070
+ * progressive disclosure (`tbd prime`, `tbd skill`, `tbd shortcut/guidelines
10071
+ * --list`). The full skill body lives in the SKILL.md surfaces, not here, so the
10072
+ * block stays well under the AGENTS.md prompt-budget guidance.
10073
+ */
10074
+ function getCodexTbdSection() {
10075
+ return `${CODEX_BEGIN_LINE}\n## tbd
10076
+
10077
+ This repository uses **tbd** for git-native issue tracking (beads), spec-driven
10078
+ planning, and on-demand engineering guidelines.
10079
+ As the agent, you operate tbd on the user’s behalf — translate their requests into tbd
10080
+ actions rather than telling them to run commands.
10081
+
10082
+ - Run \`tbd prime\` to load current project state and the full tbd workflow.
10083
+ - Run \`tbd skill\` for the complete reusable tbd skill instructions.
10084
+ - Run \`tbd shortcut --list\` and \`tbd guidelines --list\` for on-demand resources.
10085
+ - Track all work as beads: \`tbd create\`, \`tbd ready\`, \`tbd close\`, and \`tbd sync\`.
10086
+ \n${CODEX_END_MARKER}\n`;
9876
10087
  }
9877
10088
  /**
9878
10089
  * Script to ensure tbd CLI is installed and run tbd prime.
@@ -9884,82 +10095,32 @@ async function getCodexTbdSection(quiet = false) {
9884
10095
  * tbd-session.sh --brief # Ensure tbd + run tbd prime --brief (for PreCompact)
9885
10096
  */
9886
10097
  const TBD_SESSION_SCRIPT = `#!/bin/bash
9887
- # Ensure tbd CLI is installed and run tbd prime for Claude Code sessions
9888
- # Installed by: tbd setup --auto
9889
- # This script runs on SessionStart and PreCompact
9890
-
9891
- # Get npm global bin directory (if npm is available)
9892
- NPM_GLOBAL_BIN=""
9893
- if command -v npm &> /dev/null; then
9894
- NPM_PREFIX=$(npm config get prefix 2>/dev/null)
9895
- if [ -n "$NPM_PREFIX" ] && [ -d "$NPM_PREFIX/bin" ]; then
9896
- NPM_GLOBAL_BIN="$NPM_PREFIX/bin"
9897
- fi
9898
- fi
9899
-
9900
- # Add common binary locations to PATH (persists for entire script)
9901
- # Include npm global bin if found
9902
- export PATH="$NPM_GLOBAL_BIN:$HOME/.local/bin:$HOME/bin:/usr/local/bin:$PATH"
9903
-
9904
- # Function to ensure tbd is available
9905
- ensure_tbd() {
9906
- # Check if tbd is already installed
9907
- if command -v tbd &> /dev/null; then
9908
- return 0
9909
- fi
10098
+ # Ensure the tbd CLI is available and run \`tbd prime\`.
10099
+ # Installed by: tbd setup --auto. Runs on SessionStart and PreCompact.
10100
+ #
10101
+ # Local-first, then a VERSION-PINNED zero-install fallback. Pinning is both a
10102
+ # supply-chain control (an unpinned runner re-resolves to latest on every run
10103
+ # and bypasses any cool-off) and a consistency control (every teammate and agent
10104
+ # runs the same tbd version).
9910
10105
 
9911
- echo "[tbd] CLI not found, installing..."
10106
+ # Prefer common local bin locations.
10107
+ export PATH="$HOME/.local/bin:$HOME/bin:/usr/local/bin:$PATH"
9912
10108
 
9913
- # Try npm first (most common for Node.js tools)
9914
- if command -v npm &> /dev/null; then
9915
- echo "[tbd] Installing via npm..."
9916
- npm install -g get-tbd 2>/dev/null || {
9917
- # If global install fails (permissions), try local install
9918
- echo "[tbd] Global npm install failed, trying user install..."
9919
- mkdir -p ~/.local/bin
9920
- npm install --prefix ~/.local get-tbd
9921
- # Create symlink if needed
9922
- if [ -f ~/.local/node_modules/.bin/tbd ]; then
9923
- ln -sf ~/.local/node_modules/.bin/tbd ~/.local/bin/tbd
9924
- fi
9925
- }
9926
- elif command -v pnpm &> /dev/null; then
9927
- echo "[tbd] Installing via pnpm..."
9928
- pnpm add -g get-tbd
9929
- elif command -v yarn &> /dev/null; then
9930
- echo "[tbd] Installing via yarn..."
9931
- yarn global add get-tbd
9932
- else
9933
- echo "[tbd] ERROR: No package manager found (npm, pnpm, or yarn required)"
9934
- echo "[tbd] Please install Node.js and npm, then run: npm install -g get-tbd"
9935
- return 1
9936
- fi
9937
-
9938
- # Verify installation
9939
- if command -v tbd &> /dev/null; then
9940
- echo "[tbd] Successfully installed to $(which tbd)"
9941
- return 0
9942
- else
9943
- echo "[tbd] WARNING: tbd installed but not found in PATH"
9944
- echo "[tbd] Checking common locations..."
9945
- # Try to find and add to path (include npm global bin)
9946
- for dir in "$NPM_GLOBAL_BIN" ~/.local/bin ~/.local/node_modules/.bin /usr/local/bin; do
9947
- if [ -n "$dir" ] && [ -x "$dir/tbd" ]; then
9948
- export PATH="$dir:$PATH"
9949
- echo "[tbd] Found at $dir/tbd"
9950
- return 0
9951
- fi
9952
- done
9953
- echo "[tbd] Could not locate tbd after installation"
9954
- return 1
9955
- fi
9956
- }
10109
+ # Local-first: use tbd if it is already on PATH.
10110
+ if command -v tbd &> /dev/null; then
10111
+ tbd prime "$@"
10112
+ exit $?
10113
+ fi
9957
10114
 
9958
- # Main
9959
- ensure_tbd || exit 1
10115
+ # Pinned zero-install fallback. Never use an unpinned runner here.
10116
+ if command -v npx &> /dev/null; then
10117
+ npx --yes get-tbd@${VERSION} prime "$@"
10118
+ exit $?
10119
+ fi
9960
10120
 
9961
- # Run tbd prime with any passed arguments (e.g., --brief for PreCompact)
9962
- tbd prime "$@"
10121
+ echo "[tbd] tbd CLI not found and npx is unavailable."
10122
+ echo "[tbd] Install it with: npm install -g get-tbd@${VERSION}"
10123
+ exit 1
9963
10124
  `;
9964
10125
  /**
9965
10126
  * Claude Code session hooks configuration.
@@ -10049,22 +10210,14 @@ async function loadBundledScript(name) {
10049
10210
  throw new Error(`Bundled script not found: ${name}`);
10050
10211
  }
10051
10212
  /**
10052
- * AGENTS.md integration markers for Codex/Factory.ai
10053
- * Content is now generated dynamically from SKILL.md via getCodexTbdSection()
10054
- */
10055
- const CODEX_BEGIN_MARKER = "<!-- BEGIN TBD INTEGRATION -->";
10056
- const CODEX_END_MARKER = "<!-- END TBD INTEGRATION -->";
10057
- /**
10058
10213
  * Generate a new AGENTS.md file with tbd integration.
10059
- *
10060
- * @param quiet - If true, suppress auto-sync output (default: false)
10061
10214
  */
10062
- async function getCodexNewAgentsFile(quiet = false) {
10215
+ function getCodexNewAgentsFile() {
10063
10216
  return `# Project Instructions for AI Agents
10064
10217
 
10065
10218
  This file provides instructions and context for AI coding agents working on this project.
10066
10219
 
10067
- ${await getCodexTbdSection(quiet)}
10220
+ ${getCodexTbdSection()}
10068
10221
  ## Build & Test
10069
10222
 
10070
10223
  _Add your build and test commands here_
@@ -10085,6 +10238,54 @@ _Add your project-specific conventions here_
10085
10238
  `;
10086
10239
  }
10087
10240
  /**
10241
+ * Codex project-local script paths (relative to repo root). Codex hooks
10242
+ * reference ONLY these `.codex/` paths, never `.claude/`, so Codex setup stays
10243
+ * independent of Claude Code setup.
10244
+ */
10245
+ const CODEX_SESSION_SCRIPT_REL = ".codex/tbd-session.sh";
10246
+ const CODEX_CLOSING_REMINDER_REL = ".codex/tbd-closing-reminder.sh";
10247
+ const CODEX_GH_CLI_SCRIPT_REL = ".codex/ensure-gh-cli.sh";
10248
+ /**
10249
+ * Build the Codex hooks.json content. Codex uses the same lifecycle event
10250
+ * schema as Claude Code (command handlers), so tbd's hooks map almost 1:1:
10251
+ * SessionStart and PreCompact run `tbd prime`, PostToolUse reminds about sync
10252
+ * after `git push`, and (when enabled) a second SessionStart entry ensures gh.
10253
+ */
10254
+ function getCodexHooksConfig(useGhCli) {
10255
+ const sessionStart = [{
10256
+ matcher: "",
10257
+ hooks: [{
10258
+ type: "command",
10259
+ command: `bash ${CODEX_SESSION_SCRIPT_REL}`
10260
+ }]
10261
+ }];
10262
+ if (useGhCli) sessionStart.push({
10263
+ matcher: "",
10264
+ hooks: [{
10265
+ type: "command",
10266
+ command: `bash ${CODEX_GH_CLI_SCRIPT_REL}`,
10267
+ timeout: 120
10268
+ }]
10269
+ });
10270
+ return { hooks: {
10271
+ SessionStart: sessionStart,
10272
+ PreCompact: [{
10273
+ matcher: "",
10274
+ hooks: [{
10275
+ type: "command",
10276
+ command: `bash ${CODEX_SESSION_SCRIPT_REL} --brief`
10277
+ }]
10278
+ }],
10279
+ PostToolUse: [{
10280
+ matcher: "Bash",
10281
+ hooks: [{
10282
+ type: "command",
10283
+ command: `bash ${CODEX_CLOSING_REMINDER_REL}`
10284
+ }]
10285
+ }]
10286
+ } };
10287
+ }
10288
+ /**
10088
10289
  * Legacy script patterns to clean up from .claude/scripts/
10089
10290
  * These were used in older versions of tbd before hooks moved to `tbd prime`
10090
10291
  */
@@ -10345,13 +10546,7 @@ var SetupClaudeHandler = class extends BaseCommand {
10345
10546
  await writeFile(claudePaths.closingReminder, TBD_CLOSE_PROTOCOL_SCRIPT);
10346
10547
  await chmod(claudePaths.closingReminder, 493);
10347
10548
  this.output.success("Installed sync reminder hook script");
10348
- await mkdir(dirname(skillPath), { recursive: true });
10349
- let skillContent = await loadSkillContent();
10350
- const directory = await getShortcutDirectory(this.ctx.quiet);
10351
- if (directory) skillContent = skillContent.trimEnd() + "\n\n" + directory;
10352
- skillContent = insertAfterFrontmatter(skillContent, "<!-- DO NOT EDIT: Generated by tbd setup.\nRun 'tbd setup' to update.\n-->");
10353
- skillContent = skillContent.trimEnd() + "\n";
10354
- await writeFile(skillPath, skillContent);
10549
+ await writeSkillFile(skillPath, await buildSkillPayload(this.ctx.quiet));
10355
10550
  this.output.success("Installed skill file");
10356
10551
  this.output.info(` ${skillPath}`);
10357
10552
  this.output.info("");
@@ -10384,16 +10579,93 @@ var SetupCodexHandler = class extends BaseCommand {
10384
10579
  this.projectDir = dir;
10385
10580
  }
10386
10581
  async run(options) {
10387
- const agentsPath = join(this.projectDir ?? process.cwd(), "AGENTS.md");
10582
+ const cwd = this.projectDir ?? process.cwd();
10583
+ const agentsPath = join(cwd, "AGENTS.md");
10388
10584
  if (options.check) {
10389
10585
  await this.checkCodexSetup(agentsPath);
10390
10586
  return;
10391
10587
  }
10392
10588
  if (options.remove) {
10393
10589
  await this.removeCodexSection(agentsPath);
10590
+ await this.removeCodexHooks(cwd);
10394
10591
  return;
10395
10592
  }
10396
10593
  await this.installCodexSection(agentsPath);
10594
+ await this.installCodexHooks(cwd);
10595
+ }
10596
+ /**
10597
+ * Read the use_gh_cli setting; defaults to true (so fresh setup installs it).
10598
+ */
10599
+ async getUseGhCliSetting(cwd) {
10600
+ try {
10601
+ const tbdRoot = await findTbdRoot(cwd);
10602
+ if (!tbdRoot) return true;
10603
+ return (await readConfig(tbdRoot)).settings.use_gh_cli ?? true;
10604
+ } catch {
10605
+ return true;
10606
+ }
10607
+ }
10608
+ /**
10609
+ * Install Codex lifecycle hooks: writes .codex/ scripts and a .codex/hooks.json
10610
+ * (merged idempotently with any user hooks). Scripts reuse the same bodies as
10611
+ * the Claude install but live under .codex/ so Codex never references .claude/.
10612
+ */
10613
+ async installCodexHooks(cwd) {
10614
+ if (this.checkDryRun("Would install Codex hooks", { path: "./.codex/hooks.json" })) return;
10615
+ const codexPaths = getCodexPaths(cwd);
10616
+ await mkdir(codexPaths.dir, { recursive: true });
10617
+ const useGhCli = await this.getUseGhCliSetting(cwd);
10618
+ await writeFile(join(cwd, CODEX_SESSION_SCRIPT_REL), TBD_SESSION_SCRIPT);
10619
+ await chmod(join(cwd, CODEX_SESSION_SCRIPT_REL), 493);
10620
+ await writeFile(join(cwd, CODEX_CLOSING_REMINDER_REL), TBD_CLOSE_PROTOCOL_SCRIPT);
10621
+ await chmod(join(cwd, CODEX_CLOSING_REMINDER_REL), 493);
10622
+ if (useGhCli) {
10623
+ const ghScriptContent = await loadBundledScript("ensure-gh-cli.sh");
10624
+ await writeFile(join(cwd, CODEX_GH_CLI_SCRIPT_REL), ghScriptContent);
10625
+ await chmod(join(cwd, CODEX_GH_CLI_SCRIPT_REL), 493);
10626
+ } else await rm(join(cwd, CODEX_GH_CLI_SCRIPT_REL), { force: true });
10627
+ let existing = {};
10628
+ try {
10629
+ existing = JSON.parse(await readFile(codexPaths.hooks, "utf-8"));
10630
+ } catch {}
10631
+ const isTbdOwned = (entry) => {
10632
+ return (entry.hooks ?? []).some((h) => h.command?.includes(".codex/"));
10633
+ };
10634
+ const merged = { ...existing.hooks ?? {} };
10635
+ const tbdHooks = getCodexHooksConfig(useGhCli).hooks;
10636
+ for (const [event, entries] of Object.entries(tbdHooks)) merged[event] = [...(merged[event] ?? []).filter((e) => !isTbdOwned(e)), ...entries];
10637
+ await writeFile(codexPaths.hooks, JSON.stringify({
10638
+ ...existing,
10639
+ hooks: merged
10640
+ }, null, 2) + "\n");
10641
+ this.output.success("Installed Codex hooks (.codex/hooks.json)");
10642
+ }
10643
+ /**
10644
+ * Remove tbd-owned Codex hook entries and scripts, preserving user hooks.
10645
+ */
10646
+ async removeCodexHooks(cwd) {
10647
+ const codexPaths = getCodexPaths(cwd);
10648
+ try {
10649
+ const existing = JSON.parse(await readFile(codexPaths.hooks, "utf-8"));
10650
+ const hooks = existing.hooks ?? {};
10651
+ for (const event of Object.keys(hooks)) {
10652
+ const kept = (hooks[event] ?? []).filter((entry) => {
10653
+ return !(entry.hooks ?? []).some((h) => h.command?.includes(".codex/"));
10654
+ });
10655
+ if (kept.length === 0) delete hooks[event];
10656
+ else hooks[event] = kept;
10657
+ }
10658
+ if (Object.keys(hooks).length === 0) await rm(codexPaths.hooks, { force: true });
10659
+ else await writeFile(codexPaths.hooks, JSON.stringify({
10660
+ ...existing,
10661
+ hooks
10662
+ }, null, 2) + "\n");
10663
+ } catch {}
10664
+ for (const rel of [
10665
+ CODEX_SESSION_SCRIPT_REL,
10666
+ CODEX_CLOSING_REMINDER_REL,
10667
+ CODEX_GH_CLI_SCRIPT_REL
10668
+ ]) await rm(join(cwd, rel), { force: true });
10397
10669
  }
10398
10670
  async checkCodexSetup(agentsPath) {
10399
10671
  const agentsRelPath = "./AGENTS.md";
@@ -10478,8 +10750,9 @@ var SetupCodexHandler = class extends BaseCommand {
10478
10750
  existingContent = await readFile(agentsPath, "utf-8");
10479
10751
  } catch {}
10480
10752
  let newContent;
10481
- const tbdSection = await getCodexTbdSection(this.ctx.quiet);
10753
+ const tbdSection = getCodexTbdSection();
10482
10754
  if (existingContent) if (existingContent.includes(CODEX_BEGIN_MARKER)) {
10755
+ assertNotNewerFormat(existingContent, "AGENTS.md");
10483
10756
  newContent = this.updatetbdSection(existingContent, tbdSection);
10484
10757
  await writeFile(agentsPath, newContent);
10485
10758
  this.output.success("Updated existing tbd section in AGENTS.md");
@@ -10489,7 +10762,7 @@ var SetupCodexHandler = class extends BaseCommand {
10489
10762
  this.output.success("Added tbd section to existing AGENTS.md");
10490
10763
  }
10491
10764
  else {
10492
- await writeFile(agentsPath, await getCodexNewAgentsFile(this.ctx.quiet));
10765
+ await writeFile(agentsPath, getCodexNewAgentsFile());
10493
10766
  this.output.success("Created new AGENTS.md with tbd integration");
10494
10767
  }
10495
10768
  this.output.info(` File: ${agentsPath}`);
@@ -10859,9 +11132,11 @@ var SetupAutoHandler = class extends BaseCommand {
10859
11132
  console.log(colors.dim(`Cleaned up legacy ${parts.join(" and ")}`));
10860
11133
  }
10861
11134
  await this.syncDocs(cwd);
10862
- const claudeResult = await this.setupClaudeIfDetected(cwd);
11135
+ const targeting = this.resolveTargeting();
11136
+ await this.installPortableSkill(cwd);
11137
+ const claudeResult = await this.setupClaudeIfDetected(cwd, targeting.claude);
10863
11138
  results.push(claudeResult);
10864
- const codexResult = await this.setupCodexIfDetected(cwd);
11139
+ const codexResult = await this.setupCodexIfDetected(cwd, targeting.codex);
10865
11140
  results.push(codexResult);
10866
11141
  const installed = results.filter((r) => r.installed && !r.alreadyInstalled);
10867
11142
  const alreadyInstalled = results.filter((r) => r.alreadyInstalled);
@@ -10904,16 +11179,51 @@ var SetupAutoHandler = class extends BaseCommand {
10904
11179
  if (result.pruned.length > 0) console.log(colors.dim(`Pruned ${result.pruned.length} stale config entry/entries`));
10905
11180
  if (result.errors.length > 0) for (const { path, error } of result.errors) console.log(colors.warn(`Warning: ${path}: ${error}`));
10906
11181
  }
10907
- async setupClaudeIfDetected(cwd) {
11182
+ /**
11183
+ * Write the canonical portable Agent Skill to .agents/skills/tbd/SKILL.md.
11184
+ * Runs for every initialized repo, independent of agent detection, so the
11185
+ * skill is portable across Codex, Gemini CLI, Cursor, and other clients.
11186
+ */
11187
+ async installPortableSkill(cwd) {
11188
+ const colors = this.output.getColors();
11189
+ if (this.checkDryRun("Would install portable Agent Skill", { path: AGENTS_SKILL_DISPLAY })) return;
11190
+ const { portable } = getAgentSkillPaths(cwd);
11191
+ await writeSkillFile(portable, await buildSkillPayload(this.ctx.quiet));
11192
+ console.log(` ${colors.success("✓")} Portable Agent Skill (${AGENTS_SKILL_DISPLAY})`);
11193
+ }
11194
+ /**
11195
+ * Resolve which agent surfaces to install from the explicit targeting flags.
11196
+ * `--all`/`--claude`/`--codex` force surfaces on (and suppress auto-detection
11197
+ * of untargeted surfaces); `--skip-claude`/`--skip-codex` force them off; with
11198
+ * no targeting flag each surface falls back to detection-based auto behavior.
11199
+ */
11200
+ resolveTargeting() {
11201
+ const opts = this.cmd.optsWithGlobals();
11202
+ const all = opts.all === true;
11203
+ const anyPositive = all || opts.claude === true || opts.codex === true;
11204
+ const resolve = (on, skip) => {
11205
+ if (skip === true) return "off";
11206
+ if (on === true || all) return "on";
11207
+ return anyPositive ? "off" : "auto";
11208
+ };
11209
+ return {
11210
+ claude: resolve(opts.claude, opts.skipClaude),
11211
+ codex: resolve(opts.codex, opts.skipCodex)
11212
+ };
11213
+ }
11214
+ async setupClaudeIfDetected(cwd, mode) {
10908
11215
  const result = {
10909
11216
  name: "Claude Code",
10910
11217
  detected: false,
10911
11218
  installed: false,
10912
11219
  alreadyInstalled: false
10913
11220
  };
10914
- const hasClaudeDir = await pathExists(GLOBAL_CLAUDE_DIR);
10915
- const hasClaudeEnv = Object.keys(process.env).some((k) => k.startsWith("CLAUDE_"));
10916
- if (!hasClaudeDir && !hasClaudeEnv) return result;
11221
+ if (mode === "off") return result;
11222
+ if (mode === "auto") {
11223
+ const hasClaudeDir = await pathExists(GLOBAL_CLAUDE_DIR);
11224
+ const hasClaudeEnv = Object.keys(process.env).some((k) => k.startsWith("CLAUDE_"));
11225
+ if (!hasClaudeDir && !hasClaudeEnv) return result;
11226
+ }
10917
11227
  result.detected = true;
10918
11228
  const claudePaths = getClaudePaths(cwd);
10919
11229
  try {
@@ -10933,17 +11243,20 @@ var SetupAutoHandler = class extends BaseCommand {
10933
11243
  }
10934
11244
  return result;
10935
11245
  }
10936
- async setupCodexIfDetected(cwd) {
11246
+ async setupCodexIfDetected(cwd, mode) {
10937
11247
  const result = {
10938
11248
  name: "Codex/AGENTS.md",
10939
11249
  detected: false,
10940
11250
  installed: false,
10941
11251
  alreadyInstalled: false
10942
11252
  };
11253
+ if (mode === "off") return result;
10943
11254
  const agentsPath = getAgentsMdPath(cwd);
10944
11255
  const hasAgentsMd = await pathExists(agentsPath);
10945
- const hasCodexEnv = Object.keys(process.env).some((k) => k.startsWith("CODEX_"));
10946
- if (!hasAgentsMd && !hasCodexEnv) return result;
11256
+ if (mode === "auto") {
11257
+ const hasCodexEnv = Object.keys(process.env).some((k) => k.startsWith("CODEX_"));
11258
+ if (!hasAgentsMd && !hasCodexEnv) return result;
11259
+ }
10947
11260
  result.detected = true;
10948
11261
  if (hasAgentsMd) {
10949
11262
  if ((await readFile(agentsPath, "utf-8")).includes("BEGIN TBD INTEGRATION")) result.alreadyInstalled = true;
@@ -10954,12 +11267,13 @@ var SetupAutoHandler = class extends BaseCommand {
10954
11267
  await handler.run({});
10955
11268
  result.installed = true;
10956
11269
  } catch (error) {
11270
+ if (error instanceof CLIError) throw error;
10957
11271
  result.error = error.message;
10958
11272
  }
10959
11273
  return result;
10960
11274
  }
10961
11275
  };
10962
- const setupCommand = new Command("setup").description("Configure tbd integration with editors and tools").option("--auto", "Non-interactive mode with smart defaults (for agents/scripts)").option("--interactive", "Interactive mode with prompts (for humans)").option("--from-beads", "Migrate from Beads to tbd").option("--prefix <name>", "Project prefix for issue IDs (required for fresh setup)").option("--force", "Allow non-recommended prefix format (not 2-8 alphabetic)").option("--no-gh-cli", "Disable automatic GitHub CLI installation hook").action(async (options, command) => {
11276
+ const setupCommand = new Command("setup").description("Configure tbd integration with editors and tools").option("--auto", "Non-interactive mode with smart defaults (for agents/scripts)").option("--interactive", "Interactive mode with prompts (for humans)").option("--from-beads", "Migrate from Beads to tbd").option("--prefix <name>", "Project prefix for issue IDs (required for fresh setup)").option("--force", "Allow non-recommended prefix format (not 2-8 alphabetic)").option("--no-gh-cli", "Disable automatic GitHub CLI installation hook").option("--all", "Install every supported agent surface (Claude + Codex)").option("--claude", "Install the Claude Code surface (skill mirror + hooks)").option("--codex", "Install the Codex surface (AGENTS.md block + .codex hooks)").option("--skip-claude", "Skip the Claude Code surface even if detected").option("--skip-codex", "Skip the Codex surface even if detected").action(async (options, command) => {
10963
11277
  if (options.auto || options.interactive) {
10964
11278
  await new SetupDefaultHandler(command).run(options);
10965
11279
  return;