Agents
JSON and exit codes
This page is the machine contract. If you script Atlas or point an agent at it, these are the only shapes you need to parse and the only codes you need to branch on.
The stdout rule
With --json, stdout is exactly one JSON document and nothing else. Notifications, warnings, and errors go to stderr. Parse stdout; never parse the pretty tables, Markdown output, or TUI text.
$ tracker version --json
{
"format_version": "v1",
"kind": "tracker_version",
"version": "v1.13.0",
"commit": "abc123",
"build_date": "2026-05-07T00:00:00Z",
"go_version": "go1.26.6",
"platform": "darwin/arm64"
}
List commands share a common shape with kind, generated_at, and items, and useful fields are flattened onto each item so items[0].public_key_id style access works without digging.
The error envelope
Failures under --json leave stdout empty and emit a machine-readable error on stderr:
{
"format_version": "v1",
"ok": false,
"error": { "code": "not_found", "message": "ticket APP-99 not found", "exit": 3 }
}
Branch on error.code or the exit status. Message text is for humans and can change; the codes are the contract.
Exit codes
| Code | Meaning | What it usually is |
|---|---|---|
0 | ok | It worked. |
1 | internal | A real bug, or a missing required flag. |
2 | invalid_input | Bad status, type, priority, or actor. Malformed query. A bare agent: actor. |
3 | not_found | No such ticket, project, agent, or view. Also the classic symptom of an MCP server missing --workspace. |
4 | conflict | Forbidden status transition, ticket already claimed, resource already exists. The workflow saying no, as designed. |
5 | permission_denied | Policy, separation of duties, or the wrong reviewer. |
6 | busy | Another writer holds the workspace lock. Waiting a few seconds and retrying is legitimate. |
7 | repair_needed | The index is unreadable, or read-only doctor found it stale against the sources. Run tracker doctor --repair or tracker reindex. A merely missing or stale index heals itself on the next command. |
Automation stays non-interactive
Only setup paths prompt: ordinary tracker init configures detected agents without a picker; tracker init --integrations and bare tracker integrations install open the picker in a TTY. JSON mode, non-TTY execution, explicit --targets, and tracker init --skip-integrations avoid prompts. Other missing required flags fail immediately naming the flag, for example required flag(s) "body" not set. A command waiting for the workspace write lock ends in exit 6.
Pending reason codes
tracker agent pending --json explains blocked work with stable codes, so agents branch instead of guessing:
| Code | Meaning |
|---|---|
dependency_blocked | A blocker is not done yet. Canceled blockers stay blocking. |
waiting_for_review | The ticket sits in review and someone else must decide. |
waiting_for_owner | An owner gate needs a human. |
not_ready_status | The ticket is not in a state this actor can act on: usually backlog that never had blockers, or someone else's in_progress work. A backlog ticket whose blockers are all done is not pending; it appears under available as action promote. |
claimed_by_other | Another actor holds the lease. |
policy_blocked | A permission profile or governance policy says no. |
agent_at_capacity | The agent already holds its maximum active work. |
missing_capability | The ticket needs a capability this agent does not have. |
Every available entry carries an action: start, continue, review, complete, or promote. promote means the blockers are resolved but the ticket is still in backlog, so the first suggested command is the move to ready. tracker queue --json groups the same tickets under the unblocked_for_me category, which tracker next walks right after ready_for_me.
MCP shares the shapes
MCP tool responses use the same format_version convention with kind, generated_at, and payload, the same error envelope, and the same codes. Mutating tools take actor and reason arguments; high-impact tools additionally take operation_approval_id and confirm_text. Paged tools accept limit and cursor and report total, next_cursor, and truncated. Details live in MCP setup.
One workflow-shaped gotcha worth repeating: exit 4 on a status move usually means the edge does not exist. backlog to in_progress is forbidden by design; go through ready. Retrying the same move returns the same 4.