Applies to every codebase, not one project.
Any document written as the output of a session - an investigation, a root-cause writeup, an
analysis, a plan, a draft message, review notes - goes in the current codebase's _agent/docs/
directory. Permanent project documentation (docs/, README.md, ADRs, RFCs) is a different thing
and follows that repo's own rules.
_agent/ is the one folder for everything an agent leaves behind in a repo: _agent/docs/ for
these documents, _agent/handoff/ for the handoff skill's step logs. It is never committed.
The instructions
1. Write it to <repo-root>/_agent/docs/
# The MAIN checkout - never the cwd (may be a subdirectory), never a worktree root.
ROOT=$(cd "$(git rev-parse --path-format=absolute --git-common-dir)/.." && pwd)
If $ROOT/_agent is not present, create it and add it to .git/info/exclude so it never shows
up in git status. The exclude file is per clone and never committed, so no tracked file is touched:
mkdir -p "$ROOT/_agent/docs" # creates _agent/ when missing
grep -qx _agent "$ROOT/.git/info/exclude" 2>/dev/null || echo _agent >> "$ROOT/.git/info/exclude" # appends only when missing
git -C "$ROOT" check-ignore -q _agent || echo "WARNING: _agent is not ignored"
Run all three lines every time rather than testing for the folder first: they are no-ops when
everything is already in place, and a _agent/ someone created by hand without the exclude would
otherwise start showing up as untracked.
Not --show-toplevel. In a git worktree that resolves to the worktree's own root, and
because _agent/ is excluded from git the document does not travel back with the branch - it is
deleted with the worktree and the work is lost silently. --git-common-dir points at the main
checkout's .git from anywhere, so the line above lands in the same _agent/docs/ whether it
runs in the main checkout, a subdirectory of it, or a worktree. Agent sessions often run in a
throwaway worktree, so this is the normal case, not an edge one.
The same applies to the exclude file: a worktree's .git is a file, not a directory, so
<worktree>/.git/info/exclude does not exist. Resolving ROOT this way makes that path correct
too, and the exclude is shared by every worktree.
No git repository (a plain folder): ROOT is the folder itself, there is nothing to exclude,
and _agent/docs/ simply sits next to the work.
Name the file for the subject, kebab-case: apple-review-4.12-rejection-investigation.md,
coredata-migration-plan.md. If you know the ticket number, start the filename with it:
proj-42-search-duplicates.md.
When a subject grows into its own folder (section 3), key the folder the way the handoff skill
keys its step logs - the ticket, else a short slug - so the two are findable from each other:
_agent/docs/PROJ-42-search-duplicates/ pairs with _agent/handoff/PROJ-42/.
2. Put a session link in the header
Directly under the H1, one italic line - date, then the session log that produced the document:
# Apple review 4.12 rejection - investigation
*Written 2026-08-14. Session log: `~/.claude/projects/<project-key>/<SESSION-ID>.jsonl` (`claude --resume <SESSION-ID>`)*
Why: months later the document is the only artifact left, and the reasoning behind every number in it lives in the transcript. Without the id there is no way back to it except guessing at mtimes.
Finding the current session id (Claude Code). It is the UUID directory in the scratchpad path given in the system prompt:
/private/tmp/claude-<uid>/<project-key>/<SESSION-ID>/scratchpad
That same <project-key> is the log directory name (the absolute cwd with / replaced by -),
so the log is:
~/.claude/projects/<project-key>/<SESSION-ID>.jsonl
Verify it exists before writing the line - ls it. If there is no scratchpad path in context,
fall back to the newest log for this repo and say in the doc that it is inferred:
ls -t ~/.claude/projects/"$(pwd | tr / -)"/*.jsonl | head -1
An agent without a --resume equivalent (Codex) writes Session: none (<tool>) instead of the
log path, and leaves the resume line out rather than inventing one.
3. Once a subject has more than about four documents, add a README.md
A folder of working notes written over days stops being a set of drafts and becomes a small corpus, and a reader cannot tell which document is current. Give the folder an index:
- name the canonical document in the first line, so a reader knows where to start
- one table row per document with a one-line status: canonical, current, historical, superseded
- a short "where the investigation landed" paragraph, so the folder answers the question without anyone opening a second file
- a section listing the conclusions in these documents that turned out to be wrong, with the evidence that killed them
- a
Handoff log:line naming_agent/handoff/<key>/, when a handoff log exists for the same work
That last section is the one that earns its place. Working notes are written in the order things were believed, not in the order they turned out to be true, so a folder always contains superseded reasoning. Left unmarked, the next reader re-derives it from the same data.
4. When a conclusion is overturned, banner the document
A note buried in a section does not stop anyone. Put a blockquote directly under the H1 and the session line:
> **Superseded.** <one sentence on what is still valid and what is not.> Current picture:
> [`<canonical>.md`](./<canonical>.md), and [`README.md`](./README.md) for how these relate.
>
> <the specific wrong claim, and why it was wrong.>
Say what is still valid as well as what is not. Most superseded documents are partly right, and deleting them loses the evidence trail, so mark them rather than removing them.
Do not rewrite history inside the body. The value of a superseded document is that it records what was believed and on what basis.
5. Pair with the handoff log, do not duplicate it
When the same work also has a handoff step log, the two split the truth:
| Owns | Does not hold | |
|---|---|---|
_agent/docs/<key>-<slug>/README.md |
What we know: the canonical document, each file's status, where it landed, the conclusions that turned out wrong | Next moves, session state |
_agent/handoff/<key>/NN-step.md |
What happens next: the next moves, verified vs believed, how to check the tree | Findings - it links the README instead of restating them |
Link both ways: the README carries the Handoff log: line, and each handoff step carries a
Working notes: line pointing at the README. Two copies of the same state drift apart; one
owner per fact does not.
Notes
- These documents are drafts by default. When one becomes canonical somewhere else (the issue
tracker, a wiki, the repo's
docs/), put a superseded pointer at the top of the local copy rather than leaving two live versions. - A repo may already have working notes under another name (
llmtemp/,scratch/,notes/,.ai/). Read from it when a subject's history lives there; never write a new document into it. Offer the move once, do not do it unasked:mv "$ROOT"/<old>/* "$ROOT"/_agent/docs/ && rmdir "$ROOT"/<old>. A leftover exclude line for the old folder is harmless, leave it.