Agent handoff document generator (HANDOFF.md)

Updated

Fill in the form and a complete HANDOFF.md builds itself in the preview: goal, current state, how to run and test, key files, decisions with their reasons, open questions, ordered next steps, constraints, owners, and links. Tick the option to add a preamble written for an AI coding agent. Copy it, download it, or publish it as a link the next person or agent can fetch. Everything runs in your browser; the draft autosaves locally.

Pre-filled with a sample; your edits autosave in this browser.

Project

What "done" means. The next reader judges every step against this line.

Current state — one item per line

How to run and test — one command per line

Key files

Decisions and open questions

Write “decision — why”. The part after the dash becomes the Why column.

What happens next

Rendered as a numbered list; the first line is what the next reader should do first.

People and links

Options

What the agent should read, and what it should not load.

HANDOFF: Invoice export service

Repo: acme/billing-api · Branch: feat/csv-export · Written: 2026-10-15 14:46 UTC

Goal

Customers can download a CSV of all invoices for a date range from the billing dashboard.

For an AI agent

  • Read this whole file before changing anything, then continue from Next steps in order.
  • Context budget: Read this file, then only the files listed under Key files. The repo is large; do not scan it whole.
  • Do not touch: lib/invoices/csv.ts, prisma/migrations/
  • Do not re-do items listed under Done; verify them with the commands below if in doubt.
  • If the branch head differs from what this file describes, treat the file as a starting point, not the truth.

Verify before and after your changes:

npm run lint
npm test -- invoices
curl -s "http://localhost:3000/api/invoices/export?from=2026-01-01&to=2026-01-31" | head -3

Status

ItemStatus
Added GET /api/invoices/export?from=&to= returning text/csv (streamed, 10k rows/sec in local tests)Done
Unit tests for the CSV writer, including quoted commas and UTF-8 namesDone
Feature flag csv_export wired through config/flags.ts, default offDone
Dashboard button in app/billing/InvoiceList.tsx — renders, but the date picker is not passed through yetIn progress
Exports over 50k rows time out at the 30 s gateway limit — needs a decision on background jobs vs paginationBlocked

Current state

Done

  • Added GET /api/invoices/export?from=&to= returning text/csv (streamed, 10k rows/sec in local tests)
  • Unit tests for the CSV writer, including quoted commas and UTF-8 names
  • Feature flag csv_export wired through config/flags.ts, default off

In progress

  • Dashboard button in app/billing/InvoiceList.tsx — renders, but the date picker is not passed through yet

Blocked

  • Exports over 50k rows time out at the 30 s gateway limit — needs a decision on background jobs vs pagination

How to run and test

Run:

npm install
cp .env.example .env.local
npm run dev

Test:

npm run lint
npm test -- invoices

Key files

FileWhat it does
app/api/invoices/export/route.tsThe export endpoint; streams rows from the repository
lib/invoices/csv.tsCSV writer with RFC 4180 quoting — do not swap for a library
app/billing/InvoiceList.tsxDashboard list; the new Export button lives here
config/flags.tsFeature flags; csv_export gates the whole feature

Decisions

DecisionWhy
Stream the response instead of bufferingmemory stayed flat at 100k rows
Dates are exported as ISO 8601 in UTCmatches the existing JSON API, avoids locale bugs
No Excel BOM prefixthe two customers who asked use Google Sheets, which does not need it

Open questions

  • Should exports over 50k rows become an emailed background job?
  • Do we need per-currency columns, or is a single amount + currency column enough?

Next steps

  1. Pass the selected date range from the picker into the Export button
  2. Add an integration test for the 50k-row case (currently fails with a gateway timeout)
  3. Turn the flag on for the internal workspace and watch error rates for a day
  4. Write the help-center article and link it from the button tooltip

Constraints and gotchas

  • The invoices table has no index on created_at in production — the query plan is fine under 100k rows only
  • A pre-existing lint warning in lib/legacy/totals.ts is unrelated; leave it
  • CI runs on Node 20; Array.fromAsync is not available

Owners and contacts

  • Feature owner: Priya (billing team)
  • Reviewer: Marco
  • On-call for the gateway: #platform channel

Handoff written 2026-10-15. Update this file before you stop; the next reader starts here.

Nothing leaves your browser unless you click Share as link. The draft is kept in this browser's localStorage only.

What does a good handoff document contain?

The generator emits the sections below in this order. The third column is the reason the section exists from the reader's side, which is also the test for whether yours is good enough: if an agent given only the file would still have to ask, the section is too thin.

SectionWhat to writeWhy the next agent needs it
GoalOne sentence that defines "done" and names what must not change.Every later judgment ("is this step worth doing?") is made against this line. Without it an agent optimizes for the wrong thing.
Repo and branchowner/name and the branch the work lives on; the base branch if it is not main.An agent cannot guess which checkout the rest of the document describes.
Current stateThree lists: done, in progress, blocked. Facts, not intentions.Prevents redoing finished work and flags the half-finished edit that will otherwise look like a bug.
How to run and testThe exact commands, one per line, in a code block.Commands are the fastest way for an agent to verify the state before trusting the prose.
Key filesPath and one line on what it does, as a table.Turns "explore the repo" (slow, expensive in context) into "read these four files".
Decisions and whyEach choice with its reason, as a table.The reason is what stops the next person from reversing a decision that was made for a cause they cannot see.
Open questionsThings nobody has decided yet.Marks where the agent should ask instead of assume.
Next stepsA numbered list, first thing first.An ordered list is executable; a paragraph of suggestions is not.
Constraints and gotchasLimits, known-bad paths, pre-existing warnings to ignore.Saves the hour that would be spent "fixing" something that is unrelated or intentional.
Owners and linksWho to ask, and the ticket, design doc, PR.Gives the reader an escalation path and the source documents behind the summary.
For an AI agent (optional)Context budget, do-not-touch paths, verification commands.Agents follow explicit limits well and implicit ones badly; stating them costs three lines.

Minimal or full template: which one do I need?

A handoff for a one-hour fix and a handoff for a week of feature work are not the same document. Fill in only the fields you need; the generator drops empty sections.

 Minimal (same-day, one reader)Full (multi-day, agent or new teammate)
SectionsGoal, Current state, Next stepsAll eleven, including the AI-agent preamble and status table
Length10–25 lines60–120 lines
CommandsOnly if they differ from the READMERun, test, and verification commands, each in its own code block
Key filesSkip, or list the one or two you touchedTable of every file the next step needs, with a one-line purpose
DecisionsBullets, no reasonsDecision and reason as a table, so reversals are deliberate
Where it livesPull request description or a chat messageHANDOFF.md in the repo root, or a shared link pasted into the next session
TimestampsOptionalYes, so a stale handoff can be spotted against the git log

How do I hand the file to the next agent?

Three ways, in increasing order of ceremony. Commit HANDOFF.md to the branch and start the next session with "read HANDOFF.md and continue from its next steps". Or paste the markdown into the first message of the new session. Or click Share as link and give the agent the raw URL, which returns the file as text/markdown for any assistant with an HTTP tool. The HANDOFF.md walkthrough covers the MCP and curl variants, and sharing an implementation plan covers the review step that often precedes a handoff. For the markdown syntax used in the output, see the markdown cheat sheet; for the project-level document that sits next to the handoff, use the README generator.

What is a HANDOFF.md file?

HANDOFF.md is a markdown file written at the end of a work session that records the goal, what is done, what is in progress or blocked, how to run and test the code, which files matter, which decisions were made and why, and the ordered next steps. It is read by the next developer or AI coding agent so they can continue without reconstructing the context. The name is a convention, not a standard; agent-handoff.md and HANDOVER.md are the same thing.

How is a handoff different from a README?

A README describes a project for anyone, at any time: what it is, how to install and use it. A handoff describes one piece of work, right now, for one reader: where it stands and what to do next. A README is stable; a handoff is rewritten every time work stops. Generate the README with the README generator and keep the handoff next to it, or in the pull request description.

What should the "for an AI agent" preamble say?

Three things an agent cannot infer: how much to read (the context budget: "this file plus the key files, do not scan the repo"), what not to modify (paths with a reason), and how to verify state before and after changes (the exact commands). The generator writes these as the first section so the agent sees them before it acts. It also tells the agent to compare the branch head with the handoff and treat the document as a starting point if they differ.

Is anything uploaded while I type?

No. The markdown is assembled in your browser and the draft is saved to this browser's localStorage so a reload does not lose it. The only network request happens if you click Share as link, which publishes the markdown to a URL that expires in 30 days and returns a raw text URL an agent can fetch. Do not share a handoff that contains tokens, keys, or customer data; the link is readable by anyone who has it.

How long should a handoff be?

Long enough that the reader does not have to ask you anything, short enough to read in two minutes: usually 40 to 120 lines. Empty sections are omitted automatically, so a small task produces a small file. If the next steps list is longer than ten items, the task is probably two tasks and deserves two handoffs.

More markdown tools