CLI Reference

Every command, flag, and resolution rule. Install and operate tracker from the terminal.

Install

# Go install (binary includes embedded workflows)
go install github.com/2389-research/tracker/cmd/tracker@latest

# Homebrew
brew install 2389-research/tap/tracker

# Or build from source
git clone https://github.com/2389-research/tracker
cd tracker && make install

# Verify installation
tracker doctor

# Stay current (checks automatically, or run manually)
tracker update

Commands

Running Pipelines

tracker <pipeline>
Run a pipeline. Accepts a file path (build_product.dip, build.dipx), bare name (build_product), or path with slash. .dipx bundles are SHA-256-verified at load time and the bundle identity is threaded through every audit surface. .dipx v0.26.0 Opens TUI dashboard by default.
tracker -r <id> <pipeline>
Resume a previous run by ID. Prefix matching works — -r 7813b is enough if unambiguous. A run that halted at a fail-closed dead end it reached by fail-routing (a node whose only continuation is the exit — e.g. build_product's Setup → AbortRun) rewinds to the node that failed, so fixing the cause and resuming retries that step instead of re-running the terminal. A fail-routed node with real onward routing (a Fix step that loops back to Test) is retried in place. --from <node> re-enters at an explicit node; --resume-no-rewind resumes exactly at the checkpoint's current node.
tracker --no-tui <pipeline>
Run in console mode (no dashboard). Human gates use inline prompts. Auto-selected when stdin is not a TTY.
tracker --json <pipeline>
Stream events as newline-delimited JSON to stdout. Implies --no-tui. For CI/programmatic consumption.

Workflow Management

tracker workflows
List all embedded built-in workflows with display names and goals. The starters (explain, quickfix) come first, tagged ★ start here (WorkflowInfo.StartHere). v0.81.0
tracker init <name>
Copy a built-in workflow to ./name.dip in the current directory, together with its whole prompts/name/ and scripts/name/ subtrees (including sourced scripts/name/lib/ helpers, minus the *_test.sh fixture suites) plus every file its prompt_file / command_file directives reference elsewhere — the same set an embedded run materializes, so ${graph.workflow_dir} resolves the copy identically (and a starter SPEC.md for workflows that need one). Refuses to overwrite existing files.

Validation & Simulation

tracker validate <pipeline>
Check pipeline structure — parsing, structural validation, semantic validation, lint. Exits 1 on errors. Supports bare names. Accepts .dip, .dot, and .dipx bundles. .dipx v0.26.0
tracker simulate <pipeline>
Dry-run execution plan. Shows nodes, edges, BFS traversal, unreachable nodes, and graph-level attrs (sorted, deterministic). No LLM calls. It analyzes the same finalized topology a run executes, so a graph that breaks its execution-critical invariants (e.g. an edge to an undeclared node) fails here too; full structural checks are tracker validate. Supports bare names. Accepts .dip, .dot, and .dipx bundles. .dipx v0.26.0
tracker estimate <pipeline>
Rough pre-run cost & scale ballpark v0.46.0 — prices each agent node's model against a turn heuristic and reports steps, agent-node count, distinct models, and a Low–High cost range with an expected value (e.g. build_product → $0.65–$10.02, expected ~$3.56). No LLM calls; supports bare names. A deliberately wide range — actual cost depends on how many turns each agent uses and how many times loops run. Reads only the config .env (like tracker version), never the current directory's, so the TRACKER_OPENAI_AUTH switch is visible to pricing; an openai node prices at $0 when it's set to chatgpt, noted in the output v0.80.0.
tracker verify-tests [dir] [--race] [--coverage]
Test-fidelity gate v0.54.0 — scans Go test bodies under dir (default cwd) and flags groups that are byte-for-byte identical or identical except for literal values, so a “distinct” test that copies another's body can't hand out false coverage credit. Exits 1 when any duplicate group is found — drop it into a VerifyMilestone tool node. With --race, also runs go test -race ./... and fails on a detected data race or a suite that won't pass under the race detector; the race pass is opt-in and Go-only — skipped (not failed) when there is no go.mod/go.work or no go toolchain, and reported as a skip when cgo or the race detector is unavailable on the platform. It also prints an advisory v0.69.0 structural near-duplicate report — reordered/renamed copies calling the same production symbols that the literal-strip hash misses — which never affects the exit code. With --coverage, an opt-in, advisory per-test coverage-attribution pass additionally flags tests that execute zero production code (assert on a copy / path guarded out) and test-local functions that re-implement uncovered production logic; it is heavyweight (one go test run per test), Go-only, skips cleanly like --race, and never fails the gate.

Headless & Integration

tracker --webhook-url <url> <pipeline>
Fully headless. Every human gate is POSTed as JSON to <url>; the pipeline blocks until a callback arrives at the local callback server. Slack bots, email approval, mobile push. Mutually exclusive with --autopilot and --auto-approve. v0.17.0
tracker --param key=value <pipeline>
Override a workflow's top-level vars (available as ${params.key}). Repeatable. Unknown keys hard-fail at startup. v0.19.0
tracker --export-bundle <path> <pipeline>
After the pipeline completes, package the full artifact run directory as a portable git bundle (git bundle create --all). Clone with git clone <bundle> on any machine to inspect every commit and checkpoint tag. v0.17.0
tracker --gateway-url <url> <pipeline>
Route every provider through a Cloudflare AI Gateway. Tracker appends the per-provider suffix (/anthropic, /openai, /google-ai-studio, /compat). Equivalent to TRACKER_GATEWAY_URL. Per-provider *_BASE_URL env vars still win. v0.17.0

Autopilot

tracker --autopilot <persona> <pipeline>
Replace all human gates with LLM-backed decisions. Personas: lax, mid (default), hard, mentor.
tracker --auto-approve <pipeline>
Deterministic auto-approval of all human gates. No LLM calls — always picks the default or first option. For CI and testing.

Diagnostics

tracker doctor [pipeline]
Preflight health check, aware of which backends a pipeline needs: provider API key validation (masked; a key is only required when something runs on the native backend), dippin binary version, .ai/ writability, disk space, .gitignore hygiene, a warning when .env is tracked by git, and environment warnings with provenance (TRACKER_PASS_ENV=1 (from shell), TRACKER_GATEWAY_URL=… (from ~/.config/tracker/.env), and every name a .env file tried to set that its tier doesn’t allow, reported as ignored) v0.78.0. Live per-provider auth validation with a 1-token call runs by default; pass --probe=false to skip it. Under TRACKER_OPENAI_AUTH=chatgpt, the openai line reports the ChatGPT subscription sign-in instead — plan and signed-in state, plus a refreshed access token under the live probe, never OPENAI_API_KEY, OPENAI_BASE_URL or a gateway URL, and never the account ID or email v0.80.0. Its notes that those settings don’t apply to openai (a gateway still routes the other providers) and that dollar ceilings don’t count subscription calls are hints, so they never cause exit code 2. Also takes --backend (the agent backend to check), --git / --allow-init (evaluate a git preflight policy), --env-files, and -w / --workdir. Optional pipeline arg runs full lint and warns when a node pins a model that dippin marks retired on its first-party provider API (still billable via a Bedrock/Vertex passthrough) — suppressed when a gateway is configured (TRACKER_GATEWAY_URL/TRACKER_GATEWAY_KIND), since the model then routes to a passthrough. v0.63.0 Exit code 2 on warnings-only. v0.17.0 With a pipeline, the provider-key check passes when no agent node needs the native backend (all claude-code, or auto with claude available), and claude is required when a node needs it (#716). A missing dippin binary is a warning: it is only needed to lint or edit .dip files. Bare tracker doctor with Claude Code and no API key warns instead of failing and says which workflows need a key; doctor --backend claude-code with no pipeline passes. Doctor shows the resolved claude path and its source (TRACKER_CLAUDE_BIN or PATH), warns when several claude binaries are on PATH (listing each version), and fails on a broken TRACKER_CLAUDE_BIN when a node needs claude. v0.81.0
tracker diagnose [runID]
Deep failure analysis. Reads status.json + activity.jsonl. Shows tool output, stderr, errors, timing anomalies, actionable suggestions (deterministic failure pattern, escalation hit, suspicious timing, budget halt). Without ID, analyzes the most recent run.
tracker status [runID]
Agent-authored high-level timeline of a run #494 — the status updates agents wrote as they worked, in order, for a fast “what happened” read. Without an ID, uses the most recent run.
tracker audit <runID>
Full audit report: timeline, retries, errors, recommendations. For post-hoc analysis of any run.
tracker list
List recent pipeline runs with timestamps, status, and node count.
tracker run-json [runID]
Assemble the run.json manifest for a run directory from its captured audit log — goal, terminal status, per-node kind/attempts/outcome/turns/usage, run totals, tool-call and event counts, and spec identity. v0.50.0 Works after the fact, so a SIGKILLed run (which ran no in-process finalizer) or a run archived before the manifest existed both get one. Without an ID, targets the most recent run.

Setup

tracker setup
Interactive provider configuration wizard. Saves keys to ~/.config/tracker/.env. OpenAI's page has an Auth choice v0.80.0: API key, or ChatGPT subscription, which signs in with a device code — open the link setup shows on any device and enter the code within 15 minutes. Setup saves the sign-in to ~/.config/tracker/chatgpt-auth.json (mode 0600) and writes TRACKER_OPENAI_AUTH=chatgpt; picking API key later writes api-key. Sign in only with your own ChatGPT account, on your own machine.
tracker version
Show version, commit hash, build time, and configured providers. Provider status reflects the shell and ~/.config/tracker/.env only — this command never loads a .env from the current directory v0.78.0.
tracker update
Self-update to latest release. Downloads from GitHub, verifies SHA256 checksum, smoke-tests the binary, and atomically replaces with .bak rollback. Detects Homebrew and go install and advises accordingly.

Flags

Flags can appear before or after the pipeline argument.

FlagDescriptionDefault
Execution
-w, --workdirWorking directory for the pipeline runCurrent directory
-r, --resumeResume a previous run by ID (prefix match). If the run halted at a fail-closed dead end it reached by fail-routing, resume rewinds to the node that failed—
--fromWith -r: re-enter the run at this node, re-running it and everything downstream. Must be a node the run reached (completed or current); refused otherwise—
--resume-no-rewindWith -r: resume exactly at the checkpoint's current node (no automatic rewind past a fail-closed terminal)Off
--force-bundle-mismatchAllow resume when the .dipx bundle identity differs from the original runOff
--gitGit preflight policy: auto (default) | off | warn | require | initauto
--allow-initLatch permitting --git init to initialize a repo in the working directoryOff
--artifact-dirOverride node state directory v0.19.0. -r looks the run up here and fails if it is not there, so resume with the same --artifact-dir (and -w) the run used; the printed resume command includes bothDerived from run
--paramOverride workflow vars (repeatable): --param key=value v0.19.0—
--formatPipeline format override: dip or dotAuto-detect from extension
--backendAgent backend: native, claude-code, or acp. An explicit value also overrides backend: auto nodes; auto itself is a node value only (--backend auto is rejected).native
Output
--jsonStream events as NDJSON to stdoutOff
--no-tuiDisable TUI dashboard, use console modeTUI on (if TTY)
--verboseShow raw provider stream eventsOff
--export-bundleAfter the run, write a portable git bundle of run artifacts to the given path v0.17.0—
Gate handling
--autopilotLLM judge persona: lax, mid, hard, mentorOff (human gates)
--autopilot-modelModel the --autopilot judge uses for gate decisions; requires --autopilot. Set it to a model your ChatGPT plan serves when TRACKER_OPENAI_AUTH=chatgpt v0.80.0The default provider's autopilot model
--auto-approveDeterministic auto-approve (no LLM)Off
--webhook-urlPOST gate prompts to this URL and wait for callback v0.17.0—
--gate-callback-addrLocal addr for the inbound callback server:8789
--gate-timeoutHow long to wait for a webhook callback per gate10m
--gate-timeout-actionWhat to do on gate timeout: fail or successfail
--webhook-authAuthorization header on outbound webhook POSTs—
Budget ceilings v0.17.0
--max-tokensHalt if total tokens exceed this—
--max-costHalt if total cost (cents) exceeds this—
--max-wall-timeHalt if wall-clock runtime exceeds this (e.g. 30m)—
--sleep-aware-budgetExclude detected OS-suspend spans (e.g. a closed laptop) from --max-wall-time and stall budgetsoff
Provider routing & tool safety
--gateway-urlRoute every provider through a Cloudflare AI Gateway root URL; equivalent to TRACKER_GATEWAY_URL. See the gateway routing guide for the AWS Bedrock recipe. v0.17.0—
--gateway-kindGateway path convention: cf-aig (default) or bedrockcf-aig
--tool-allowlistRestrict tool commands to glob patterns. Repeatable; each value can be a comma-separated list. Additive with the tool_commands_allow graph attr. Never overrides the denylist. v0.23.0—
--tool-denylist-addExtend the built-in tool-command denylist with extra glob patterns. Repeatable; each value can be a comma-separated list. Additive only — cannot remove built-ins. Pairs with the tool_denylist_add graph attr. --bypass-denylist still disables everything. v0.24.1—
--bypass-denylistDisable the built-in denylist for dangerous tool commands (eval, pipe-to-shell, curl | sh). Loud stderr warning on startup. Use only in sandboxed environments where dangerous patterns are intentional. v0.23.0Off
--max-output-limitHard ceiling (bytes) on per-stream tool output size; caps per-node output_limit attrs. When a stream exceeds its cap, tracker keeps the tail (last limit bytes) so routing markers like printf 'tests-pass' emitted at end-of-output survive truncation. tracker diagnose surfaces a tool_output_truncated suggestion. v0.23.0 tail-window v0.27.00 (effective 10 MB)
--env-filesWhich .env files tracker run / tracker doctor load: all (config file, then project file), config (~/.config/tracker/.env only), or none. The shell-only TRACKER_ENV_FILES is the env equivalent; the flag wins. See Environment variables for what each file may set. v0.78.0all
Exit codes
--fail-on-overrideExit code 2 when the run terminates as validation_overridden. Default behavior exits 0 (an override is a deliberate operator decision). Equivalent to TRACKER_FAIL_ON_OVERRIDE=1; the flag wins. See the Exit codes section. v0.35.0Off
Misc
--helpCommon flags only — the short reference for everyday runs—
--help-allFull flag reference, grouped by concern (budget, gateway, gates, artifacts, tool safety) v0.66.0—
--versionShow version info—

Exit codes v0.35.0

tracker run uses three distinguishable exit codes so CI integrations can branch on terminal status without parsing stdout.

CodeMeaning
0Run completed. Terminal status is either success or validation_overridden.
1Run failed or was halted by a budget guard. Terminal status is fail or budget_exceeded.
2Run completed as validation_overridden and --fail-on-override (or TRACKER_FAIL_ON_OVERRIDE=1) was set. Lets CI distinguish operator-accepted overrides from clean successes without scraping output.

Generic failures dominate --fail-on-override: a run that fails after an override exits 1, not 2. Without the flag, override runs exit 0 — an override is a deliberate operator decision and the default treats it as audit-positive. CI pipelines that should NOT auto-deploy on overrides must opt in:

tracker --fail-on-override workflow.dip && deploy.sh

Tool safety in pipeline files v0.23.0

The denylist, allowlist, and per-stream output ceiling are enforceable from a pipeline file as well as CLI flags. CLI values and graph attrs union; the denylist always wins.

Graph attributeNotes
tool_commands_allowComma-separated globs restricting every tool node's command to match at least one pattern. Unions with --tool-allowlist; cannot override the denylist.
tool_denylist_addComma-separated globs added to the built-in denylist for every tool node. Unions with --tool-denylist-add; strictly additive (cannot remove built-ins). v0.24.1

Example, DOT form:

digraph G {
  // Only git and make commands are allowed in tool nodes.
  graph [tool_commands_allow="git *,make *"];
  Setup [handler="tool", tool_command="git init"];
  Build [handler="tool", tool_command="make build"];
  Setup -> Build;
}

As of dippin-lang v0.23.0+, both attributes are exposed via a defaults: block in a .dip file (defaults: tool_commands_allow: "git *,make *"). The DOT form above and the library API (graph.Attrs["tool_commands_allow"]) remain equivalent ways to set them.

Name resolution

When you run tracker build_product (bare name, no path, no extension), the resolver checks in this order:

  1. Explicit file path

    If the name contains / or ends in .dip/.dot/.dipx, treat as a filesystem path. No further resolution.

  2. Local .dip file

    Check if build_product.dip exists in the current directory. Local files always win.

  3. Bare file

    Check if build_product exists as a file in the current directory.

  4. Embedded workflow

    Look up build_product in the built-in workflow catalog. If found, load from go:embed.

  5. Error

    Print "unknown pipeline" with a list of available built-in workflows.

This applies uniformly to tracker run, tracker validate, and tracker simulate.

Environment variables

Provider keys

VariableProviderNotes
ANTHROPIC_API_KEYAnthropicRequired for claude-* models
ANTHROPIC_BASE_URLAnthropicCustom endpoint (proxies, etc.)
OPENAI_API_KEYOpenAIRequired for gpt-*, o* models
OPENAI_BASE_URLOpenAICustom endpoint
GEMINI_API_KEYGeminiRequired for gemini-* models
GOOGLE_API_KEYGeminiAlternative to GEMINI_API_KEY
GOOGLE_BASE_URLGeminiNot read by Tracker; stripped from claude and (with TRACKER_STRIP_ACP_KEYS=1) ACP children with the other base URLs
OPENROUTER_API_KEYOpenRouterNot read by Tracker; stripped from ACP children with TRACKER_STRIP_ACP_KEYS=1
GEMINI_BASE_URLGeminiCustom endpoint
OPENAI_COMPAT_API_KEYOpenAI-compatRequired for the openai-compat provider (any OpenAI-compatible endpoint)
OPENAI_COMPAT_BASE_URLOpenAI-compatEndpoint for the openai-compat provider. Unset, the adapter default is OpenRouter (https://openrouter.ai/api). Like every per-provider *_BASE_URL, it wins over TRACKER_GATEWAY_URL.

Variables come from three sources with different trust, and each source may set only the names its trust allows (v0.78.0, env trust policy):

Every other name — TRACKER_PASS_ENV, TRACKER_PASS_API_KEYS, TRACKER_STRIP_ACP_KEYS, TRACKER_CLAUDE_BIN, TRACKER_FAIL_ON_OVERRIDE, TRACKER_AUDIT_DIR, XDG_STATE_HOME, HERDR_*, PATH, HTTPS_PROXY, SSL_CERT_FILE, LD_PRELOAD, and any name tracker does not read — is shell-only: a file that sets one is skipped for that key with a single stderr line naming the file, the key and where it belongs, and tracker doctor lists the attempt. A symlinked .env and a group/world-writable .env (config or project) are skipped whole. tracker version reads the config file only, never the current directory. The full registry is internal/envpolicy in the source tree.

Tracker runtime knobs

VariableDefaultNotes
TRACKER_GATEWAY_URL—Equivalent to --gateway-url. Tracker appends per-provider suffixes (/anthropic, /openai, /google-ai-studio, /compat). Per-provider *_BASE_URL still wins. v0.17.0
TRACKER_GATEWAY_KINDcf-aigEquivalent to --gateway-kind: the gateway path convention, cf-aig (Cloudflare AI Gateway suffixes) or bedrock. The flag wins. Config .env or shell. v0.36.0
TRACKER_OPENAI_AUTHapi-keyopenai auth mode: api-key (default) or chatgpt — bill openai calls to your ChatGPT subscription after signing in with tracker setup. Config .env or shell. v0.80.0
TRACKER_CLAUDE_BINunsetAbsolute path of the claude binary for every claude-code use: --backend claude-code, backend: claude-code / auto nodes, the claude-code autopilot and tracker doctor. Overrides the PATH lookup, so a stale claude earlier on PATH no longer wins (#719). It must be an executable file; a wrong value fails with its path and never falls back to PATH (under backend: auto the node refuses to start instead of moving to an API key). Every run names the binary it used, and tracker doctor warns when several claude binaries are on PATH. Shell-only: a .env file cannot set it. v0.81.0
TRACKER_PASS_API_KEYSunset--backend claude-code only (and the claude-code autopilot). Set to exactly 1 to keep Tracker's five provider keys (ANTHROPIC_API_KEY, OPENAI_API_KEY, OPENAI_COMPAT_API_KEY, GEMINI_API_KEY, GOOGLE_API_KEY) and their base URLs (ANTHROPIC_BASE_URL, OPENAI_BASE_URL, OPENAI_COMPAT_BASE_URL, GEMINI_BASE_URL, GOOGLE_BASE_URL) in the claude subprocess env. By default exactly those ten names are removed so the CLI bills to Max/Pro subscription auth instead of the API key, and doesn’t send that login to a gateway set for the native backend (#677). Routing claude through a gateway on purpose takes this switch: key and base URL together. This is a billing control, not a confinement boundary: every other variable passes through, and the Bash commands, hooks and MCP servers claude starts inherit what claude received (see CLAUDE_CODE_SUBPROCESS_ENV_SCRUB). The ACP backend does not read this variable — see TRACKER_STRIP_ACP_KEYS. Shell-only: a .env file cannot set it. v0.13.0
TRACKER_STRIP_ACP_KEYSunset--backend acp only. Set to exactly 1 to remove eleven provider key and base-URL names (ANTHROPIC_API_KEY, OPENAI_API_KEY, OPENAI_COMPAT_API_KEY, GEMINI_API_KEY, GOOGLE_API_KEY, OPENROUTER_API_KEY, ANTHROPIC_BASE_URL, OPENAI_BASE_URL, OPENAI_COMPAT_BASE_URL, GEMINI_BASE_URL, GOOGLE_BASE_URL) from the ACP agent process and its --version probe. The default is full passthrough of Tracker's environment, because ACP bridges route their own credentials. The strip is exact-name: other credentials pass through in both modes. Terminal commands the agent asks Tracker to run get the TRACKER_PASS_ENV scrub, and this switch also strips its eleven names from them, even when TRACKER_PASS_ENV=1. v0.17.0
TRACKER_PASS_ENVunsetSet to 1 to disable the sensitive-env scrub on tool subprocesses, native-backend agent bash commands, verify commands, ACP terminal commands and git subprocesses (names containing _API_KEY, _SECRET, _TOKEN, _PASSWORD; DOCKER_AUTH_CONFIG; and, under any name, a value that is a URL with a password, an http(s) URL with any userinfo, or a Docker auths JSON blob — #679). Proxy variables (HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, FTP_PROXY, NO_PROXY) skip the value check so commands behind an authenticated proxy keep network access. Default scrubs them out. Use only when a tool genuinely needs a secret. Shell-only: a .env file cannot set it.
CLAUDE_CODE_SUBPROCESS_ENV_SCRUBunset--backend claude-code only. Read by Claude Code, not tracker: export 1 to have Claude Code strip credentials from the Bash commands, hooks and stdio MCP servers it starts, while claude keeps them for its own API calls. Tracker passes it through but never sets it. Claude Code's rule keeps GITHUB_TOKEN, GH_TOKEN and proxy settings. With Claude Code 2.1.280 under bypassPermissions (tracker's default for claude-code nodes), it also made claude refuse commands with $VAR expansions, env, sh -c and listings outside the working directory. A refused call fails a node left on that default (#676). Shell-only: a .env file cannot set it.
TRACKER_ENV_FILESallShell-only equivalent of --env-files: all loads the config .env then the project .env, config loads only ~/.config/tracker/.env, none loads neither. An explicit flag wins; an unknown value is an error. Cannot itself be set from a .env file. v0.78.0
TRACKER_FAIL_ON_OVERRIDEunsetSet to exactly 1 (strict parsing) to exit code 2 when a run terminates as validation_overridden. Equivalent to --fail-on-override; the CLI flag wins when both are present. v0.35.0
TRACKER_SPRINT_WRITER_MODELunset (tool disabled when unset; the configured model name is used directly)Model used by the write_enriched_sprint agent-runtime tool. When set, the tool registers, together with dispatch_sprints, in the native backend's tool registry. Pair with TRACKER_CODEGEN_MODEL for the full architect-side flow. v0.25.0
TRACKER_SPRINT_WRITER_PROVIDERanthropicProvider the write_enriched_sprint tool calls TRACKER_SPRINT_WRITER_MODEL on. Read only when that model is set. v0.25.0
TRACKER_CODEGEN_MODELunset (tool disabled when unset; the configured model name is used directly)Model used by the generate_code tool to expand a contract into files. v0.25.0
TRACKER_CODEGEN_PROVIDERopenaiProvider the generate_code tool calls TRACKER_CODEGEN_MODEL on. Read only when that model is set. v0.25.0
TRACKER_RUN_ID / TRACKER_RUN_DIR / TRACKER_WORKDIRset by trackerOutputs, not inputs: tracker injects these into every locally-executed tool subprocess — the run ID, the absolute per-run artifact dir, and the absolute workdir — so a tool can cat "$TRACKER_RUN_DIR/<NodeID>/response.md" for an upstream agent's output. The run dir exists before the first node runs, so a start tool node can write into it. Operator-exported values of these names are overridden, never inherited. Present on the TRACKER_PASS_ENV=1 path too. v0.37.0 A tool node that writes $TRACKER_RUN_DIR/notice.txt leaves the user an end-of-run message, printed after the run summary (TUI and console; 4 KiB max, control characters stripped). v0.81.0
TRACKER_ACP_CACHE_READ_RATIOunsetACP cost estimate only. A fraction in (0, 1] of the estimated input tokens priced as cache reads instead of fresh input. The cache-read rate is model-specific — it comes from the model's catalog entry (e.g. gpt-4.1 and gpt-4o price cached input at 0.25× / 0.5×), falling back to 10% of the input rate only for models the catalog has no cache rate for. Unset, non-numeric or out-of-range values price all estimated input as fresh (no cache discount; the estimate can still be low, since it never sees the bridge’s own system prompt and tool schemas) and log one warning. v0.24.1
TRACKER_AUDIT_DIR—Absolute path that replaces the base directory of the secure run state: the live activity log and the authoritative checkpoint.json land under <dir>/<runID>/. A relative value is silently ignored so the working directory can never re-anchor the log. v0.28.0
XDG_STATE_HOME~/.local/stateWhen TRACKER_AUDIT_DIR is unset and this is an absolute path, the secure run state lives under $XDG_STATE_HOME/tracker/runs/<runID>/. Relative values are ignored. On Windows %LOCALAPPDATA%\tracker\runs is tried next. v0.28.0
XDG_CONFIG_HOME~/.configLocation of the config env file $XDG_CONFIG_HOME/tracker/.env. tracker setup writes it; tracker run and tracker doctor read it (after the shell, before the workdir .env); tracker version and tracker estimate read only this file, never the workdir .env. No other subcommand loads either .env file. A relative value is ignored, with a notice, and $HOME/.config is used.
TRACKER_DEBUGunsetAny non-empty value makes the Anthropic adapter log a 200-byte preview of the raw response body when a response comes back empty (0 output tokens, no text, no tool calls).
TRACKER_NO_NOTIFYunsetAny non-empty value disables desktop notifications (osascript on macOS, notify-send on Linux). v0.13.0
TRACKER_NO_UPDATE_CHECKunsetAny non-empty value skips the background update check that tracker run performs. The check is also skipped when CI is set and in dev builds. v0.12.0
HERDR_ENV / HERDR_PANE_ID / HERDR_BIN_PATHset by HerdrInjected by a Herdr terminal pane. When HERDR_ENV=1 and both HERDR_PANE_ID and HERDR_BIN_PATH are set, tracker reports its run lifecycle (working / blocked / idle) to that pane by invoking the herdr CLI at HERDR_BIN_PATH. If any of the three is missing, reporting is a no-op. v0.76.0
TRACKER_HERDRunsetSet to 0 to opt out of Herdr reporting even inside a Herdr pane. v0.76.0

Autopilot mode

Run pipelines fully autonomous. Human gates are answered by an LLM judge with a configurable decision-making persona.

# Balanced judgment (default persona)
tracker --autopilot mid build_product

# Move fast, approve everything reasonable
tracker --autopilot lax build_product

# High quality bar — pushes back on gaps
tracker --autopilot hard build_product

# Approves but writes detailed feedback
tracker --autopilot mentor build_product

# Deterministic auto-approve — no LLM, for CI
tracker --auto-approve build_product

Personas

PersonaApproval BiasReasoning StyleBest For
laxStrong approveBrief: "Looks fine, moving on"Demos, prototypes, overnight runs
midBalancedConcise: one paragraphGeneral-purpose unattended runs
hardPrefers retry/adjustDetailed: cites specific gapsPre-release quality sweeps
mentorApprove with notesVerbose: 3-5 sentences of feedbackLearning, review artifacts

How It Works

  1. Gate Reached

    Pipeline hits a human gate (ApprovePlan, EscalateMilestone, etc.)

  2. LLM Consulted

    The autopilot sends the gate's prompt, context, and available options to the LLM with the persona's system prompt.

  3. Structured Response

    LLM returns {"choice": "approve", "reasoning": "..."}. Choice is matched against edge labels.

  4. Fallback on Error

    If the LLM fails or returns an unmatchable choice, the default edge is taken with a warning.

Design Note

The autopilot reuses the pipeline's existing LLM client — no separate configuration. It picks the cheapest model from the configured default provider (falling back to claude-sonnet-4-6 if none is set) for cheap, fast gate decisions. All decisions are logged to the activity log for post-hoc review via tracker diagnose.

Agent backends

Three backends, one pipeline. Native is the default and works with every provider. Claude Code gives agents file editing, terminal access, and MCP tool servers (subscription auth, no API key needed). ACP bridges tracker to third-party coding agents like claude-agent-acp, codex-acp, and gemini --acp via JSON-RPC over stdio.

Side-by-Side Comparison

Native (default)Claude Code v0.12.0ACP v0.16.0
How it worksWraps agent.Session — tracker's built-in turn loopSpawns claude CLI as a subprocess, parses NDJSON outputSpawns ACP-compatible agents via JSON-RPC 2.0 over stdio
ProvidersAnthropic, OpenAI, Gemini, OpenAI-compatAnthropic (via Claude CLI)Routed to matching ACP binary per provider
Tool accessTracker's registered tool set; tool_access: read_only keeps exactly read / grep_search / glob (symlinks out of the workdir and secret-looking files refused)File editing, terminal, MCP servers; read_only: --tools Read,Glob,Grep, dontAsk, --strict-mcp-config, --setting-sources userFull agent toolset (file ops, terminal via ACP); refuses read_only
Best forStandard LLM calls, multi-provider pipelines, cross-reviewImplementation nodes that need file editing + terminalHosting third-party ACP coding agents inside a tracker pipeline
EnvironmentThe agent's bash tool and verify commands get exec.CommandEnv: Tracker's environment minus names containing _API_KEY, _SECRET, _TOKEN or _PASSWORD, minus DOCKER_AUTH_CONFIG, and minus credential-bearing values such as a URL with a password (#679); TRACKER_PASS_ENV=1 passes everything. v0.77.0 Not native-only: workflow tool nodes get the same CommandEnv and git subprocesses the same credential patterns (gitSafeEnv, which also drops GIT_DIR-class redirect variables unconditionally) under every backend — only the agent process itself differs per column.Full environment minus Tracker's five provider keys (ANTHROPIC_API_KEY, OPENAI_API_KEY, OPENAI_COMPAT_API_KEY, GEMINI_API_KEY, GOOGLE_API_KEY) and their *_BASE_URLs so the CLI bills to subscription auth; TRACKER_PASS_API_KEYS=1 keeps them. claude's own Bash/hooks/MCP children inherit the rest unless the operator exports CLAUDE_CODE_SUBPROCESS_ENV_SCRUB=1.Agent process: full environment by default (bridges route their own credentials); TRACKER_STRIP_ACP_KEYS=1 strips eleven provider key / base-URL names. Terminal commands the agent asks Tracker to run get exec.CommandEnv, like native bash, with TRACKER_STRIP_ACP_KEYS=1 applied on top.
Error mappingProvider HTTP status + SSE eventsClaude CLI exit codes → pipeline outcomes; a result listing permission_denials fails a node left on bypassPermissions with no tool_access / disallowed_tools, even on exit 0 (#676)ACP JSON-RPC error codes → pipeline outcomes
Per-node overridebackend: native (or auto, when claude isn’t available)backend: claude-code (or auto, when claude answers)backend: acp + optional acp_agent:

When to Use Which

Use Native When

  • Your agents make standard LLM calls (analysis, planning, review)
  • You need multi-provider pipelines (Claude + GPT + Gemini)
  • Cross-review nodes that compare outputs from different models
  • You want the fastest possible execution

Use Claude Code When

  • Agents need to edit files on disk (implementation, fix nodes)
  • Agents need terminal access (run tests, build commands)
  • You want MCP tool servers available to agents
  • You want Claude's built-in code intelligence

Usage

# Global: every agent node uses Claude Code
tracker --backend claude-code build_product

# The killer combo: autonomous + Claude Code
tracker --backend claude-code --autopilot mid build_product

# Native is the default — no flag needed
tracker build_product

# No flag and no API key: the starters use backend: auto (Claude Code if installed)
tracker explain --param question="what does this repo do?"

Per-Node Selection in .dip

Mix backends within a single pipeline. Use Claude Code for implementation, native for everything else. Per-node backend: attrs always override the global --backend flag. backend: auto picks your Claude subscription when claude is installed (outside the working directory and answering --version), otherwise a configured API key, once per run, and announces the choice; an explicit --backend wins over it, and a resume reuses the recorded choice. With every agent node on auto, claude-code or acp, no API key is needed to start. tool_access: read_only limits a node to reading: read / grep_search / glob on the native backend (secrets and paths outside the workdir refused), --tools Read,Glob,Grep with dontAsk on Claude Code; ACP refuses it.

agent Implement
  label: "Build the feature"
  model: claude-sonnet-5
  backend: claude-code
  prompt: |
    Implement milestone ${ctx.current_milestone} following SPEC.md.

agent Review
  label: "Review the implementation"
  model: gpt-5.4
  provider: openai
  # No backend attr — uses native (default)
  prompt: |
    Review the implementation for correctness and style.

The acp backend (v0.16.0+) spawns ACP-compatible coding agents as subprocesses via JSON-RPC over stdio (claude-agent-acp, codex-acp, gemini --acp). Override the chosen binary per-node via the acp_agent node attribute.

Companion binaries

Two binaries ship alongside tracker but are not part of the product CLI — they verify and benchmark the engine. tracker-conformance pins engine behavior against version drift; tracker-swebench evaluates the agent against SWE-bench. For how these fit into tracker's verification story, see How we verify tracker.

tracker-conformance v0.47.0+

Emits a normalized, deterministic golden trace of an example workflow — event sequence, per-node SessionStats, aggregate UsageSummary, and terminal status/class — via a stub completer (no API keys, no wall-clock noise). The committed goldens are versioned in lockstep with the tracker tag, so a downstream port pins a version and diffs for any engine-behavior drift. This binary is a GoReleaser-published release asset for exactly that reason.

tracker-conformance golden <fixture.dip>
Print the normalized golden trace for a fixture to stdout. Committed goldens live at cmd/tracker-conformance/testdata/golden/*.golden.json; regenerate after an intentional engine change with go test ./cmd/tracker-conformance -run TestGoldenTraces -update-golden.

tracker-swebench v0.18.0+

Evaluates tracker's agent against the SWE-bench dataset. Orchestrates per-instance Docker containers, a dataset JSONL parser, a resumable results writer, and an in-container agent-runner that captures changes via git diff.

tracker-swebench --dataset <path.jsonl> [flags]
Run the harness over a SWE-bench dataset. Supports --model, --provider, --gateway-url, --max-turns, --timeout, --instance, --results-dir, --docker-image, and forwarding of CF_AIG_TOKEN through the container for gateway auth.
tracker-swebench analyze <results-dir>
Bulk-triage a completed run. Reads predictions.jsonl + run logs + empty-patch diagnostics and emits overall resolved/unresolved/empty/error counts, per-repo breakdown, top-10 empty-patch and longest-unresolved instances, and error-class distribution. Auto-detects SWE-bench evaluator resolved_ids; gracefully degrades when no evaluator report is present. v0.22.0
# Analyze a completed run, pretty-printed
tracker-swebench analyze ./swebench-results/

# Structured JSON for downstream tooling
tracker-swebench analyze ./swebench-results/ --json > report.json

# Evaluate predictions against a specific ID file
tracker-swebench analyze ./swebench-results/ --predictions preds.jsonl

Troubleshooting

SymptomCauseFix
"no LLM providers configured"Missing API keystracker setup or export env vars — or install and sign in to Claude Code (npm i -g @anthropic-ai/claude-code && claude /login): workflows whose agent nodes are all auto / claude-code (e.g. explain, quickfix) need no key
An old or wrong claude runs (e.g. unrecognized_model)Another claude is earlier on PATHtracker doctor lists every claude on PATH with its version; set TRACKER_CLAUDE_BIN=/absolute/path/to/claude in the shell
“this run resolved backend: auto to …, which is no longer available”A resume found the recorded backend goneRestore that backend, or resume with --backend to switch deliberately; a resume never switches on its own
TestMilestone instantly escalatesStale fix_attempts counterrm .ai/milestones/fix_attempts
Node fails with no visible errorTool stderr not surfacedtracker diagnose shows full output
Pipeline loops foreverUnconditional fallback to loop targetRoute fallbacks to escalation gates or Done
Run halted with budget_exceededHit --max-tokens / --max-cost / --max-wall-timetracker diagnose prints the per-provider breakdown and the dimension that tripped
Tool retries same error 5 timesDeterministic command bugtracker diagnose flags it — fix the command in the .dip file

Diagnose intelligence

tracker diagnose doesn't just dump errors — it analyzes failure patterns and generates actionable suggestions.

Deterministic Failure Detection

When a tool node fails multiple retries with identical errors, diagnose recognizes it as a deterministic bug in the command — not a transient issue that retrying might fix. This saves users from wading through 5 identical stack traces to realize the command itself is wrong.

  ✗ T1Init
    Handler:  tool
    Duration: 3.2s
    Attempts: 5 failures (all identical — deterministic)
    Output:
      The workspace name "." is invalid.
      Workspace names must start with a letter.

─── Suggestions ───────────────────────────────────────────
  → T1Init: Failed 5 times with identical errors — this is a
    deterministic bug in the command, not a transient failure.
    Retrying won't help. Fix the tool command in the .dip file
    and re-run.

All Detection Patterns

PatternDetectionSuggestion
Identical retriesSame error signature across 2+ failuresDeterministic bug — fix the command
Varying retries3+ failures with different errorsFlaky command or environment issue
Escalation hitESCALATE + fix attempts in outputReset counter: rm .ai/milestones/fix_attempts
Silent failureNo stdout, stderr, or errors capturedCheck activity.jsonl manually
Missing command/filecommand not found or No such fileCheck working directory and tool availability
Go test failuresFAIL + go test in outputCheck known_failures exclusion list
Suspiciously fast<50ms for non-tool nodesConfiguration issue or missing handler

Quick reference

The commands you'll use most, at a glance.

# First time (Claude Code signed in: no API key needed)
tracker explain --param question="what does this repo do?"
tracker quickfix --param change="fix the README typo"
tracker setup                           # configure API keys interactively (no Claude Code)
tracker doctor                          # check setup: keys, claude, tools

# Run pipelines
tracker build_product                   # built-in workflow, no file needed
tracker my_pipeline.dip                 # local file
tracker --autopilot mid build_product   # fully autonomous
tracker --backend claude-code my.dip    # agents use claude CLI

# Full YOLO — Claude Code agents, autopilot gates, TUI dashboard
tracker --backend claude-code --autopilot lax build_product

# After a run
tracker diagnose                        # analyze most recent failure
tracker audit <runID>                   # full audit trail
tracker list                            # recent runs

# Manage pipelines
tracker workflows                       # list built-in workflows
tracker init build_product              # copy to cwd for editing
tracker validate my.dip                 # lint + structure check
tracker simulate my.dip                 # dry-run all paths
tracker verify-tests . --race           # flag duplicate tests + race check

# Maintenance
tracker update                          # self-update to latest release
tracker version                         # version + configured providers