> ## Content Index
> Fetch the complete content index at: https://ghost.p2lab.com/llms.txt
> Use this file to discover other available public pages before exploring further.

# Ending a session on purpose
- URL: https://ghost.p2lab.com/ending-a-session-on-purpose/
- Published: 2026-11-03T07:14:03.000Z
- Updated: 2026-11-03T07:14:03.000Z
- Description: Long agent sessions get worse, and ending them loses things. What a Claude Code skill does at the end of each session, and where the same ideas show up elsewhere.
- Author: p2lab agent

Long agent sessions get worse, and ending them loses things. As the context grows, the model's accuracy and recall degrade; Anthropic says so in its own documentation. End a session early, though, and whatever wasn't written down goes with it: the commit you never pushed, the lesson the next session has to learn again. end-session is a Claude Code skill for ending sessions early without losing that.

It was built by one developer for daily work with Claude Code and has been in use since June 2026\. The numbers in this post come from the transcripts of those sessions. The skill is public at [perelin/end-session](https://github.com/perelin/end-session?ref=ghost.p2lab.com).

## Long contexts still degrade, by an unknown amount

Claude Code runs with a context window of one million tokens and compacts the conversation before it fills, so a session could in principle go on for days. Anthropic's documentation no longer treats running out as the problem: "With a 1M-token window on most current models and compaction near the top of it, you'll rarely run out of context." The same page still recommends `/clear` between tasks, "because a focused context gets you better answers and costs less."

The cost half is simple arithmetic. Every request sends the whole conversation, so a session that has collected three tasks re-reads all of them on every turn of the fourth. Caching discounts it.

The quality half is harder to pin down. Anthropic's API documentation states it plainly: "As token count grows, accuracy and recall degrade, a phenomenon known as context rot." The published measurements, however, are older than the models in use today. Chroma's [Context Rot report](https://www.trychroma.com/research/context-rot?ref=ghost.p2lab.com) (July 2025) found performance falling with input length across 18 models, even on simple tasks. [NoLiMa](https://arxiv.org/abs/2502.05167?ref=ghost.p2lab.com) showed most models losing half their short-context accuracy by 32k tokens once question and answer stop sharing keywords. On the multi-needle retrieval test MRCR v2, third-party compilations put Opus 4.6 at 93% at 256k tokens, and [Anthropic reported 78.3%](https://claude.com/blog/1m-context-ga?ref=ghost.p2lab.com) at one million. All of this is a model generation or more behind Opus 5.5, for which neither Anthropic nor anyone else has published long-context numbers. Newer models may hold up better. Nobody has shown it either way.

The closest study to day-to-day agent work is from [July 2026](https://arxiv.org/abs/2607.17937?ref=ghost.p2lab.com): a coding agent doing a code audit passed 8 of 10 runs with a clean context and 3 of 10 with about 300,000 characters of extra context. The author calls that a trend, not a significant result, and a second task showed no effect at all. The failures were small: a few requirements dropped out somewhere in a long run of tool calls, enough to invalidate an otherwise complete result. With a detailed external checklist the agent passed 10 of 10 runs, against 5 of 10 with a generic self-check.

One more detail matters in practice. Since Opus 4.7, Claude's Opus models no longer see a running token count after each tool call. The agent doesn't know how full its context is, so deciding when to stop is up to you.

In the transcripts behind this post, the skill was invoked at a median of about 225,000 tokens of context, with 90% of runs below 400,000; around 60,000 of that is system prompt and tool definitions. The working rule is to stop by 500,000 at the latest, and earlier when a unit of work is done. That limit is a judgment call the evidence can't confirm or refute. What the evidence does support is treating a session as one unit of work.

## What the skill does

Ending a session well is mostly bookkeeping, and bookkeeping is what gets skipped at the end of a long stretch. The skill runs it in a fixed order:

1. A read-only script surveys every repository the session touched and sorts each local branch and worktree into AUTO-PRUNE, ASK or KEEP.
2. Pull requests get a proper description, their checks are read, and drafts with green checks are marked ready.
3. The tracker is brought up to date: a project update is posted (Linear, if connected) and tickets are moved to match reality.
4. Merged branches and their worktrees are deleted; everything else is listed for a decision.
5. Lessons that will matter again are written somewhere durable.
6. A short handover is printed for the next session.

The rule with the most revisions is about when to ask. Early versions asked before every outward action, including posting a status update. Now there are two tiers. Actions that only make the systems reflect reality happen without asking and are reported afterwards: the project update, moving a ticket, marking a PR ready, deleting a branch whose PR is verifiably merged. Anything destructive or irreversible still needs an explicit yes: merging, force-pushing, deleting anything else, writing to repository files. The skill says it bluntly: "The answer to 'should I post this?' is always yes; stop asking."

"Verifiably merged" needed a precise definition. Squash merges don't leave the branch as an ancestor of main, so `git branch --merged` misses them. A branch is deleted automatically only if its PR is merged, the local tip is exactly the merged head, its worktree is clean and isn't the one the session runs in, and no submodule inside it holds commits that exist on no remote. The survey script applies that predicate and has a test for each condition.

## Lessons that will matter again leave the handover

Before the handover is written, the skill collects the non-obvious things the session learned and asks of each one: will this still be true in a month? If not, it belongs in the handover. If so, it goes to the narrowest place where it will be read when it matters: a comment at the exact line, the repository's CLAUDE.md, or the agent's memory for things that cross repositories.

This step matters more for the next session than the note itself. Without it, the same trap gets copied from handover to handover and disappears the first time someone forgets to paste one.

## The handover is a list of pointers

The note is a fenced markdown block of about two thousand characters, pasted as the first prompt of the next session. It starts with two fixed lines (a greeting and a working mode: look at the current state yourself, then ask before deciding), followed by the goal in one sentence, pointers, commands that show the live state, open decisions, next steps, unverified assumptions, and gotchas for this transition only.

Pointers means IDs, titles, URLs, absolute paths and the commands to run. The next session will check the PR, the ticket and the branch anyway, so the note names them and leaves their state out. A word like "green" or "ready" is stale by the time anyone reads it.

Two sections are deliberately narrow. Open decisions holds only what the human alone can settle: a product call with no sensible default, missing access, something irreversible. Anything with a clear default is written as a next step with that default, because a listed decision makes the next session wait for an answer it doesn't need. Unverified assumptions exists because a wrong fact carried forward does more damage than a missing one.

The transcripts show the format in use. Of the sessions started from a pointer-style handover, 33 of 46 ran at least one of the listed state commands among their first tool calls. Notes got shorter when the format switched from status prose to pointers, from a median of 3,500 characters to 2,600\. The skill had asked for 1,000 to 1,500 and the notes never came close, so the target is now 2,500.

## Others arrived at the same ideas

The skill was built from daily use, without a template. The overlap with what others have published is the best argument that it isn't idiosyncratic.

Amp [replaced compaction with a feature called Handoff](https://ampcode.com/news/handoff?ref=ghost.p2lab.com) in October 2025, because compaction is lossy and "encourages long, meandering threads, in which you just compact once you run out of context window." Handoff takes a goal for the next thread and drafts a starting prompt plus a list of relevant files. HumanLayer's [frequent intentional compaction](https://github.com/humanlayer/advanced-context-engineering-for-coding-agents/blob/main/ace-fca.md?ref=ghost.p2lab.com) keeps context usage around half the window and moves work between phases through files on disk. Anthropic's article on [harnesses for long-running agents](https://www.anthropic.com/engineering/effective-harnesses-for-long-running-agents?ref=ghost.p2lab.com) has each session work on one feature, start by reading a progress file and the git log, and leave the code clean and committed. Werner Robitza [describes a handoff skill](https://slhck.info/software/2026/07/10/agent-handoffs-and-human-bottleneck.html?ref=ghost.p2lab.com) based on one by Matt Pocock: goal, completed work, key files, current state, next steps, and a list of undocumented gotchas, which he calls the most important part.

They share one unit of work per session, a fresh context instead of repeated summaries, state on disk or in the tracker, and pointers instead of retelling. end-session adds the bookkeeping around the note and the rule that durable knowledge leaves the handover. None of these approaches has been benchmarked against another; the case for all of them rests on practice.

## What a review against the transcripts changed

The survey used to be a list of git and gh commands for the agent to run and interpret repo by repo. They were the most frequent shell commands in past runs, and the merge predicate is exactly the kind of check a model gets subtly wrong deep into a long context. It is now a Python script with tests against throwaway repositories, and the agent reads its verdict.

Writing the script turned up a bug. The skill detected background sessions, where closing the session deletes its worktree, through an environment variable that Claude Code doesn't set in those sessions. The check had never fired.

The skill text also lost a fifth of its length. Explanations of submodules and worktree removal moved to a reference file that is read only when the survey reports one. The predicate stayed in the main text, since it is the rule that protects unsaved work.

## Install

Inside a Claude Code session:

```
/plugin install end-session --marketplace perelin/end-session
```

It needs git, Python 3 and an authenticated `gh`. Without gh, every branch lands in ASK and nothing is deleted automatically. The project update assumes a tracker connector such as Linear and is skipped without one. The two fixed lines at the top of the handover are the author's own, in German; replace them with yours. The parts about background sessions are specific to Claude Code's agent view.

The skill is MIT-licensed: one skill file, one reference file, a survey script of about 210 lines and its tests.

*This post was written by an AI agent working with the skill's author, who asked for it and reviewed it before it went out.*