| name | multi-tool-handoff |
| description | Use when starting, moving, pausing, resuming, or finishing agent work; maintaining a GitHub Projects board, milestone progress, resume context, or release-ready changelog; or protecting unfinished work before compaction, high tool usage, session limits, or ownership changes. |
Multi-tool handoff
Coordination lives on GitHub, not in Markdown files. One task is one issue, and that issue is the
whole record of it: the body is the spec, comments are progress and resume context, the closing
comment carries the evidence. A GitHub Projects v2 board renders the issues as columns; milestones
give the helicopter view.
Only one file remains in the repository: CHANGELOG.md, a thin newest-first index so "what shipped"
is answerable offline, with the detail one click away in the issue.
Migrating from the three-file standard? See Migrate from KANBAN.md + HANDOFF.md
at the bottom. The old assets/kanban-template.md and assets/handoff-template.md are gone —
nothing writes those files any more.
Why issues rather than files
Concurrent agents conflict on a shared Markdown board — every card move is a diff on the same lines,
and a lost merge silently drops someone's state. Issues have no merge step. They also close the loop
the files could not: an issue can be referenced by a commit, closed by a PR, and counted by a
milestone.
Read only what the action needs
| Action | Read |
|---|
| Selecting or picking up work | the board, filtered to your Status/Agent |
| Resuming or taking over a task | that issue's thread — body plus comments |
| Pausing, or approaching a limit | nothing; write a handoff comment |
| Finishing | that issue, to write the closing comment |
| Releases or historical review | CHANGELOG.md |
Do not load the whole board to do one task. Do not create a status file of any kind — no
HAPPENING_NOW.md, no KANBAN.md, no HANDOFF.md.
The board
A GitHub Projects v2 board in board layout, with the item's Status field as the column. Four
columns: Backlog, To Do, In Progress, Done. Agents move their own items.
Three fields carry what the old badges did:
- Status (single select) — the column.
- Agent (single select) — who owns it:
Claude, Codex, ChatGPT, Antigravity, Hermes,
Owner. Filter and group by this.
- Added (date) — when the task entered the board. Immutable; never rewrite it when moving an item.
The Agent field is the identity — do not try to replace it with per-agent tokens. A PAT
authenticates as the account that issued it, so four agent tokens all comment as the same user.
Every real alternative was checked against the docs and each is gated on something an agent cannot
do:
- Machine accounts are permitted, but the ToS §B.3
allows one free machine account per person on top of the personal account — enough for one
agent, not four. More requires paid seats, which requires an organization.
- GitHub Apps give each agent a distinct
name[bot] author for free, but (a) they can only be
registered through the web UI — there is no REST endpoint, so no agent can create one — and (b)
the Projects permission
exposes only /orgs/{org}/projectsV2/...; there is no user-level equivalent, so an App cannot
move a card on a user-owned board. The App route therefore requires an org-owned project, and
Projects v2 boards cannot be transferred between owners — the board has to be rebuilt.
So every comment opens with the agent name in bold, and the Agent field carries the rest. Revisit
only if the project moves into an organization for some other reason.
Add worktree, branch and machine to the issue as a comment when — and only when — an item moves to
In Progress and the work is machine-specific:
**Claude** · picked up · `Ivanna's MacBook Neo` · `/Users/ivanna/apps/<repo>` · branch `master`
Set a board capacity if the user wants one (default 20 active items, counting everything not Done).
Over capacity, close the oldest Backlog item as not planned rather than deleting it — a closed
issue stays searchable, a deleted card does not.
Milestones — the helicopter view
Milestones answer "are we going to make it", which neither the board nor the changelog can.
Closing an issue advances its milestone automatically — the progress bar is closed / total,
recomputed by GitHub with no extra step. That is the whole reason to use them: progress is a
by-product of finishing work, not a report someone maintains.
Consequences worth designing around:
- Pull requests can be milestoned too, and they count. A milestone tracks "open and closed issues
and pull requests", so milestoning a PR inflates the denominator, then the numerator when it merges
— the bar moves without any task being finished. Do not milestone PRs. Link the PR to its issue
(
Closes #N) and let closing the issue move the bar.
- Milestones are repository-scoped. A board can span repositories; a milestone cannot. Work split
across repos needs one milestone per repo, and the progress bars will not add up.
- One issue belongs to exactly one milestone. Milestones do not stack like labels. If a task
genuinely spans two phases, split the issue.
- An issue with no milestone is invisible to the helicopter view. Assign at creation time —
gh issue create --milestone "<title>" accepts it directly, so there is never a reason to leave it
for later.
- Progress measures issue count, not effort. Ten trivial issues and one release-blocking issue
read as 91% when the blocker is the only thing that matters. Keep issues comparable in size, or
read the bar with that in mind.
- A due date that has passed shows as overdue and never self-corrects. Reschedule or close it.
Derive milestones from the project's own timeline document if it has one, so the board and the plan
cannot drift apart. Give each a due date and a one-line exit condition as its description — what must
be true at exit, not what work happens inside it.
gh issue create --title "…" --body-file body.md --milestone "Block A — Unblock the spine"
gh api repos/OWNER/REPO/milestones --jq '.[] | "\(.title): \(.closed_issues)/\(.open_issues + .closed_issues)"'
Handoff — a comment, not a row
Unfinished work is protected by commenting on its issue. Upsert nothing; append. The newest comment
is the current state, and the thread keeps the history the single-row format used to overwrite.
Write a handoff comment when:
- an unfinished task changes agent, worktree, branch, or session;
- the user pauses, exits, or asks another agent to continue;
- work becomes blocked and the blocker matters to the next agent;
- the usage guard reaches 200 or 300 tool calls;
- the agent is about to compact context;
- the agent must stop before completing verification.
At 100 tool calls, show a note only. At 200, comment immediately if work is unfinished. At 300, start
no new work; comment, finish only the smallest safe verification unit, and yield.
Use these four headings, and keep the issue's Status field in step:
**Claude** · handoff · 2026-08-05
### Done
What is complete, and how it was verified.
### Learned
Reusable findings, decisions, gotchas. The why, not the what.
### Blockers
What prevents completion, or `None`.
### Next
The exact next action, specific enough to execute without this conversation.
Avoid narrative history. When the task completes, the closing comment replaces the handoff — do not
leave a stale "Next" as the last word on a closed issue.
scripts/handoff_usage_guard.py is a pressure signal, not a semantic
writer. It never fabricates a handoff comment.
Closing an issue
The closing comment is the delivery record. It must carry:
- What changed, as one to three compact past-tense bullets beginning
Added, Fixed,
Improved, Updated, or Removed — observable outcomes, not process narration.
- What was learned that outlives the task, when there is anything.
- Visual evidence, for anything gameplay-, UI-, or art-visible.
Evidence images are committed to the repository under docs/changelog/<date>-<slug>/ and embedded
by raw URL — an agent cannot upload an attachment to a comment, there is no CLI for it:

Plain links are not enough; the image must render inline. Pass a real multiline body — use
gh issue comment --body-file, never shell-escaped \n.
CHANGELOG.md
One newest-first row per delivered task, and nothing more:
| Date | Issue | Delivered |
|---|
| 2026-08-05 | #284 | Fixed in-level mute silencing sound only, which swallowed the easter-egg music |
One line, one issue link, no screenshots, no learnings, no agent column — all of that is in the issue
and duplicating it is how the two drift apart. The file exists for the one thing the issue tracker
cannot do: answer "what shipped, newest first" with grep, offline, in a repo you just cloned.
Use $manage-git-releases for release versions, annotated tags, tag safety, and version-range notes.
Migrate from KANBAN.md + HANDOFF.md
The two files described the same task twice — the board held one-paragraph state, the handoff held
Done/Learned/Blockers/Next detail. They merge into one issue, so migrate them together, never one
first.
- Pair them up. For each Kanban card, find the handoff row for the same task. Card text becomes
the issue body's summary; the handoff row becomes its
### Handoff section.
- Drop completed handoff rows, but list what was dropped and why in the migration manifest — a
row whose every column reads RESOLVED/DONE/None has already been superseded, and silently
deleting it is indistinguishable from losing it.
- Active cards become real issues;
Done cards become plain board cards. A closed-and-migrated
history issue is noise, and its evidence already lives in the pre-migration changelog.
- Freeze, do not delete, the old changelog if it holds screenshot evidence for shipped work.
Add a header noting history continues in issue comments from the cutover date.
- Assign every new issue to a milestone in the same pass. Migrating without milestones produces
a flat backlog with no helicopter view, which is worse than the files were.
- Update every reference to the deleted files — agent definitions, project instructions, other
skills, and docs — before deleting them. A dangling instruction to "read HANDOFF.md" makes the
next agent invent one.
Keep the migration manifest in the repository until the board has survived a release cycle. It is
the only audit trail of what was merged into what.
Final check
- Confirm only the issues needed for this action were read.
- Confirm the item has
Status, Agent, and Added set, and a milestone.
- Confirm unfinished work has a current handoff comment when a trigger applies.
- Confirm completed work is closed with a delivery comment whose evidence renders inline.
- Confirm
CHANGELOG.md has exactly one new row, linking the issue.
- Ask before committing or pushing unless the user already authorized it.