Your first task
You will be able to create a project, plan a small graph, claim a task, be refused when you try to close it, satisfy the refusal, and close it for real — in about five minutes, on a repository you already have.
Assumes: Commission is installed and COMMISSION_ACTOR is set.
The refusal in the middle is the point of this page. A tour that only shows the happy path teaches the wrong model of commission: it hides that completion is a checked fact rather than an assertion.
1. Create the project
From the root of the repository you want to track:
commission init myapp --name "My App"created project myapp (My App)
this repo is bound to it — bare commission commands target 'myapp' here
next:
commission apply -f plan.json create a whole task graph at once
commission add "..." or one task to start with
commission next --claim what to work on, claimed atomicallyThat wrote a .commission.json at the repository root:
{
"$schema": "https://commission.sh/schema/commission-config.schema.json",
"version": 1,
"project": "myapp"
}Three keys, and only one of them is about you. Every Commission command run anywhere inside this repository now resolves the project by walking up to that file, so agents never have to be told which project they are in. Commit it.
2. Define a gate
A gate names the evidence a task must carry before Commission will let it close. Gates are data, not process documentation:
commission gates --set shipped=pr,testshipped: pr, testA task tagged gate: shipped cannot reach done without a pr and a test
evidence record attached. Nothing enforces what those references mean — commission
checks that you attached them, and the event log records who did.
3. Plan a small graph
One task is not interesting; the shape of the work is. Write a plan document:
cat > plan.json <<'PLAN'
{
"project": "myapp",
"tasks": [
{ "key": "schema", "title": "Design the events table",
"criteria": ["migration reviewed", "indexes justified"],
"touches": ["src/db"] },
{ "key": "ingest", "title": "Webhook ingest endpoint",
"deps": ["schema"], "gate": "shipped", "touches": ["src/http"],
"criteria": ["signature verified", "replays rejected"] },
{ "key": "feed", "title": "Event feed in the web view",
"deps": ["schema"], "touches": ["src/web"] }
]
}
PLAN
commission apply -f plan.jsonapplied to 'myapp': 3 created, 0 updated
+ myapp-1 (schema)
+ myapp-2 (ingest)
+ myapp-3 (feed)apply is atomic: the local keys resolve to real ids inside one transaction,
so a plan that names an undefined gate or a missing dependency creates
nothing and tells you which line was wrong. Re-applying the same document
upserts by key rather than duplicating — the plan file can live in the repo and
grow. Every field is in the apply reference.
touches is a free-text label for the area of the codebase a task will edit.
Commission never interprets it; it only uses it to work out which ready tasks can be
dispatched to different agents at the same time without colliding.
4. See the frontier, not the backlog
commission readyready frontier (dispatch independent tasks in parallel):
myapp-1 · Design the events table [open · p2]Two of the three tasks exist and are not shown, because they depend on the first. Blocked is derived, never set — there is no blocked status to forget to update, and no way for the board to disagree with the graph.
5. Claim it
commission next --claimclaimed myapp-1
routing: blaze is holding it; autonomy autonomous (default); no actors are declared, so nothing is restricted
myapp-1 · Design the events table [open · p2]
project: My App
criteria:
[ ] 0. migration reviewed
[ ] 1. indexes justified
blocks: myapp-2, myapp-3
next:
commission start myapp-1
commission note myapp-1 -m "<progress>"One command selected the task, claimed it atomically under a lease, and printed
the whole context bundle — body, criteria, dependency state, linked documents,
recent notes, and the commands that come next. A fresh session resumes from
this and nothing else. Run it from two shells with different COMMISSION_ACTOR
values and each gets a different task; see parallel work.
Move it into flight and leave a breadcrumb:
commission start myapp-1
commission note myapp-1 -m "partial index on (project_id, ts) — full index was 4x the size"Notes are for the next session, which is often you on Monday. Decisions, dead ends, and discoveries; not a progress bar.
6. Be refused
commission done myapp-1cannot complete myapp-1: 2 unchecked criteria
missing: criterion 0: migration reviewed
missing: criterion 1: indexes justified
hint: tick each with 'commission check myapp-1 0', 'commission check myapp-1 1' — only once it is actually true; or --force to override (logged)Exit code 2. That is not a crash and not a failure — it is commission declining an
action it understood, naming what is missing and the exact command that fixes
it. An agent reads that hint and acts on it without a human. See
exit codes for the full contract, including the
--json shape of the same refusal.
7. Satisfy it, and close
commission check myapp-1 0
commission check myapp-1 1
commission done myapp-1myapp-1 criterion 0 ticked; 1 remaining
myapp-1 criterion 1 ticked; 0 remaining
myapp-1: in_progress → done
next task: commission next --claimTick a criterion when it is actually met. Nothing checks that you were honest — but the event log records when you ticked it and what you had attached at the time, which is a far more useful artifact than a status field nobody trusts.
myapp-2 carries gate: shipped, so it will refuse a second time, for a
different reason, until evidence is attached:
commission evidence myapp-2 pr=https://github.com/acme/myapp/pull/14 test=ci-22118. Look at where you are
commission board
commission log --last 5My App (myapp) — 1/3 done, 2 open
ready:
myapp-2 · Webhook ingest endpoint [open · p2 · gate:shipped]
myapp-3 · Event feed in the web view [open · p2]
recently done:
myapp-1 · Design the events table (2026-07-27 14:52)The board is a query, not a record. So are ready, standup, export, and
blocked state. There is nothing to keep in sync, which is why drift is
structurally impossible rather than merely discouraged.
The whole sequence
commission init myapp --name "My App"
commission gates --set shipped=pr,test
commission apply -f plan.json
commission ready
commission next --claim
commission start myapp-1
commission note myapp-1 -m "partial index on (project_id, ts) — full index was 4x the size"
commission done myapp-1 # refused: 2 unchecked criteria
commission check myapp-1 0
commission check myapp-1 1
commission done myapp-1 # closes
commission boardEvery command on this page is executed by tests/docs.test.ts against a
scratch database.
Next
- Your first agent — hand this loop to a coding agent.
- Guides → task lifecycle — every transition, and what refuses.
- Reference → CLI — every command and flag.
Part of Start here.
This page is docs/start/first-task.md in the Commission
repository, rendered in place — the site keeps no copy of it. The repository is private, so there is no edit link to follow.