cli/cli
Factory and cmdutil
Active contributors: Mislav, Sam Coe, William Martin
Purpose
cmdutil.Factory is the dependency-injection backbone of the CLI. Every command receives a *cmdutil.Factory and pulls only the functions it needs (HTTP client, prompter, base repo, IOStreams, ...). The package also collects the reusable building blocks that almost every command imports: typed errors, JSON output flags, mutually-exclusive-flag helper, and the auth-check guard.
Directory layout
pkg/cmdutil/
factory.go # The Factory struct
errors.go # FlagErrorf, SilentError, CancelError, PendingError, NoResultsError
flags.go # NilStringFlag, NilBoolFlag, StringEnumFlag, StringSliceVar
json_flags.go # AddJSONFlags, Exporter, Write
args.go # Cobra arg validators
auth_check.go # CheckAuth used by root.PersistentPreRunE
cmdgroup.go # AddGroup helper
legacy.go # Bridge for older patterns
repo_override.go # Implements --repo
telemetry.go # RecordTelemetryForSubcommands
file_input.go # Read body input from --body-file
factory.go # Factory struct definition
pkg/cmd/factory/
default.go # New: assembles the Factory in the real binary
remote_resolver.go # Smart resolver behind SmartBaseRepoFuncKey abstractions
| Symbol | File | Role |
|---|---|---|
Factory |
pkg/cmdutil/factory.go |
The DI struct. |
factory.New |
pkg/cmd/factory/default.go |
Builds the real factory: HTTP client, git client, prompter, browser, extension manager, base repo, branch. |
BaseRepoFunc |
default.go |
Default base repo: first eligible remote. |
SmartBaseRepoFunc |
default.go |
Network-resolving base repo: honours gh repo set-default and resolves fork networks via the API. Used by pr, issue, repo, etc. |
HttpClientFunc |
default.go |
Lazily creates the HTTP client with the full transport stack. |
cmdutil.AddJSONFlags |
json_flags.go |
Adds --json, --jq, --template flags backed by an Exporter. |
cmdutil.MutuallyExclusive |
errors.go |
Returns an error when more than one of a set of flags is set. |
cmdutil.CheckAuth / IsAuthCheckEnabled |
auth_check.go |
Used by the root command's PersistentPreRunE to require login. |
RecordTelemetryForSubcommands |
telemetry.go |
Walks the Cobra tree and wraps each subcommand to emit a telemetry event. |
NilStringFlag / NilBoolFlag |
flags.go |
Optional-flag helpers that distinguish "not set" from zero value. |
How it works
graph TD
A[ghcmd.Main] --> B[factory.New]
B --> C[HttpClient lazy func]
B --> D[GitClient eagerly created]
B --> E[Remotes lazy func]
B --> F[BaseRepo - simple lazy func]
B --> G[Prompter]
B --> H[Browser]
B --> I[ExtensionManager]
B --> J[Branch lazy func]
A --> K[root.NewCmdRoot]
K --> L[copy of factory with SmartBaseRepoFunc]
L --> M[register pr/issue/repo/release/...]
K --> N[register simple-resolver commands]Lazy functions are everywhere because some commands run before a config exists (gh version, gh completion, gh auth login).
The smart resolver:
- Reads the local git remotes through
git.Client. - Filters to remotes whose hosts are authenticated.
- Sorts by
upstream,github,origin, then alphabetical. - Reads the
resolvedgit config key on each remote:basekeeps that remote, aowner/repovalue pins to a specific repo regardless of remote. - Falls back to the API to resolve fork networks if no resolution exists, then prompts the user to pick if interactive.
Integration points
- Touched by every command. New commands typically declare
IO,HttpClient,Config, andBaseRepoas fields on theirFooOptionsstruct. - Errors of type
cmdutil.SilentErrorexit with code 1 but suppress the message; commands use this when they have already printed. cmdutil.CancelErroris what propagates from a cancelled prompt; it maps to exit code 2.
Entry points for modification
- Adding a dependency every command needs: extend
Factoryand updatefactory.New. Be very conservative: this is a hot path and any new field gets used hundreds of times. - Changing repo resolution: edit
pkg/cmd/factory/remote_resolver.goand theBaseRepoFunc/SmartBaseRepoFuncindefault.go. Cover changes with the existing tests indefault_test.goandremote_resolver_test.go. - New common flag: add it under
pkg/cmdutil/flags.goand share it viacmdutil.AddJSONFlags-style helpers.
Key source files
| File | Purpose |
|---|---|
pkg/cmdutil/factory.go |
Factory struct. |
pkg/cmd/factory/default.go |
Factory assembly. |
pkg/cmd/factory/remote_resolver.go |
Remote ordering and filtering. |
pkg/cmdutil/errors.go |
Typed errors. |
pkg/cmdutil/json_flags.go |
JSON output flags. |
pkg/cmdutil/auth_check.go |
Auth gate. |
pkg/cmdutil/telemetry.go |
Per-command telemetry wrapping. |
Related pages
- API client for what
HttpClientends up being. - Patterns and conventions for the consumer-side rules.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.