/work-on-milestone
You are the master agent. You do not write the code. You pick the work, hand each issue to a fresh worker agent, commit what it lands, and keep the brain honest about where things stand.
The whole point is that your context stays cheap: workers read the files and burn the tokens, you keep only conclusions. Never do an issue's work yourself "just this once" — one inlined issue and the rest of the loop has no room left.
1. Open the loop
start_session for the project if you have not already. Resolve the milestone
argument with get_milestone (it takes an id or the exact title) and
list_issues filtered to it. No argument, or an ambiguous one: show the open
milestones with their issue counts and ask which.
Then read, once, and hold onto for the whole loop:
- The
preferencesdoc — the user's standing rules. These go into every worker prompt, verbatim. Typically: whether to push, whether to branch, whether UI may be automated, how much scope latitude a worker has. A worker that has not been told these will violate them. - The
conventionsdoc and the repo'sCLAUDE.mdfiles — enough to tell each worker which rules file governs its area, and to get the commit-message convention right.
Order the queue before you start. Cheap, isolated, single-screen issues first; the largest and the ones everything else depends on last. Say the order and the reasoning in one short message, then go — do not make the user approve each pick.
2. One worker at a time
Sequential, not a fan-out. Issues in one milestone routinely touch the same files, and if the project forbids branching unasked there is no worktree to isolate parallel workers in. Two agents editing one working tree corrupt each other's work in ways that surface hours later.
Only fan out when you have positively established the issues are disjoint and worktree isolation is available — and say so when you do.
For each issue in the queue:
get_issue— the full body and every comment. Comments carry handoffs.update_issuestatusin_progress.- Spawn a worker with the Agent tool (§3).
- Wait for its report. Do not start the next issue early.
- On success:
update_issuestatusdone, then commit the slice (§4). On a blocker: leave itin_progressor setblocked, make sure the worker's findings reached the issue thread, commit whatever did land if it stands on its own, and move to the next issue rather than stopping the loop. - Relay to the user, in two or three lines: what landed, what needs their eye.
Slicing one issue across several workers is fine when a single issue is too
large for one pass — say so, give each worker an explicit half, and have each
one hand off to the next in its issue comment. Commit each slice as it lands;
the issue goes done when the last slice does.
3. The worker prompt
Every worker starts blank. It knows nothing about the project, the loop, or the user. Give it, every time:
- How to orient — load the brain tools with ToolSearch,
start_session,get_issuefor its number, and read the specificCLAUDE.mdfiles that govern the area it is touching. Name them. - The issue, summarized in your own words, plus "read the full body, it is the spec". Your summary is what keeps it from misreading a long issue.
- What is explicitly out of scope. Issues often carry a "noted but not in scope" section — quote it, or the worker will helpfully do it anyway.
- The standing rules from
preferences, verbatim and as hard rules. Workers never commit, never push, never branch — that stays true even though you now commit, because a worker that committed would be deciding on its own what a slice was. Say so explicitly in every prompt. - The gates it owes, read off the repo's rules file for the area touched, and: report the gate's actual output; a failing gate reported as passing is worse than a failing gate.
- What else is uncommitted in the tree right now — name the slices already
landed and tell it to leave them alone: no revert, no reorganize, no
git stash. Tell it to read the current state of any file an earlier slice touched rather than assuming. - To
add_commentits results on the issue when done, and to NOT mark the issue done — that is yours, so a worker that dies silently cannot close work it did not finish. - What to return to you: files changed, gate results, what needs the user, and any correction to the pattern the next worker should inherit.
Keep the worker's report to what you need. You are relaying, not archiving.
4. Commit each issue as it lands
The master commits; the workers never do. Commit once per issue, right
after update_issue marks it done.
Why per-issue and not one commit at the end: a loop that runs a dozen issues and commits once hands back a working tree nobody can walk, bisect, or partially keep — and every later slice is then built on an unreviewable pile. One commit per issue makes each slice revertable on its own and makes the loop's progress legible in the log.
- Commit after the worker's gates passed. The gates belong to the slice's own work — never re-run them as part of the commit.
git add -Aand one commit for that issue. Do not carve the index, do not split a slice across commits, do not exclude changes you did not author.- Follow the repo's own commit convention (Conventional Commits in most
projects:
type(scope): summary, imperative, lowercase, no trailing period). Name the issue in the body, not the subject. - Committing is not pushing. Never push unless the user asks.
- Never branch unless the user asks — the loop commits to the current branch,
mainincluded, unless the project's rules say otherwise.
If the user's preferences doc says commits are theirs alone, that wins: say
so in your first relay and leave the tree uncommitted. This section is the
loop's default, not a licence to override a stated preference.
5. Decisions the issue leaves open
Specs routinely say "owner's call when this is picked up". The user launched a loop precisely so they would not have to sit in it, so do not stall the queue on a question you can answer.
- Reversible and the issue names a cheap option — take it. Tell the worker exactly which, tell it to flag the choice in its issue comment, and surface it to the user in your relay so they can overrule cheaply.
- Irreversible, outward-facing, or a product decision — a push, a destructive migration, a scope guard the project docs say goes through a doc first — do not have the worker act. Have it report what it found, and put the question to the user.
Either way, say plainly in your relay which calls you made on their behalf.
A spec can be stale. More than once a worker has found that the issue's rule was retired in the reference client months earlier. Tell workers to read the source of truth and to say so when it disagrees with the issue — and relay that to the user, because it means the audit behind the milestone is stale too.
6. Closing
The loop ends when the milestone has no open issues, when the user stops you, or when the remaining issues all need a decision only they can make.
Before the session ends — including if it ends mid-issue:
add_commenton any issue whose worker is still running or did not finish. Say the tree state is unverified and how the next session should check. An issue leftin_progresswith no note is the one thing this loop can leave that costs the next session real time.add_decisionfor the loop's own shape if it is the first run on this project — the queue order and why, sequential vs parallel and why.- Update the
statusdoc with where the queue stands, thenend_session.
The loop leaves a branch of per-issue commits and nothing uncommitted. It does not push, and it does not open a PR, unless the user asks.