# Handing work to the next session

> End a session that stopped halfway with a handoff file that names the state, the decisions and what was ruled out, and count the turns a fresh session needs with and without it.

Page: https://schubergphilis.github.io/ai-training/customizing-agents/session-handoff/
License: CC BY-SA 4.0, https://creativecommons.org/licenses/by-sa/4.0/

A coding session often ends before the work does. The next session, yours
tomorrow or a colleague's, starts without the conversation. In this lesson
we end a session with a handoff file and measure what it saves: the number
of turns a fresh session needs before it does useful work, first from the
diff alone and then from the handoff.

The lesson uses Claude Code, and the files are in the course repository at
`site/examples/customizing-agents/session-handoff/`. `session.md` is the log
of a session that stopped halfway, written for this lesson.
`setup_practice.py` builds a practice repository in the state that session
left behind, and `check_handoff.py` checks a handoff file. Both are short
Python scripts. The first builds its repository in a new directory that
you name, and the second only reads the file you give it. Run the commands
in this lesson from that directory. In the `cd` line, replace
`<course-repo>` with the path to your copy of the course repository.

```sh
cd <course-repo>/site/examples/customizing-agents/session-handoff
```

## What the next session starts from

In Claude Code, a new session doesn't see the conversation of an earlier
one, and its context window starts empty (How Claude Code works, Claude Code documentation).
At its start it loads `CLAUDE.md` and the auto-memory notes
(How Claude remembers your project, Claude Code documentation). Everything else it learns from the repository, and
that includes the changes that aren't committed yet.

The Agent Engineer Course separates a session from its state. The
session is the full history of messages, tool calls and results. The state
is a short summary of the facts that matter, which is quicker to use than
the history (Memory and context: context engineering, memory kinds, memory versus RAG, context rot, Agent Engineer Course). A **session handoff** is that state, written to a
file before the session ends: what was done, what is left, what was decided
and why, what was tried and ruled out, and where the files are. The next
session reads the file and starts from it.

Claude Code can also reopen an old conversation. `claude --continue`
opens your last conversation in this directory again, and
`claude --resume` shows the saved conversations so that you can pick one
(Best practices for Claude Code, Claude Code documentation). That helps when you continue the same work
on the same computer, because Claude Code keeps the conversations as files
on your own computer, in `~/.claude/projects/` (How Claude Code works, Claude Code documentation).
A colleague on another machine can't resume them. A resumed conversation also
brings back its whole history, and that includes the approaches that went
wrong. The best-practices page gives advice for the case where you have
corrected the agent more than twice on the same problem: clear the
conversation, and start again with a prompt that states what the failed
attempts taught you (Best practices for Claude Code, Claude Code documentation). A handoff file is that
prompt, written down before the session ends.

#### Checkpoint: What does the new session know?

Yesterday's session ended before the work was done, and nobody wrote
anything down. What does today's new session have to go on?

- All of yesterday's conversation, because Claude Code saves every conversation on your machine.
- The repository with its uncommitted changes, and nothing about why you ruled out the approach.
- The files the old session read, because Claude Code loads them again when a new session starts.
- Only the last commit on main, because a new session ignores the changes that are not committed.

## Start from the diff alone

Read `session.md` first. In it a user and an agent work on a bug in a small
report service: the export writes a report created at midnight on 1 March
in Auckland as 11:00 on 28 February. The agent first changes the test to
expect the wrong time. The user rules that out, and then rules out the
server's time zone too. Three decisions follow, each with a reason. The
session stops before any code is changed, and the edit to the test is
still there.

Build two practice repositories from the same state, one for this section
and one for the rest of the lesson. The script refuses a directory that
already exists.

```sh
python3 setup_practice.py ~/handoff-diff-only
python3 setup_practice.py ~/handoff-practice
```

Here is what a fresh session finds in either of them: the output of
`git status --short`, `git diff --stat=60` and the tests.

#### Example: Look at the practice repository

Run these in `~/handoff-diff-only`, and compare with the output below. The
last line is the verdict of `python3 -m unittest -q`, which prints
`Ran 4 tests` and then `OK` in your terminal.

```sh
git status --short
git diff --stat=60
python3 -m unittest -q
```

Output:

```text
M test_reports.py
 test_reports.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
tests: OK
```

The repository shows one changed line in a test and a green suite. It
doesn't show that the change was ruled out, or why, or what the fix
should look like. Now let a fresh session work from that. Start Claude
Code in `~/handoff-diff-only` with two settings. The environment variable
`CLAUDE_CODE_DISABLE_AUTO_MEMORY=1` turns auto-memory off
(How Claude remembers your project, Claude Code documentation), so no memory note can carry facts from one practice
session to the next. `--permission-mode default` starts Manual mode, where
the agent may read files without a prompt and asks before edits and
commands (Choose a permission mode, Claude Code documentation), so you see the steps it wants
to take.

```sh
cd ~/handoff-diff-only
CLAUDE_CODE_DISABLE_AUTO_MEMORY=1 claude --permission-mode default
```

Type this as your first message:

```text
Continue the work in progress in this repository.
```

Count your turns: each message you type is one, and the first message
counts. Useful work has started when the agent undoes the edit to the
test, or starts to change `format_ts()` so that each time keeps its own
offset. If the agent asks a question, answer it from `session.md`, and
count the answer. Stop after five turns if useful work hasn't started, and
write down "more than 5". Then leave with `/exit` and write down your
count. A model answers differently each time, so your count may differ
from a colleague's.

#### Checkpoint: The fresh session says it is done

The fresh session answers: "The expected value in `test_export_timezone`
was updated to match the UTC output, and all 4 tests pass. Shall I commit
the change?" What do you do?

- Approve the commit, because the tests pass and the diff is only one line.
- Ask the agent to run the tests once more before it commits the change.
- Tell the agent to read the log of yesterday's session under ~/.claude/projects/ and work it out.
- Tell the agent that the test edit was ruled out and why, and write the reason down for the next session.

## Write the handoff before the session ends

A handoff is written by the session that did the work, before it ends. In
this lesson that session is the one in `session.md`, so you replay it and
then ask for the handoff. Start Claude Code in `~/handoff-practice` with
the same two settings.

```sh
cd ~/handoff-practice
CLAUDE_CODE_DISABLE_AUTO_MEMORY=1 claude --permission-mode default
```

Open `session.md` in an editor, copy from the first `**User:**` line to
the end, and paste it as your first message. If the agent asks to edit a
file, answer no. Then ask for the handoff:

```text
Write HANDOFF.md for the next session on this work. Name the current state and the next step, every decision with its reason, the failing test, what was tried and ruled out and why, and the files to look at. Use only this conversation and the repository, and change no other file.
```

Approve the edit that writes `HANDOFF.md`, and leave with `/exit`. If
Claude Code prints a message that says it saved memories, auto-memory is
still on (How Claude remembers your project, Claude Code documentation). Then build a new practice repository with
another name and start again.

Check the file from the course directory:

```sh
cd <course-repo>/site/examples/customizing-agents/session-handoff
python3 check_handoff.py ~/handoff-practice/HANDOFF.md
```

The script looks for the words that name each fact the next session needs
and prints `named` or `missing`. It only matches words, so open the file
and read it before you trust a `missing`, and a `named` only means that the
words are there. The course repository has two
handoffs written for the lesson, and no model produced them.
`samples/files-only.md` lists the changed file and the files to read, and
it has no decisions.

#### Example: Check the handoff that lists files

Run this, and compare with the output below.

```sh
python3 check_handoff.py samples/files-only.md
```

Output:

```text
samples/files-only.md
  state, undo the edit to test_reports.py: missing
  decision, keep each offset, for customers: missing
  decision, UTC stays Z, for billing: missing
  decision, no offset means UTC: missing
  failing test, test_export_timezone: missing
  ruled out, the server's time zone: missing
  where the fix goes, format_ts(): named
named 1 of 7
```

A fresh session that reads this file learns where to look and still
repeats the test edit. `samples/full.md` has a section for the state,
the decisions with their reasons, what was ruled out, and the next steps
in order.

#### Example: Check the full handoff

Run this, and compare with the output below.

```sh
python3 check_handoff.py samples/full.md
```

Output:

```text
samples/full.md
  state, undo the edit to test_reports.py: named
  decision, keep each offset, for customers: named
  decision, UTC stays Z, for billing: named
  decision, no offset means UTC: named
  failing test, test_export_timezone: named
  ruled out, the server's time zone: named
  where the fix goes, format_ts(): named
named 7 of 7
```

If your `HANDOFF.md` misses a fact that is really gone, add it by hand.
The handoff is yours to correct before the next session reads it.

#### Checkpoint: Which lines belong in the handoff?

Which two lines tell the next session something it can't find in the
repository?

Select exactly 2.

- Ruled out: converting to the server's time zone, because the servers run in UTC.
- Changed: test_reports.py, because the test for the time zone export was edited.
- Decision: UTC stays in the Z form, because the billing import reads only that form.
- Output: the complete text of the last test run, with the trace of the failure.

## Start fresh from the handoff

Now start a new session in `~/handoff-practice`, with the same two
settings as before:

```sh
cd ~/handoff-practice
CLAUDE_CODE_DISABLE_AUTO_MEMORY=1 claude --permission-mode default
```

Then type:

```text
Read HANDOFF.md and continue the work.
```

Count the turns until useful work starts, by the same rule as before, and
leave with `/exit`. Compare the two counts. With a handoff that names the
ruled-out edit, the agent can start on the next step in its first answer.
Without it, the agent may commit the wrong test, or you spend turns
telling it what the log says. One pair of counts says little on its own,
because a model answers differently each time. The handoff changes what
the agent knows at its first turn, and that holds on every run.

The handoff is for this piece of work, and it goes where the work is. Keep
`HANDOFF.md` on the branch until the work is done, and delete it with the
last commit. A fact that outlives the work belongs somewhere else. A
decision with lasting reasons, such as the `Z` form for the billing
import, goes in a decision file, as
[Keep the reasons where the agent reads them](https://schubergphilis.github.io/ai-training/coding-with-agents/keeping-understanding/#keep-the-reasons-where-the-agent-reads-them)
described. A rule that every session needs goes in the project-root
`CLAUDE.md`, which each session loads at its start (How Claude remembers your project, Claude Code documentation).

#### Pitfall: The handoff that listed only files

A developer ends the session with a handoff that lists the changed files,
the files to read and "tests pass". The next morning a fresh session
reads it, sees the edited test and the green suite, and commits the edit
that was ruled out the day before. Every line of the handoff was true, and
none of them said what was decided or why. A list of files repeats what
`git status` shows. Write the decisions with their reasons and what was
ruled out, because those facts are in no file.

## Exercise

If you followed the steps above, you have the exercise: your
`HANDOFF.md`, its result from `check_handoff.py`, and two counts. Otherwise
do the steps now: build two practice repositories, count the turns of a
fresh session in the first, replay `session.md` in the second and have
the agent write `HANDOFF.md`, and count the turns of a fresh session that
starts from it. The agent works in copies that the script built, and in
Manual mode it asks before edits. The steps take about fifteen minutes
and show you what a handoff saves in turns.

A good result: `HANDOFF.md` names the ruled-out test edit, the server's
time zone, the three decisions with their reasons and the failing test,
and the fresh session starts useful work in its first turn or second
turn. The count without a handoff is higher, or the agent went wrong
where you didn't correct it. If the fresh session found the fix from the
code alone, ask it which decisions it followed and why. It can't name the
billing import or the database team, and those reasons are what the
handoff adds. When you are done, delete the practice directories you
built. In your own last session that stopped halfway, what did you
rule out that no file shows?

Stretch: Write a second handoff by hand for the same session, from the log alone and without the agent. Start a new practice repository from it and compare its count with the first.

## Recap

1. A new Claude Code session starts without the old conversation. It
   loads `CLAUDE.md` and auto-memory and reads the rest from the repository
   (How Claude Code works, Claude Code documentation) (How Claude remembers your project, Claude Code documentation).
2. A session handoff is the state of the work written to a file before the
   session ends: what is done, what is left, the decisions with their
   reasons, what was ruled out, and where the files are (Memory and context: context engineering, memory kinds, memory versus RAG, context rot, Agent Engineer Course).
3. The diff shows what changed. The reasons and the rejected approaches are
   only in the conversation, so they are what the handoff must hold.
4. Resuming works on your own machine, and it brings back the approaches
   that went wrong too. A handoff works for any session and for a colleague
   (How Claude Code works, Claude Code documentation) (Best practices for Claude Code, Claude Code documentation).
5. Keep the handoff with the work and delete it when the work is done. Move
   a lasting decision to a decision file and a rule for every session to
   `CLAUDE.md`.

#### Habit

The next time you stop a session before the work is done, have the agent
write a handoff with the decisions and what was ruled out, and read it
before you close the session.

## References

- How Claude Code works, Claude Code documentation, https://code.claude.com/docs/en/how-claude-code-works
- How Claude remembers your project, Claude Code documentation, https://code.claude.com/docs/en/memory
- Memory and context: context engineering, memory kinds, memory versus RAG, context rot, Agent Engineer Course, https://lsimons.github.io/agent-engineer-course/05-memory-and-context/
- Best practices for Claude Code, Claude Code documentation, https://code.claude.com/docs/en/best-practices
- Choose a permission mode, Claude Code documentation, https://code.claude.com/docs/en/permission-modes
