Bootstrap exemptions for auxiliary commands: help, completion, __complete, and the init subtree¶
- Authors
- Matt Cockayne, Claude Fable 5 (AI drafting assistant)
- Date
- 2026-07-23
- Status
- IMPLEMENTED — 2026-07-23
- Related
- architectural review (GTB-core §HIGH
auto-generated-command bootstrap + §LOW SkipUpdateCheck Use-strings + §LOW
init <provider>config-gating findings)
1. Problem¶
The root PersistentPreRunE (pkg/cmd/root/root.go:784-867) performs the full framework
bootstrap — flag extraction, config-store construction with the missing-config gate,
telemetry consent, collector wiring, update check — for every runnable command.
With cobra.EnableTraverseRunHooks, that includes cobra's auto-generated help,
completion <shell> and hidden __complete commands, none of which are exempted: the
only fast-path is the InitCmd feature match at root.go:796.
Concrete failures on the current code path:
- Fresh install breaks help and completion. On a scaffolded tool with no config file
yet (InitCmd enabled by default,
AutoInitialiseopt-in),resolveBootstrapConfigreturnsErrNoConfigFile(root.go:214), sotool helpandtool completion bashexit non-zero withfailed to load configuration: no config file found(root.go:810-813) — with no hint telling the user to run<tool> init. Shell tab-completion (__complete) errors on every keystroke. - Completion pays the bootstrap even when config exists — including the throttled-but-sometimes-real network update check and, for telemetry-enabled tools, the consent-prompt attempt.
SkipUpdateCheckmatches fragileUsestrings (pkg/setup/update.go:572-577): the skip list{"update","auth","init","version"}is compared against the leafcmd.Use, which may carry an args suffix, collides with any downstream command coincidentally namedauth, and omitsmcp,doctor,helpandcompletion. The codebase already owns the right mechanism — the typed feature annotation stamped bysetup.Wrapand read viasetup.FeatureOf, used for exactly this reason atroot.go:792-796(the comment there names the Use-string footgun).init <provider>is config-gated on a fresh install — the same mechanism gap. The pre-run's exemption matches onlyFeatureOf(cmd) == p.InitCmd, i.e. the init leaf; provider subcommands (init github,init bitbucket) are registered viaregisterSubcommands(pkg/cmd/initialise/init.go:104-114) and wrapped with their provider feature, so on a machine with no config file they fail the missing-config gate instead of running — the one command tree that exists to fix that state.
2. Proposed change¶
All changes use the existing typed-annotation machinery (setup.Wrap/FeatureOf,
setup.SkipConfigCheck/SkipsConfigCheck — pkg/setup/command.go) rather than adding
string matching.
- Pre-run fast path for cobra's auxiliary commands. In
newRootPreRunE, beforeresolveBootstrapConfig, return early (after the same debug-logging setup theInitCmdbranch performs) whencmd.Name()ishelp,cobra.ShellCompRequestCmd,cobra.ShellCompNoDescRequestCmd, or the command is the root-registeredcompletiongroup (match the built-in by identity/parentage, not by a downstream-colliding name where feasible; cobra's generated commands carry no annotations, soName()against cobra's own constants is the correct discriminator here — these names are cobra-reserved, unlikeauth). - Exempt the whole init subtree. Replace the leaf-only check at
root.go:796with a walk upcmd.Parent()until a command withFeatureOf == p.InitCmdis found (or annotate provider subcommands withsetup.SkipConfigCheckat registration inregisterSubcommands). Either way,init githubon a configless machine must run. - Annotation-based
SkipUpdateCheck. Replace theUse-string list atpkg/setup/update.go:572-577with annotation matching: skip whenFeatureOf(cmd)∈ {UpdateCmd,InitCmd} and introduce asetup.SkipUpdateCheckAnnotation(mirroringSkipConfigCheckAnnotation) stamped onversion(which is wrapped with the empty feature,pkg/cmd/version/version.go:102) and on the forgeauthcommand — so the exemption is rename-safe and cannot collide with downstream commands namedauth. Addmcp,doctor,helpandcompletionto the skip set via the same annotation at their construction sites. - Hint on the missing-config error. Where the pre-run wraps the load failure
(
root.go:811-813), attacherrors.WithHintf(err, "Run '%s init' to create a configuration.", props.Tool.Name)whenerrors.Is(err, ErrNoConfigFile)and the init feature is enabled (fall back to a plain "no config file found at" hint when it is not).
3. Scope & release plan¶
- GTB-repo only:
pkg/cmd/root,pkg/setup(annotation +SkipUpdateCheck),pkg/cmd/initialise(subtree exemption),pkg/cmd/version(annotation stamp).SkipUpdateCheck's signature/semantics change is a public-API break — permitted pre-1.0, ships asfeat(root)(minor) with a note in the commit body and a migration note indocs/migration/. - E2E/BDD implications: yes. Fresh-install
help/completionbehaviour is exactly the user-facing workflow the project's BDD strategy targets. Add Gherkin scenarios infeatures/(steps intest/e2e/steps/,cmd/e2ebinary): "Given no config file exists, When I run<tool> help, Then the exit code is 0 and usage is printed"; likewise forcompletion bashand an__completeinvocation; plus "init github with no config file runs the initialiser". Run with-count=1(Godog results are go-test-cached). - Unit tests: pre-run fast-path table tests;
SkipUpdateCheckannotation tests extendingpkg/setup/command_test.go. /gtb-verifybefore the MR; updatedocs/components/for the root pre-run and setup command annotations (functional change requires a doc update).
4. Acceptance criteria¶
- On a filesystem with no config file:
tool help,tool --help,tool completion bash|zsh|fish, and a__completerequest all exit 0 with correct output and no config/update/consent side effects; covered by Gherkin scenarios. tool init github(andinit bitbucket) run on a configless machine instead of failing the missing-config gate.- With config present,
__completeandcompletionnever trigger the network update check or the telemetry consent prompt (assert via the fake release source / recorded prompts in the existing test harness). - A downstream tool defining an unrelated command named
authorinitgets the normal bootstrap (no accidental exemption) — annotation matching, not name matching, decides. - Running any non-exempt command with no config file produces the existing error plus
a hint naming
<tool> init. SkipUpdateCheckhas no remainingcmd.Usestring comparisons.
5. Open questions — resolved¶
- Only cobra's own generated command instances are exempted, not any
downstream command that happens to share the name. The discriminator
(
isCobraGeneratedCommand,pkg/cmd/root/root.go) is a direct child of the root carrying no annotations — every GTB-wrapped command is stamped bysetup.Wrap, so a downstream feature command namedhelporcompletionstill gets the normal bootstrap (covered byTestPreRun_DownstreamCompletionCommand_GetsNormalBootstrap). - The fast path still configures debug logging (
applyDebugFlag, shared semantics with the formerInitCmdbranch), so--debug tool completion bashstays debuggable. It is tolerant of__complete, whose flags cobra never parses. - Both. Cobra's auxiliary commands are exempted intrinsically, and a
Tool.Bootstrap.AuxiliaryCommandsname/path list (matchingSkipConfigCheck's semantics viaMatchesAuxiliaryList) lets downstream tools extend the fast-path set without a GTB release. Auxiliary commands run withprops.Confignil — stronger thanSkipConfigCheck's tolerant load.
Implementation notes¶
SkipUpdateCheckkeeps its signature; only the exemption semantics changed (annotation/feature parent-chain walk, noUsestrings).help/completionneed no update-check annotation because the pre-run fast path returns before the check is ever reached; there is no construction site at which to stamp cobra's generated instances. The forgeauthcommand named by §2.3 no longer exists post-extraction, so no stamp was needed there.- Migration note:
docs/reference/migration/v0.x-update-check-annotations.md. - The
init githubfresh-install path is covered by unit test (TestPreRun_FreshInstall_InitSubtreeRuns) rather than a Gherkin scenario: the provider wizard reaches an unguardedform.Run()and huh hangs on non-terminal stdin (the MR !157 failure mode), which would risk hanging the e2e suite. Gherkin covershelp,completion bash,__completeand the run-init hint (features/cli/fresh_install.feature).