Core
Tickets and workflow
Tickets carry a type, status, priority, labels, relationships, comments, and history. The workflow is deliberately strict: only some status edges exist, review is a real gate, and the tracker would rather refuse a move than let state drift.
Creating and editing
tracker ticket create --project APP --title "Add health check" \ --type task --actor human:owner --reason "planned work" tracker ticket view APP-1 tracker ticket edit APP-1 --actor human:owner --reason "retitle" tracker ticket list --project APP --status ready
- Types:
epic,task,bug,subtask. Templates fromtracker templates listcan pre-fill new tickets via--template. - Priority, labels, and assignee have their own commands:
ticket priority,ticket label add/remove,ticket assign. - Ticket titles are normalized before rendering: control characters and bidirectional overrides are stripped so a hostile title cannot scramble a board or a terminal.
Statuses and legal edges
Six working statuses plus two terminals. Not every move exists, and that is the point.
backlog -> ready, blocked, canceled ready -> in_progress, blocked, canceled in_progress -> in_review, ready, blocked, canceled in_review -> done, in_progress, blocked blocked -> ready, in_progress, canceled done -> (terminal) canceled -> (terminal)
backlog -> in_progress is forbidden and always will be; work goes through ready. An illegal move exits with code 4 and a clear message. That exit 4 is the workflow working, not a crash, and retrying the same move gets the same 4.
in_review and done are special: you reach them through request-review, approve, or complete rather than move, because those commands also run the completion policy and any gates. Under review_gate, reviewer approval is the final transition to done; there is no second completion command.
tracker ticket request-review APP-1 --reviewer agent:reviewer-1 \ --actor agent:builder-1 --reason "ready for review" tracker ticket approve APP-1 --actor agent:reviewer-1 --reason "review passed" tracker ticket reject APP-1 --reason "tests missing" --actor agent:reviewer-1
request-review opens or reuses a review gate, so gate list, approvals, and inbox show the pending review explicitly. When --reviewer is omitted, Atlas uses the ticket reviewer or the effective project, epic, or ticket required_reviewer. Use ticket complete for open-mode work or policies whose separate required gates have passed; it cannot bypass the request-review and approval lifecycle.
Claims and leases
A claim is a lease that keeps two workers off the same ticket. Claim before you touch code.
tracker ticket claim APP-1 --actor agent:builder-1 --reason "start work" tracker ticket heartbeat APP-1 --actor agent:builder-1 tracker ticket release APP-1 --actor agent:builder-1 --reason "handing back"
Claiming a ticket someone else holds is exit 4, not a queue. When the queue and a ticket seem to disagree, tracker inspect APP-1 --actor agent:builder-1 answers "why can't I move this" in one call: policy, lease, queue position, and history together.
Dependencies
tracker ticket link APP-2 --blocked-by APP-1 --actor human:owner --reason "needs schema" tracker ticket link APP-5 --parent APP-4 --actor human:owner --reason "subtask" tracker ticket unlink APP-2 APP-1 --actor human:owner --reason "no longer needed"
blocked_byis enforced for unsafe progress: moving toin_progressorin_review, approval, and completion are rejected while any blocker is unresolved.- Only
doneunblocks dependents. Acanceledblocker does not, on purpose. human:ownercan push through with--override-deps --reason "...". The event records adependency_overridepayload naming the unresolved blockers, so the shortcut is visible forever.
Comments and history
tracker ticket comment APP-1 --body "retry logic now exponential" \ --actor agent:builder-1 --reason "progress note" tracker ticket history APP-1 --json
History is the append-only event stream rendered for one ticket: every move, claim, comment, gate decision, and override, each with its actor and reason.
Bulk operations
Grooming sessions get real tooling instead of a shell loop.
tracker bulk move ready --ticket APP-3 --ticket APP-4 --dry-run --actor human:owner tracker bulk move ready --ticket APP-3 --ticket APP-4 --yes \ --actor human:owner --reason "sprint planning" tracker bulk assign agent:builder-1 --view sprint-42 --yes \ --actor human:owner --reason "assign sprint"
--dry-runpreviews without mutating; live batches require--yes.--viewexpands a saved view into ticket IDs in the view's own order; duplicates are removed.- Every committed per-ticket event carries the same
metadata.batch_id, so a batch is auditable as a unit. bulkcoversmove,assign,request-review,complete,claim, andrelease.
Archiving is soft: tracker ticket archive removes a ticket from active views while the file and history stay in the repo. ticket delete survives as a compatibility alias for the same thing.