Generate Command¶
The generate command group handles the creation of new assets (projects, commands, flags).
Help Output (generate --help)¶
Scaffold new projects (skeletons) or add new commands to existing gtb projects.
Usage:
gtb generate [flags]
gtb generate [command]
Available Commands:
add-flag Add a new flag to an existing command
command Generate a new command or subcommand
docs Generate documentation for a command using AI
skeleton Generate a new cli project skeleton
Flags:
-h, --help help for generate
--model string AI model to use (per-provider defaults apply when omitted)
--provider string AI provider to use (openai/claude/gemini/claude-local/openai-compatible)
Global Flags:
--ci flag to indicate the tools is running in a CI environment
--config stringArray config files to use (default [/home/mcockayne/.gtb/config.yaml,/etc/gtb/config.yaml])
--debug forces debug log output
Subcommands¶
Skeleton¶
Generates a new project structure from scratch.
Help (generate skeleton --help):
Generate a new cli project skeleton
Aliases:
skeleton, project, cli
Flags:
-d, --description string Project description (default "A tool built with gtb")
-f, --features strings Features to enable (init, update, mcp, docs, doctor, changelog, keychain, ai, config, telemetry) (default [init,update,mcp,docs,doctor,changelog,keychain])
--git-backend string Git backend (github or gitlab) (default "github")
--go-version string Go version for go.mod (defaults to the running toolchain version)
-h, --help help for skeleton
--host string Git Host (e.g. github.com) (default "github.com")
-n, --name string Project name (e.g. mytool)
-p, --path string Destination path (default ".")
-r, --repo string Git repository (e.g. myorg/mytool)
Feature flags¶
The --features flag controls which subsystems and side-effect activations appear in the scaffolded project. Defaults are selected in the interactive wizard and reflected in the manifest so gtb regenerate preserves the choice.
| Feature | Default | What it scaffolds |
|---|---|---|
init |
on | init subcommand |
update |
on | self-update subsystem |
mcp |
on | MCP server subsystem |
docs |
on | built-in docs browser |
doctor |
on | doctor subsystem |
changelog |
on | changelog subsystem |
keychain |
on | cmd/<name>/keychain.go blank-importing pkg/credentials/keychain — activates the OS keychain backend by default. Delete the scaffolded file for a regulated build (no go-keyring / godbus / wincred linked). See How to configure credentials and How to implement a custom credential backend. |
ai |
off (opt-in) | AI chat subsystem |
config |
off (opt-in) | config subsystem with get/set/list |
telemetry |
off (opt-in) | telemetry subsystem |
Example — generate a regulated build with no keychain code linked:
Post-generation git step¶
After the skeleton is written and post-processing settles (go mod tidy,
golangci-lint --fix, manifest-hash refresh), generate project makes the
destination a real repository with a single initial commit. This is opt-out:
it runs by default, including under --ci/non-interactive.
| Flag | Default | Behaviour |
|---|---|---|
--no-git |
off (git step on) | Skip the init + initial commit entirely; no .git is created. |
--push |
off (opt-in) | After the commit, add the derived remote as origin and push the default branch. |
--git-branch <name> |
main |
Default branch the initial commit lands on (matches the rendered releaser-pleaser CI). |
Behaviour details:
- Already a repo. If the destination is already inside a git repository
(discovery walks upward for an enclosing
.git), the whole step is skipped with an info log — the scaffold is never committed into someone else's tree, and a subdirectory of an existing repo is treated as already-a-repo. - Staging. The tree is staged honouring the generated
.gitignore, so build artefacts are excluded while the.gitignoreitself is committed. - Commit message.
chore: scaffold <tool> with gtb— the non-releasingchore:type means the empty scaffold does not make releaser-pleaser cut a release. - Author identity. Resolved in order: host git config (
user.name/user.email, repo-local → global → system) → the GTB config keysgenerator.git.author.name/generator.git.author.email→ a safe framework fallback (gtb <gtb@localhost>), so the commit never fails for lack of an identity. - Push target. Derived from the release source as
https://{host}/{owner}/{repo}.git(GitLab nested group paths are preserved), usingpkg/vcs/repo's provider-aware auth. Creating the remote on the forge is out of scope — the push assumes the remote exists. - Best-effort. Every git action is non-fatal: any failure (init, commit,
missing remote, auth, network) logs a warning and generation still succeeds.
A failed push prints the manual
git push -u origin <branch>to run once the remote exists. - Conflicting flags.
--no-gitwith--pushis rejected — push has no commit to publish without the git step. - Dry-run.
--dry-runperforms no git actions; the would-be init/commit (and push under--push) is listed under "Post-generation actions". regenerate/removenever init, stage, commit, or push — the git step is exclusive to initial scaffolding viagenerate project.
The step is built on the pkg/vcs/repo Initializer primitives
(DiscoverRepository, InitLocal, AddAll) plus CreateRemote / Push — see
vcs/repo.
# default: scaffold and make the initial commit on main
gtb generate project -n mytool -r myorg/mytool
# scaffold only, no commit
gtb generate project -n mytool -r myorg/mytool --no-git
# scaffold, commit, and push to the (assumed-existing) remote
gtb generate project -n mytool -r myorg/mytool --push
Self-update policy¶
The --update-policy flag (interactive: the Self-Update Policy wizard step)
sets the generated tool's props.Tool.UpdatePolicy baseline — how it behaves
when a newer release is found. The value is persisted to the manifest so
gtb regenerate preserves it, and end users can override it at runtime via the
update.policy config key.
--update-policy |
Emitted props.Tool.UpdatePolicy |
Behaviour when a newer release exists |
|---|---|---|
disabled / (empty) |
(field omitted — framework default) | Logs that an update is available, then continues the command. |
prompt |
props.UpdatePolicyPrompt |
Prompts the user to update; declining continues the command. |
enabled |
props.UpdatePolicyEnabled |
Blocks every command until the tool is updated. |
The check is always skipped under --ci/ci: true regardless of policy. See
the self-update policy migration note
for the full resolution order.
Update check interval¶
The --update-check-interval flag (interactive: the Update Check Interval
wizard step) sets the generated tool's props.Tool.UpdateCheckInterval baseline
— how often it checks for a newer release, as a Go duration
(e.g. 24h, 168h, 30m). Like the policy, it is persisted to the manifest
(update_check_interval) so gtb regenerate preserves it, rendered into the
props.Tool literal as a time.Duration expression (168 * time.Hour), and
overridable at runtime via the update.check_interval config key.
--update-check-interval |
Emitted props.Tool.UpdateCheckInterval |
Effect |
|---|---|---|
| (empty) | (field omitted — framework default) | Checks at most once every 24h. |
168h |
168 * time.Hour |
Checks at most once a week. |
0/0s |
(field omitted) | A zero baseline is treated as "unset" → 24h. To check on every invocation, set update.check_interval: "0" in config at runtime — a compiled-in "every run" baseline is intentionally not offered. |
Resolution precedence at runtime: a valid update.check_interval config value
(where 0 means "every run") → the props.Tool.UpdateCheckInterval baseline (if
positive) → the framework default (24h).
# generate a tool that prompts to self-update and checks weekly
gtb generate project -n mytool -r myorg/mytool \
--update-policy prompt --update-check-interval 168h
Command¶
Generates a new Cobra command, optionally using AI or from a script.
Help (generate command --help):
Generate a new command or subcommand with boilerplate code.
Examples:
# Generate a command named 'login' in the current project
gtb generate command --name login --short "Login to the system"
# Generate a subcommand 'list' under 'login'
gtb generate command --name list --parent login --short "List sessions"
# Generate 'leaf' nested under the existing 'gala/mid' path (--parent takes a slash path)
gtb generate command --name leaf --parent gala/mid --short "Deeply nested"
# Generate a command with flags and assets
gtb generate command -n serve -f "port:int:Port to listen on" --assets
# Generate a command from a script (e.g., bash)
# The AI will attempt to convert the script to Go code
# The autonomous agent is used by default for verification
gtb generate command -n backup --script ./backup.sh
# Use the original feedback loop instead of the autonomous agent
gtb generate command -n backup --script ./backup.sh --agentless
# Create a protected command (cannot be overwritten by generator)
gtb generate command -n sensible --protected
# Temporarily unprotect a command to allow overwrite
gtb generate command -n sensible --protected=false --force
# Generate a command kept off the MCP tool surface (still runnable on the CLI)
gtb generate command -n post --mcp-enabled=false
Usage:
gtb generate command [flags]
gtb generate command [command]
Available Commands:
protect Protect a command from being overwritten
unprotect Unprotect a command to allow overwriting
Flags:
--agentless Use original retry loop instead of autonomous agent
--alias strings Aliases for the command
--assets Include assets directory support
--flag strings Flags definition (name:type:description:persistent)
--force Overwrite existing files
-h, --help help for command
--long string Long description
--mcp-enabled Expose this command as an MCP tool (tri-state: --mcp-enabled=false excludes it from the MCP surface, omitted for default-exposed). The command stays runnable on the CLI either way (default true)
-n, --name string Command name (kebab-case)
--parent string Parent command to nest under; use a slash path (parent/child) for deep nesting (default "root")
-p, --path string Filesystem project root directory (not a command path) (default ".")
--persistent-pre-run Generate a PersistentPreRun hook
--pre-run Generate a PreRun hook
--prompt string Natural language description or path to a file containing the description
--protected Mark the command as protected (tri-state: --protected for true, --protected=false for false, omitted for nil)
--script string Path to a script to convert to Go (bash/python/js)
-s, --short string Short description
Add Flag¶
Injects a new flag into an existing command file.
Targeting nested subcommands. -c/--command accepts a slash-delimited
command path (parent/child/leaf). To add a flag to a nested subcommand,
pass the full path — a leaf name alone resolves only a top-level command, and
neither a space-joined ("reel create now") nor a dotted (reel.now) form is
accepted. -p/--path is the filesystem project root (which project's
.gtb/manifest.yaml to edit), not a command path — a common source of
confusion. When -c does not resolve, the error now hints at the slash-path
form (e.g. did you mean -c parent/<name>?).
# Flag on the top-level 'deploy' command
gtb generate add-flag -c deploy -n verbose -t bool -d "Verbose output"
# Flag on 'now' nested under 'reel/create'
gtb generate add-flag -c reel/create/now -n force -t bool -d "Skip confirmation"
Help (generate add-flag --help):
Add a new flag to an existing command in the current project.
The target command is addressed by -c/--command. To target a nested
subcommand, pass the full slash-delimited command path (parent/child/leaf).
Usage:
gtb generate add-flag [flags]
Flags:
-c, --command string Command to add the flag to; use a slash path (parent/child/leaf) for nested subcommands
-d, --description string Flag description
-h, --help help for add-flag
-n, --name string Flag name
-p, --path string Filesystem project root directory (not a command path) (default ".")
--persistent Make the flag persistent
-s, --shorthand string Single-letter shorthand for the flag (e.g. v for -v)
-t, --type string Flag type (string, bool, int, float64, stringSlice, intSlice) (default "string")
--shorthand/-s gives the generated flag a single-letter shorthand (the
-x form). The value is validated as a single ASCII letter, recorded as the
manifest flag's shorthand, and rendered as the cobra …VarP(&opts.X, "name",
"x", …) registration. Leave it empty for a long-form-only flag.
Both invocation paths validate their inputs. The non-interactive path
(both --command and --name supplied on the command line) applies the
same rules the interactive wizard enforces before touching the manifest:
- the command path is validated segment-by-segment via
generator.ValidateCommandName(kebab-case + underscore, lowercase first, no path separators or dots), --nameis validated bygenerator.ValidateFlagName(^[a-z][a-z0-9-]{0,63}$), and--typeis validated bygenerator.ValidateFlagType(one of the renderable types; an unknown type is rejected rather than silently degraded to a string flag).
A bad value returns a generator.ErrInvalidInput-wrapped error instead
of corrupting .gtb/manifest.yaml.
Docs¶
Generates documentation for a command. AI doc-generation is opt-in: it runs
only when an AI provider is explicitly configured (via --provider or the
ai.provider config key) and --agentless is not set. Otherwise — and this is
the default — GTB writes deterministic boilerplate documentation from the
manifest with no API call. A configured-but-failing AI call (e.g. no API
credit) degrades quietly to the same boilerplate rather than erroring loudly.
The same gate governs the docs step of generate command, so scaffolding a new
command never reaches out to a paid AI API by default.
Help (generate docs --help):
Generate Markdown documentation for a Go command.
When an AI provider is configured (via --provider or the ai.provider config
key) and --agentless is not set, the command source is analysed and the AI
integration produces rich docs following the docs-site conventions. Otherwise
GTB writes deterministic boilerplate documentation with no API call — AI
doc-generation is opt-in.
Examples:
# Boilerplate docs (no AI), the default
gtb generate docs --command mycmd
# AI-assisted docs (requires a configured provider)
gtb generate docs --command mycmd --provider claude
# Force boilerplate even with a provider configured
gtb generate docs --command mycmd --agentless
Usage:
gtb generate docs [flags]
Flags:
--agentless Skip AI doc-generation and write boilerplate docs only
--command string Name/Path of command to document
-h, --help help for docs
-n, --name string Command name (optional, inferred from path)
--package string Path to package to document (relative to project root)
--parent string Parent command name (optional, if not in manifest)
--path string Path to project root (default ".")
--source string Path to the command source code (deprecated, use --command)
--source is a deprecated alias for --command (Cobra prints a
deprecation warning steering you to --command). It still works:
docs falls back to --source when --command is empty, and it
participates in the one-required {command|package|source} group, so a
source-only invocation is accepted rather than wrongly rejected.
--source is mutually exclusive with --package.