CLI Reference

Sparkwing ships a single sparkwing binary. This page is a map of what each command group is for; the complete, auto-generated listing of every command, flag, and argument lives in cli-reference.md, one cli-<group>.md page per command group (offline: sparkwing docs read --topic cli-reference, or --topic cli-<group> for one group). Treat that generated reference as authoritative -- when this page and it disagree, it wins.

The CLI compiles pipelines, manages local state, and coordinates admission. A compiled pipeline binary can also execute on its own; see Headless hosts.

OutputSection anchor link

Commands with --output use pretty on stdout terminals and compact JSON when stdout is redirected. --output pretty|json|plain (or -o) overrides the default. JSON reports occupy one line; JSON lists emit one object per line, with an empty stream for no results. Errors go to stderr.

Help, documentation, onboarding cards and completion scripts emit records with kind and text in JSON mode. Help also carries command metadata. Use explicit plain output when consuming their original text:

source <(sparkwing completion --shell zsh --output plain)
sparkwing docs read --topic pipelines --output plain | less
sparkwing info --for-agent --output plain
sparkwing commands --format markdown --output plain

commands --format markdown --split-dir DIR writes reference pages into files and reports the result in the selected output mode. Supported output modes are pretty, json, and plain.

Cache JSON reports expose their fields directly through .entries and similar fields. Cache failures return a nonzero status with no stdout record. Plain cache output is the cache directory for cache info, the key for cache explain, and the reclaimed entry count for cache prune.

sparkwing runSection anchor link

sparkwing run <pipeline> [flags...]

Compiles and runs a pipeline from the nearest pipeline directory. Runner controls use --sw-*; an unknown option with that prefix fails before execution setup. Other arguments pass to the pipeline. Put -- before pipeline arguments that resemble runner controls. Every argument after the separator passes through unchanged.

The runner also consumes --profile, -C, -v, and the explicit --dry-run=true and --dry-run=false forms before the separator. --target passes to the pipeline.

--sw-allow is enforced by the CLI before it dispatches a foreground run. A step declares its labels in Go, so the CLI builds the .sparkwing/ binary first and weighs the declarations that build emits, on every invocation. The labels you authorize are forwarded to the run as SPARKWING_ALLOW (comma-separated) so the run's own record shows what was authorized -- setting that variable by hand authorizes nothing, because the gate has already run by then.

A queued run of a pipeline that declares a risk is refused. The trigger carries no allow, so the launch weighs the declarations before it persists the run, and weighs what the run will execute: the --sw-ref worktree when the launch names a ref, the binary an armed schedule pinned, the working tree otherwise. A scheduled run goes through the same submission and is refused the same way. sparkwing runs retry is not weighed yet: it re-queues the source run's own declarations, so a retry of a risk-declaring run is not refused. Run a risk-labeled pipeline in the foreground, where --sw-allow authorizes it.

--profile NAME selects the storage and dispatch addressing (state/cache/logs, and any controller auth). Execution still happens locally; to hand a run to a cluster, use sparkwing pipeline trigger for remote execution.

Command groupsSection anchor link

Top-level groups, each with its own --help and a full per-group page indexed in cli-reference.md:

GroupFor
infoAgent entrypoint card: what sparkwing is, what's in this repo, what to run next
pipelineThis repo's pipelines: list / describe / discover / new / explain / run / trigger / hooks / sparks
runShortcut for pipeline run (the positional form)
runsInspect and manage runs: list / status / logs / retry / cancel, plus approvals and triggers
reposThe machine's fleet of sparkwing repos and their SDK pins: list / info / update
queueLocal admission: holders, connections, waiters, capacity
daemonThe local admission daemon: status / restart
profileShow which profile would resolve for this invocation, and why (read-only; never prints tokens)
versionComposite CLI + SDK + sparks version card; update --sdk bumps the pinned SDK
updateSelf-update the sparkwing CLI binary
dashboardDetached local dashboard server: start / kill / status
doctorDiagnose and repair local state, including unsafe private-home permissions and records whose processes have exited
cloudConnect this machine to a controller: connect / status / disconnect
clusterCluster ops against a profile's controller: status / agents / worker / gc / users / tokens / image / webhooks / concurrency
secretsSecrets, laptop dotenv or controller-stored with --profile: set / get / list / delete
configureLaptop-local config: init / profiles / xrepo
debugInteractive run debugging: run / release / attach / env / rerun / replay
docsThe embedded copy of this doc tree: list / read / all / search
examplesThe worked-pipeline registry; --name <example> --body prints the source
commandsThe full CLI surface as JSON (agent self-discovery)
completionShell completion script (--shell bash|zsh|fish)

ConventionsSection anchor link

  • Structured output. List / describe / get verbs accept -o pretty|json|plain (pretty on terminals, JSON when piped). -o / --output is the one output-format selector across the CLI.
  • List output is one record per line. A listing's -o json is NDJSON: one complete JSON object per line, no array and no pretty-printing, so head -5 returns five whole records instead of a truncated document that parses as nothing. Read the stream a line at a time (json.Decoder in a loop, jq -c . with no -s, while read line, and similar readers). An empty listing is an empty stream. Describe, get, and status verbs return one compact JSON object.
  • Profile addressing. --profile NAME picks the storage/dispatch profile. Absent, commands read local state (SQLite under ~/.sparkwing/). sparkwing run always executes locally; sparkwing pipeline trigger is the verb for remote (cluster) execution.
  • Required flags. Marked [required] in --help; missing ones fail before any side effect.
  • Hidden entries. Pipelines marked hidden: true don't appear in pipeline list or tab-complete but stay invocable by exact name. Pass --all to pipeline list to see them.

Agent discoverySection anchor link

Use the command index to find a command, then read its help:

sparkwing commands --query status
sparkwing runs status --help
sparkwing pipeline list -o json
sparkwing pipeline describe --name fictional-build -o json
sparkwing pipeline discover --query fictional-build -o json

Command records carry path, synopsis, and subcommand_count. Help supplies descriptions, flags, and examples. Hidden commands require --include-hidden. See Bounded discovery for pagination.

The describe schema matches sparkwing.DescribePipeline plus group / tags / triggers drawn from the pipelines: block in .sparkwing/sparkwing.yaml.

Headless hostsSection anchor link

A runner host does not need the sparkwing CLI. Ship it the compiled pipeline binary (a plain go build of your .sparkwing/ module), invoke pipelines by name, and inspect local state through the binary's own ops verbs:

./pipelines <name>
./pipelines ops queue
./pipelines ops doctor
./pipelines ops stats
./pipelines ops stats-reset
./pipelines ops version

The ops verbs share the CLI's output conventions -- -o pretty|json|plain, the same JSON shapes as sparkwing queue / sparkwing doctor -- so a script written against the CLI works unchanged against the binary. Use these commands to inspect a host and repair abandoned state.

One thing a bare pipeline binary does not do is host the admission daemon. The installed Sparkwing distribution owns daemon lifecycle. Pipeline clients declare required capabilities and use the running daemon; they never host, replace, or upgrade it. A run's client spawns the binary named by SPARKWING_WINGD_BIN -- which sparkwing run sets to its own path -- else the sparkwing found on PATH.

With neither present, a run says so once and proceeds without host arbitration -- fine for a host that runs one pipeline at a time. .Concurrency() groups still hold, through the shared store instead of the daemon. The exception is a pipeline that reserves host capacity with .Resources(): that run fails instead, naming the fix, because CPU and memory have no fallback arbiter (SPARKWING_ALLOW_UNADMITTED=1 overrides it if you know what else runs on the box). Put the CLI on the box when concurrent runs there should queue against each other -- see local-execution.md.

Bounded discoverySection anchor link

Use sparkwing commands --query status to find a command by path or synopsis, then read that command's --help. The index sorts command paths lexically and returns at most 40 command records. --path restricts a subtree before query filtering and pagination. Child counts describe the full visible registry, even when a child is outside the current page.

docs list --query <topic> returns at most 40 topic metadata records. docs search --query <question> ranks matching sections before choosing its 20-result page. Search records include a short snippet, without body content. Read a selected hit with docs read --topic <slug> --section <start_line>. Section selectors refer to the embedded docs in this binary; they do not apply to web documents or multi-topic guides. --body on search explicitly includes the bodies of the selected page.

All three indexes emit compact NDJSON by default when piped. A final kind: "page" record reports total, returned, limit, truncated, and next_cursor when another page exists. Pass that cursor with --cursor, keeping the same filters and binary version. Command/topic cursors name the last lexical path/slug; search cursors name the last ranked section as slug:start_line. An unknown cursor fails instead of silently restarting. Metadata records retain their existing selection fields; readers must recognize the final page record separately from command and topic records.

--limit 0 explicitly returns every remaining match. Plain mode prints paths or selectors only; continuation information goes to stderr. Pretty mode includes a short page footer. Explicit commands --format markdown exports the exhaustive reference and rejects query/pagination flags; a --path export still selects the requested subtree. Use --output plain when redirecting the Markdown artifact to a file.