CLI Development
The Go CLI under cli/ wraps the public API as seed <resource> <verb>. It's used by humans, by deploy smoke, and most importantly by the Pi agent inside sandboxed tasks — Pi discovers commands at runtime, so CLI coverage is what determines what tasks can do.
Default stance
Spec first, CLI follows. Every CLI command should map to one or more OpenAPI endpoints. If the API doesn't exist yet, go to add-api-endpoint first — adding a CLI command without a spec entry creates a feature that has no SDK and no MCP exposure.
Non-interactive by default. All commands must work with --flag args or env vars; never block on stdin for required values. The CLI runs inside Pi sandboxes (no TTY), in CI, and in deploy smoke. An interactive prompt breaks all three.
Human-readable default, JSON on demand. Commands print pretty output by default and switch to --output json when needed. Pi parses JSON; humans read tables. Don't pick one and lose the other.
Use this skill when
Adding a CLI command for a new API endpoint, changing CLI auth/config resolution, fixing CLI tests, rebuilding cli/bin/seed for local smoke, or auditing CLI coverage after API changes.
Workflow
- Inspect the API surface — read
openapi/v1.yamlandapp/api/v1/<resource>/route.tsfor what's available. - Check existing patterns — look at
cli/cmd/keys.goorcli/cmd/usage.gofor the conventional shape (Cobra command, flags, output formatting). - Add the command —
cli/cmd/<resource>.gowith both query and mutation subcommands as needed. - Add tests —
cli/cmd/<resource>_test.gonext to the source. - Rebuild the binary —
cd cli && make build. Stalecli/bin/seedis the most common cause of "deploy smoke fails but the deployed API works." - Run Go tests —
cd cli && go test ./.... - Run repo gates —
./scripts/gates.sh.
Conventions
- Cobra commands — one resource per file (
cli/cmd/<resource>.go). Subcommands:list,get,create,update,delete, plus resource-specific verbs. - Auth resolution — API key from
--api-keyflag →SEED_API_KEYenv → config file at~/.seed/config.json. Theauthcommand sets the config. - Base URL —
--api-urlflag →SEED_API_URLenv → default to production URL fromlib/brand.ts. - Output — pretty default,
--output jsonflag for machine consumption. - Errors — non-zero exit code, error message to
stderr, no panics on user errors.
Pi consumption pattern
Pi is the heaviest user of the CLI. Every command should be safe for Pi to run:
- No interactive prompts.
--api-keyand--organization-idshould always be flag-passable. - Idempotent reads.
seed keys listshouldn't have side effects. - Predictable JSON output. Pi often filters with
jq. Field names should be stable and documented in the command help. - Clear exit codes. Non-zero on failure so Pi can detect and react.
Hard rules
- Don't add a CLI command for an endpoint that doesn't exist in
openapi/v1.yaml. Spec first. - Don't break existing flag names in a non-major release. The CLI is consumed by automated systems that won't notice silent renames.
- Don't ship without rebuilding
cli/bin/seedif you're going to run deploy smoke afterward. The smoke runner uses the local binary. - Don't put business logic in the CLI. It's a thin wrapper over the API. If the CLI computes something the API doesn't, that's an API gap to fix, not a CLI feature.
Where things live
| File | Purpose |
|---|---|
cli/cmd/root.go | Cobra root, global flags, version |
cli/cmd/auth.go | seed auth login — writes config |
cli/cmd/keys.go, keys_test.go | API key management — reference pattern |
cli/cmd/me.go | seed me — current user/org |
cli/cmd/usage.go | Usage queries |
cli/cmd/version.go | seed version |
cli/Makefile | make build produces cli/bin/seed |
cli/AGENTS.md | CLI development patterns and conventions |
cli/bin/seed | Built binary used by smoke (gitignored) |
docs/cli.md | CLI architecture overview |
Auxiliary content
- references/original-guide.md — operational reference (principles + primary workflow)
- references/workflow.md — step-by-step for adding a command
- references/graph.md — handoff to
add-api-endpoint,release-cli,testing-infra - scripts/cli-preflight.sh — Go test + build + version sanity; run before any CLI release work
- scripts/list-cli-surfaces.sh — maps current CLI commands to OpenAPI endpoints; run when auditing coverage gaps
- assets/cli-command-plan-template.md — template for designing a new CLI command (subcommands, flags, output shape)
- assets/evals/basic.json — eval cases for skill regression