name: alpaca-cli-regenerate
description: >- Use when this capability is needed.
metadata:
author: alpacahq
Generate - Keep the CLI Up to Date
Pipeline
Run each phase in order. Stop and fix before moving to the next.
Phase 1: Pull latest specs
make spec-update requires network access (it curls docs.alpaca.markets).
Request full_network permissions if running in a sandbox.
make spec-update
Downloads trading-api.json and market-data-api.json from
docs.alpaca.markets/openapi/ into api/specs/.
After pulling, check what changed:
git diff --stat api/specs/
If nothing changed, specs are already current - skip to Phase 4 to
verify generated code is still fresh.
Phase 2: Generate code
make generate
This runs go run ./cmd/generate which reads the specs and writes:
| Generated file | Contents |
|---|
internal/api/trading_types.gen.go | Structs and enums from trading spec |
internal/api/trading_client.gen.go | Trading API client methods |
internal/api/marketdata_types.gen.go | Structs and enums from market data spec |
internal/api/marketdata_client.gen.go | Market data API client methods |
internal/api/descriptions.gen.go | Op metadata, flags, response schemas |
internal/cmd/commands.gen.go | Cobra command tree |
Never edit *.gen.go files directly. Change the specs or generator,
then re-run make generate.
Phase 3: Fix generator failures
The generator enforces exhaustiveness. Common failures and fixes:
New operation not registered
unregistered operation "FooBar" — add to cmdRegistry or cmdSkip
Every operationId in the specs must appear in either cmdRegistry or
cmdSkip in cmd/generate/commands.go.
To register a new command, add an entry to cmdRegistry:
"FooBar": {
parent: "<parent-group>",
use: "<subcommand-name>",
examples: " alpaca <parent> <subcommand> --flag value",
},
Rules for registry entries:
parent must be a key in cmdParents (or create a new parent group)
examples is required - the generator fails without it
- Use kebab-case for
use names
- Add
defaults for sensible default flag values
- Add
bodyAliases if a body field name collides with a query/path param
- Add
bodyHook / bodySkipFields for complex body construction
- Add
configureFunc for hand-written configure hooks (e.g. order submit's bracket legs)
- Add
normalize for path params that need URL normalization (e.g. symbols with /)
If the command IS its parent (e.g. alpaca clock runs directly, not
alpaca clock get), use self: true and omit use:
"LegacyClock": {
parent: "clock",
self: true,
examples: " alpaca clock",
},
To skip an operation (intentionally exclude from the CLI):
var cmdSkip = map[string]string{
"FooBar": "reason for skipping",
}
Body field collision
body field "name" collides with a query/path param — add bodyAliases
Fix by adding a bodyAliases entry that renames the body flag:
"UpdateFoo": {
parent: "foo",
use: "update",
bodyAliases: map[string]string{"name": "new-name"},
examples: " alpaca foo update --name old --new-name new",
},
New parent group needed
Add to cmdParents in cmd/generate/commands.go:
"myGroup": {
use: "my-group",
short: "Short description",
long: "Longer description for --help.",
},
For nested groups, set parent:
"mySubGroup": {
use: "sub",
short: "Sub-group description",
parent: "myGroup",
},
Top-level parent groups also need root wiring. If the new group is
not nested under an existing parent, add it to addGroup() in
internal/cmd/root.go. Pick the right group (tradingGroup,
accountGroup, or utilGroup):
addGroup(rootCmd, tradingGroup.ID, orderCmd, ..., myGroupCmd)
Without this, the command won't appear in --help or --help-all.
After fixing, re-run make generate until it succeeds.
Phase 4: Update golden files
If the command tree or op metadata changed, golden files will be stale:
go test ./internal/cmd -run TestCommandTreeGolden -update
go test ./internal/cmd -run TestOpsGolden -update
Phase 5: Run all checks
make check
This runs golangci-lint, go test -race ./..., and go build. Fix any
failures before proceeding.
If tests fail due to golden drift you missed, re-run Phase 4.
Phase 6: Verify completeness
Review what changed end-to-end:
git diff --stat
Verify:
If commands were added, add integration tests in test/integration/.
Follow the rules in the "Integration tests" section of AGENTS.md -
one file per feature area, t.Parallel() for read-only tests, cleanup
for writes. If the endpoint is unavailable on paper (see the
paper-unavailable list in AGENTS.md), write a test that accepts either
a valid response or a structured JSON error.
If commands or flags were added, removed, or renamed, follow the
"Keep docs in sync" section in AGENTS.md.
Quick reference
| Task | Command |
|---|
| Pull specs | make spec-update |
| Generate code | make generate |
| Update golden files | go test ./internal/cmd -run TestCommandTreeGolden -update && go test ./internal/cmd -run TestOpsGolden -update |
| Lint + test + build | make check |
| See what changed | git diff --stat |
| Integration tests | make test-integration (needs API keys) |
Key files
| File | Role | Editable? |
|---|
api/specs/*.json | OAS specs (read-only inputs) | No - pull from upstream |
cmd/generate/main.go | Generator logic | Yes |
cmd/generate/commands.go | Command registry and parent groups | Yes |
internal/api/*.gen.go | Generated types and clients | No - regenerate |
internal/cmd/commands.gen.go | Generated Cobra commands | No - regenerate |
internal/cmd/root.go | Root command wiring (addGroup for top-level parents) | Yes |
internal/cmd/testdata/*.golden | Golden test snapshots | Update via -update flag |
Anti-Patterns
- NEVER edit
*.gen.go files directly - they are overwritten by make generate. Change the specs or the generator instead.
- NEVER edit spec files in
api/specs/ - fix bugs upstream and re-import with make spec-update.
- NEVER skip
make check after generating - generated code can introduce lint failures or test regressions.
- NEVER update golden files without reviewing the diff - golden updates should reflect intentional command tree changes, not mask bugs.
- NEVER add a
cmdRegistry entry without examples - the generator enforces this and will fail.
- NEVER add an operation to
cmdSkip without a reason - the reason documents why the endpoint is excluded from the CLI.
Source: alpacahq/cli — distributed by TomeVault.