020 · CLI
Command-line interface (spec_cli_020)
| Status | Implemented. Reverse-engineered from 53f8c53 (2026-09-24) and kept with the code since; its paths and names checked 2026-09-27 (//tools/specs). |
| Source | apps/cli/main.go, exitcode.go, oneshot.go, setup.go, configcmd.go, doctor.go |
| Tests | apps/cli/main_test.go, images_test.go, locale_test.go |
| Related | spec_config_002, spec_workspace_018, spec_tui_019, spec_service_021, spec_workers_023 |
blitz (also blz, a link to it in the release archives) is a single static Go binary. With no prompt it starts an interactive REPL in a workspace; with a prompt it runs one turn and exits. Subcommands cover diagnostics, configuration, the per-user service and workers.
| Command | Purpose |
|---|---|
blitz [flags] [prompt...] |
REPL, or a one-shot run when a prompt is given |
blitz exec [flags] <prompt...> |
Always a one-shot run; no prompt is a usage error |
blitz doctor [--online] |
Health checks (§7) |
blitz auth status, `blitz auth login <google |
anthropic |
blitz config init [--force] | path | show |
Configuration file management (§8) |
blitz serve [...] |
Hidden: runs blitzd, the per-user service, with the same arguments (spec_service_021 SVC-00) |
blitz service install | uninstall | status |
Login item for the service |
blitz workers [list] | enable <name> [-y] | disable <name> | run <name> | runs <name> [-n N] | undo <run-id> [-f] |
Workers (spec_workers_023) |
blitz mcp add <name> <command|url> [--env K=V] [--header K:V] [--prefix p] [--agents a,b] | list | get <name> | remove | enable | disable | login | logout <name> |
MCP servers in the user’s settings (spec_mcp_009 MCP-03, MCP-38) |
blitz license [full|third-party] |
The NOTICE (with pointers to the rest), the Apache License, or the third-party notices, paged on a terminal; the REPL’s /license shows the same (spec_release_readiness_030 RR-05) |
blitz completion bash|zsh|fish|powershell |
Cobra-generated shell completion |
Persistent (all commands): -c/--config DIR (config directory, default ~/.blitz), -d/--dir DIR (workspace; default the current directory).
Run flags (root and exec):
| Flag | Meaning |
|---|---|
-p/--prompt TEXT |
One-shot prompt; - reads stdin |
-a/--agent NAME |
Agent to activate |
-m/--model NAME |
Model (may be provider/model) |
--agency low|medium|high|extreme |
Agency level (lower-cased) |
--trust-project |
Trust the workspace’s project settings for this run, without recording it (spec_project_config_031); --trust-workspace is a hidden alias |
-r/--resume [ID|NAME] |
Resume a session by ID; bare -r means latest; a snapshot name starts a new session from it |
-C/--continue |
Continue this workspace’s most recent non-snapshot session |
--output-format text|json|stream-json |
One-shot output format (default text) |
--input-format text|stream-json |
stream-json: stdin carries JSON lines driving the session (CLI-07); needs --output-format stream-json |
--json-schema FILE|JSON |
The answer must be JSON valid against the schema (CLI-08) |
--no-session-persistence |
Keep nothing of the run’s session (CLI-09) |
--fork |
With --resume/--continue: continue in a copy (spec_sessions_017 SES-20) |
--name TITLE |
Name the new session |
--append-system-prompt TEXT, --append-system-prompt-file PATH |
Add to the agent’s instructions for the run, in a service of its own (spec_memory_012 MEM-41) |
--max-turns N |
Cap model calls in a one-shot run (0 = unlimited) |
--max-cost-usd N |
Stop a one-shot run once it has cost more than N USD (0 = unlimited; needs a priced model, else a warning) |
--timeout D |
Stop a one-shot run after D (e.g. 15m; 0 = unlimited) |
--plan |
One-shot plan-only run (read-only tools) |
--local |
Run in a service of the run’s own (a private blitzd), not the shared one (CLI-14) |
--allow RULE, --deny RULE |
Add permission rules for this run (repeatable; read(…) can’t be given this way) |
--effort LEVEL |
Session reasoning effort (minimal…max; otherwise a usage error). Attached, it changes the service workspace’s effort |
--permission-mode MODE |
Start in default, accept-edits, plan, dont-ask or bypass (needs the OS sandbox; otherwise a usage error). Attached, it changes the service workspace’s mode |
--image PATH |
Attach an image to the first prompt (repeatable) |
Root only: -i/--interactive (REPL even with a prompt), -v/--version (prints Blitz Go (Google ADK) version <v>; version stamped into release builds from the git tag (bazel build --config=release), dev otherwise).
- CLI-01 If
-p -is given, or no-pand stdin is not a TTY and-iis not set, the prompt is read from stdin (max 10 MiB) and trimmed. - CLI-02 Positional arguments frame piped input:
args + "\n\n" + pipedwhen both exist; args alone or piped alone otherwise. - CLI-03 Empty stdin when stdin was to be read is a usage error (“stdin was empty (use -i …)”).
- CLI-04
-p TEXTtogether with positional arguments is a usage error. - CLI-05 A run is one-shot iff a prompt exists and
-iis not set. - CLI-06
--plan, a non-text--output-format, or any of--max-turns/--max-cost-usd/--timeoutwithout a one-shot prompt is a usage error. Negative limits and an unknown--output-formatare usage errors. - CLI-07
execwith no prompt from any source is a usage error.
- CLI-10
--diris expanded (~), made absolute, and must be an existing directory, else usage error. The process working directory is never changed; the workspace is passed explicitly (cfg.Tools.WorkspaceDir). - CLI-12a
--worktree[=name](-w; the name only after=, since a word after a space is the prompt; no name:wt-<date>-<hex>) with--refstarts the run in a new git worktree of the repository--dir(or the working directory) is in:<repo>/.blitz/worktrees/<name>on a new branchblitz/<name>from--ref(defaultHEAD),.blitz/worktrees/added toinfo/exclude, and the untracked files.worktreeincludelists (glob patterns,#comments) copied in (pkg/worktree). The workspace is then the worktree, with its own lock and checkpoints.blitz worktrees list(name, branch, path; “changes not committed” for tracked changes; “folder gone”),remove <name> [--force](the branch stays) andprune(PAR-PAR-10, -12). - CLI-11 Flag overrides are applied after config load:
--model→blitz.default_model,--agent→blitz.default_agent,--agency→blitz.agency_level. Since 2026-10-04 they,--trust-project,--plugin-dir,--add-dir,--append-system-prompt(-file)and--no-session-persistencemake the run one of its own (CLI-14): its private service opens the workspace with them (attached to the shared service they were ignored, and--trust-projectonly warned). - CLI-12 The default
sloglogger discards output until the diagnostic log is installed, so warnings are not duplicated on stderr. - CLI-13 Observability (log file, optional OTel) starts before the workspace opens and is flushed on exit; failures only disable the affected part and print a warning.
- CLI-14 Since 2026-10-04 (the owner’s request: one engine, not two). The CLI runs no workspace itself and doesn’t link the engine (
//tools:check_deps); every workspace is in ablitzd(spec_client_022), which it finds beside itself, in its Bazel runfiles (bazel run), else on PATH. The shared service: it attaches when the socket answers; otherwise it starts the service (its login item when installed, elseblitzd --idle-exit 15mdetached, in the home folder, which stops after 15 minutes with no request, turn or background run) and waits up to 15 s for it. Clients starting it at once take turns through a lock file beside the socket (<socket>.start, created exclusively; one older than 30 s, its holder dead, is taken over): one starts it, the others find it answering. A started service’s output goes to a temporary file, never a pipe to the CLI, which a service outliving it would die writing to (SIGPIPE); the REPL prints a dim “attached” line. A run of its own (--local, and the flags CLI-11 names): a privateblitzdon a socket in a 0700 temporary folder, with--exit-with-stdin(it stops when the CLI exits, however it exits) and the run’s settings as its hidden flags (the prompt in a file there, not on the command line, removed once the service has answered); a private service never runs the workers’ schedules; the CLI attaches to it and stops it and removes the folder at exit. When the shared service has the workspace open and no turn runs there, it’s asked to close it (CloseWorkspace) so the private one can; otherwiseErrWorkspaceBusyis a usage error (“another blitz has it open”).blitz trust,sessions export,memory,models,config permissions checkandworkersgo through the shared service too (ForgetProjectTrust,ExportSession,ListNotes/ForgetNote,ListModels,CheckPermission); the CLI exports no telemetry (the service does) and keeps only its diagnostic log. - CLI-15 If the configured model fails to initialise: one-shot runs fail with exit 1 and “(run ‘blitz doctor’)”; the REPL warns that turns fail until the model works (WS-05).
- CLI-16 Input source: nothing interactive if stdin carried the prompt; the line editor on a TTY in REPL mode (falls back to a plain line reader with a warning); otherwise a line reader whose prompts go to stderr when output is JSON (stdout stays pure JSON). The input is wired as the approver and
ask_user_questionprompter. - CLI-17
--imagepaths are loaded through the workspace sandbox; a failure is a usage error.@pathimage mentions in a one-shot prompt are loaded too, with failures only warned (see spec_images_011). - CLI-18 Session selection follows spec_sessions_017; a
ResumeErroris a usage error. When resuming in the REPL, a green line reports the session (or “branched from snapshot”) and the last 3 messages are recapped; resuming a session whose workspace differs warns. - CLI-19 SIGTERM always cancels the run context; in one-shot mode SIGINT does too. The REPL handles Ctrl+C itself.
- CLI-20
text: a printer renders events (Markdown/spinner only when stdout is a TTY and enabled in[ui]); after the turn a dim usage line goes to stderr when pretty. - CLI-21
stream-json: after the prompt is accepted, emit{"type":"session","session_id","model","agent"}; then one line per event:text(non-thought; withpartial,author),tool_call(name,args),tool_result(name,result); then the result object. - CLI-22
json: a single result object at the end, with tool calls collected (args and matching result by ID+name). - CLI-23 Result object:
type:"result",session_id,result(final model text),is_error,error,exit_code,duration_ms,usage{input_tokens,cached_input_tokens,output_tokens,model_calls},cost_usd(only when priced and ≥1 call),tool_calls. - CLI-24 A
prompt_submithook refusal maps to exit 4; interruption (context cancelled, not max-turns) maps to 130. - CLI-25 Before exit, background processes are handled by
ConfirmExit: prompt only in text mode on a TTY with an input and no cancellation; otherwise they are killed (spec_shell_007).
| Code | Meaning | Mapping |
|---|---|---|
| 0 | success | nil |
| 1 | runtime or model error | default |
| 2 | invalid flags/arguments | withCode(exitUsage, …), cobra flag errors |
| 3 | a limit stopped the run (--max-turns, --max-cost-usd, --timeout) |
api.IsLimit(err): ErrMaxTurns, ErrCostLimit, ErrTimeLimit (also when attached: MAX_TURNS, COST_LIMIT, TIME_LIMIT) |
| 4 | prompt blocked by a prompt_submit hook |
*api.BlockedError |
| 130 | interrupted | errors.Is(err, context.Canceled) |
-
CLI-30 Errors are printed once to stderr via the localized
repl.errormessage; usage is silenced. Flag errors append “Run ‘–help’ for usage.” doctor,--helpand CLI errors are English by policy (see spec_i18n_004). -
CLI-62 2026-10-13 (the owner’s request).
blitz --helpis grouped, each group sorted by name (apps/cli/helpgroups.go): commands in cobra groups (Runs and sessions, The workspace, Models and extensions, Setup and maintenance; none left under “Additional Commands”), and the run’s flags, forblitzandblitz exec, in Session, Agent and model, One-shot run, Permissions and sandbox, Instructions and plugins, then Other flags. Other commands keep cobra’s single Flags list. A test checks every visible command has a group and every grouped flag exists. -
CLI-07
--input-format stream-json(PAR-CLI-03): a one-shot run (the prompt argument is optional) reads JSON lines from stdin:{"type": "user", "text": …}runs a turn (in order, one at a time, after the prompt argument’s),{"type": "approval", "id": …, "decision": "once|session|always|deny"}answers anapproval_requestline (id,tool,kind,detail,diff,targets,key_label,must_ask), and{"type": "answer", "id": …, "answer": …}answers aquestionline (id,question,options). Each turn writes its events and itsresultline as stream-json output does. A line that isn’t JSON, has an unknown type, or answers nothing waiting gets anerrorline; the run goes on. When stdin ends, the queued turns finish, requests still waiting are denied, background processes are stopped, and the run exits with the last turn’s error code.--imageandblitz init’s prompt apply to the first turn only. -
CLI-08
--json-schema(PAR-CLI-02) takes a schema (draft 2020-12 or 07) inline or from a file; an invalid one is a usage error. The prompt sent (not the transcript’s) asks for a single JSON value valid against it; the answer’s JSON (all of it, a fenced block, or the outermost braces or brackets) is validated. If it fails, one more turn in the session gives the error and asks again. The valid value isstructured_resultin json and stream-json results; still invalid, the run fails (exit 1, the error in the result). Providers’ native structured output isn’t used: it would turn off tools for Gemini. -
CLI-09
--no-session-persistence(PAR-CLI-04) keeps the run’s sessions in a temporary folder removed at exit, and runs locally (not in the service); the audit log is written as usual. With--resumeor--continue, or without a prompt, it’s a usage error, as is--json-schemawithout one.
- CLI-40 The completer registers every slash command and fixed sub-arguments (
skills list|show|search,session list|new|load|save,search web|session,envs prune|remove,memory show|reload|add,approvals revoke|clear,diff git,attach clear,undo --force,set agency=). - CLI-41 Dynamic sources: agent names (
/agent,/pin_model); pinned agents (/unpin); models in use plus models with settings (/model_settings); locale tags (/locale); the 20 newest workspace session IDs plus all snapshot names (/resume).@pathcompletion is provided by the TUI completer.
- CLI-49 Since 2026-10-04
blitz doctorrunsblitzd doctorwith the run’s--config,--dir,--model,--agent,--agency,--plugin-dir,--add-dirand--online, passing its output and exit code through: the checks build models, sandboxes and MCP clients, which only the service carries (apps/service/internal/doctor). It needs no running service; withoutblitzdit’s a usage error. - CLI-50
doctorprints one line per check:✓(ok),!(warn),✗(fail), name padded to 16. Exit 1 if any check failed. - CLI-51 Checks, in order: config file (exists; warn if group/other-readable); config parse; skills (policy problems, parse failures, scripts blocked by policy, script sandbox in use); credentials for the provider (Gemini or Anthropic with
adc: a project is required, and the credentials file ofGOOGLE_APPLICATION_CREDENTIALSor gcloud’s login is looked for, a warning without one; Anthropic withoauth: the profile’s credentials must exist; otherwise Anthropic may rely onANTHROPIC_AUTH_TOKENor a login profile; Ollama needs none; otherwise a missing key fails; keys shown maskedabc…wxyz); pricing for the active model; log level/dir; telemetry endpoint and content capture; the primary model, each fallback (warn, not fail) and each[agent_models]pin;bash(fail if missing) andgit(warn); workspace and shell sandbox status; web search provider; each MCP server (command on PATH); hooks (first word resolvable); session dir permissions; audit log; project memory files found. - CLI-52
--onlineadditionally sends"Reply with the single word: ok"(max 16 output tokens, 30 s timeout) to each model separately (never through the fallback chain), runs a test web search (“Go programming language”, 3 results), and connects to each MCP server to count its tools (20 s timeout).
- CLI-60
config initwrites a commented template to<configdir>/.env.tomlwith mode 0600 (dir 0700); refuses to overwrite without--force(usage error); the template is validated as TOML before writing. - CLI-61
config pathprints the file location;config showprints the effective configuration as TOML with Gemini/OpenAI/Anthropic keys and every MCPenvvalue masked.
- A
blz refactorcommand is proposed but not designed.