ctx-handoff Claude Code mod: make Claude Code long sessions easier
Keeps the prompt cache warm, writes project notes from what you teach Claude, and can hand off a full context.
Permissions
- Reads filesCan read files and list directories on your machine ($.fs.read / list / stat / exists).
- Writes filesCan create or overwrite files on your machine ($.fs.write).
- Calls the model (uses your quota)Can send its own requests to Claude, which count against your plan's usage ($.model.* / $.agent.spawn).
- Intercepts tool callsSees every tool call Claude makes (tool.call / tool.check) and could block or change it.
- Reads your promptsCan see what you type and the conversation transcript (prompt.* / session.append / session.messages).
- Changes the UIDraws into the Claude Code interface: bands, panes, status text, toasts (ui.render / $.ui.*).
- Adds commands/toolsRegisters new slash commands or tools that you or Claude can invoke ($.command.register / $.tool.register).
- Stores dataKeeps data between sessions in the plugin's private store ($.store.*).
- tested with
- v2.1.303
- last tested
- requires
- Claude Code ≥ 2.1.287
- surfaces
- above-prompt, status, toast
- source
- CabLate (cablate) (MIT)
Install inside Claude Code:
/plugin install ctx-handoff --marketplace cablate/ctx-handoff-modWhat does this mod do?
ctx-handoff is a community mod by CabLate (cablate) for Claude Code long sessions. It bundles several chores that come up when a conversation runs for hours: it sends a tiny request while you are away so the prompt cache does not expire, it turns your repeated instructions into per-project notes that are loaded into new conversations, and it nudges Claude when it retries a failing tool or says "done" without running a check.
Two bigger features are less automatic. An optional handoff writes a summary of the work, clears the conversation and continues in a fresh one when the context reaches a threshold; it is off by default. Guards are tool-call checks the mod drafts from rules you keep repeating, and they only apply after you approve them. A panel above the prompt (/handoff panel) lists guards, memories, rules, the latest notes update and every setting.
The author's README targets Claude subscriptions and long, large-context sessions. On an API key, Bedrock or Vertex the cache lasts five minutes, so the author suggests /handoff refresh off.
Demo
The recording starts Claude Code with the mod loaded in the small demo project. The footer immediately shows ctx-handoff: 30 more messages until notes update, the countdown to the next background notes update. The clip then runs /handoff guard, which prints Guards: none with the conditions under which guards get drafted, and /handoff refresh, which prints Currently on. Usage: /handoff refresh on|off. No model request is made in the clip, and it does not open the panel because the panel shows the full path of the notes file.
Install
Use any of the methods in the install block; they install straight from the author's own marketplace. Start a new session and run /handoff. The footer countdown appears once the session starts.
$ install ctx-handoff
Requires Claude Code ≥ 2.1.287
Installs from the author's own marketplace: cablate/ctx-handoff-mod
1.One line, inside Claude Code
/plugin install ctx-handoff --marketplace cablate/ctx-handoff-modPaste into a running session (v2.1.275+). Claude Code asks to add the marketplace first.
2.From your shell
claude plugin marketplace add cablate/ctx-handoff-mod claude plugin install ctx-handoff@ctx-handoff-modThen run /reload-plugins in any session that is already open.
3.Try it without installing
git clone https://github.com/cablate/ctx-handoff-mod claude --plugin-dir ./ctx-handoff-modLoads the mod for one session only. Nothing is added to your settings.
How it works
Everything is registered from one module, hooks/register.ts. Each finished turn restarts an idle timer. When it fires, and the context is above min_tokens, the mod sends a minimal fork request to read the cached conversation and then schedules the next one. This is the scheduling function, from hooks/register.ts:
async function schedule($: EngineInterface, delay = cfg.idleMs) {
rt.idle?.cancel()
if (await awayPaused($)) { rt.idle = undefined; await update($, idleState, () => null); return }
rt.idle = $.clock.after(delay, () => void onIdle($))
const due = (await $.clock.now()) + delay
await update($, idleState, () => ({ due, refreshes: rt.refreshes }))
}By default the idle time is 50 minutes and at most 3 refreshes run, after which an away handoff is saved without clearing. Every 30 user messages, or before a handoff, a separate request without history sends only the new part of the conversation to a notes model (claude-sonnet-5-5, low effort). Its JSON actions are validated in code, user quotes must be found in your actual messages, and lines that look like secrets are dropped before anything is written. The notes are injected into new conversations through prompt.context.
Customize it
The mod declares no userConfig. Settings live on the panel's Settings tab (/handoff panel, then key 5), and the mod also reads pluginConfigs["ctx-handoff@<marketplace>"].options from settings.json; the panel value wins. The settings include auto_handoff (default off), threshold (600000 tokens), idle_minutes (50), max_refresh (3), min_tokens (30000), distill_every (30), notes_model, retry_nudge, done_check, reply_language and language. Slash commands cover the rest: /handoff now, dry, distill on|off, refresh on|off, away pause|resume, guard, resume, continue and resend.
Permissions & safety
We read the manifest, hooks/hooks.json, hooks/register.ts in full, and the modules for settings, notes, handoff, guards, loops, language, promotion and the distill prompt. The remaining files, mostly the i18n strings, the panel view and small record helpers, were checked for side effects with searches rather than read line by line. The repo has no package.json, install script, binary or minified code. tools/ holds author-side scripts that the plugin does not load, and we did not run them. There are no hidden Unicode characters.
Findings you should know about:
- Model requests, no other network. There is no
fetch, process call or network code. The mod calls$.model.forkand$.model.complete, which use your Claude quota. Conversation text is sent for notes and handoff summaries, the same way the conversation itself is. - Writes outside its own store.
$.fs.writecreates and updates<claude config dir>/projects/<workspace>/memory/ctx-handoff.md, and writes a backup in.ctx-handoff-backup/before deleting a note from the panel. Background notes updates are on by default, but they are skipped when the session starts in your home folder. It does not touch settings.json, shell files or LaunchAgents, and it readsHOME,USERPROFILEandCLAUDE_CONFIG_DIR. - It injects text into the model.
prompt.contextadds your notes, an optional progress memo and guard questions to new conversations, tagged[ctx-handoff]. Tool results can carry nudges. Once a rule has been repeated 3 times in a git repo, the injected text tells Claude to write it into the repo (CLAUDE.md,.claude/skills, hooks) without asking first, but not to commit. The notes are model-written summaries of your conversations, so check the file now and then. - Gating hooks.
tool.callcan deny a call only for a guard you approved.classic.Stopcan block one "done" answer per turn when files were edited and no check ran (done_check, on by default).prompt.submitholds your messages while a handoff is running. If you turn auto handoff on, the mod runs/clearand submits the summary itself. - No daemon, no telemetry. Timers live only in the Claude Code process. Usage statistics stay in the plugin's store.
- Managed setups.
claude plugin validatenotes thatprompt.contextandclassic.Stophooks do not run in a user-installed plugin where an organization manages Claude Code. - License. MIT, with a LICENSE file.
claude plugin validate reported no errors. Its only warning is that the CLAUDE.md at the repo root is not loaded as plugin context. The author's 290 tests across 15 files passed on Claude Code 2.1.303.
- Reads files
- Can read files and list directories on your machine ($.fs.read / list / stat / exists).
- Writes files
- Can create or overwrite files on your machine ($.fs.write).
- Calls the model (uses your quota)
- Can send its own requests to Claude, which count against your plan's usage ($.model.* / $.agent.spawn).
- Intercepts tool calls
- Sees every tool call Claude makes (tool.call / tool.check) and could block or change it.
- Reads your prompts
- Can see what you type and the conversation transcript (prompt.* / session.append / session.messages).
- Changes the UI
- Draws into the Claude Code interface: bands, panes, status text, toasts (ui.render / $.ui.*).
- Adds commands/tools
- Registers new slash commands or tools that you or Claude can invoke ($.command.register / $.tool.register).
- Stores data
- Keeps data between sessions in the plugin's private store ($.store.*).
Compatibility & troubleshooting
Checked with Claude Code 2.1.303 on macOS (validate, tests and the recording). The author's README requires 2.1.287 or later. If /handoff does nothing:
claude --versionis 2.1.287 or later, and you started a new session after installing.- Another
/handoffcommand may exist; the mod then registers/ctx-handoffinstead. - The footer countdown is absent when notes updates are off or when you started Claude Code in your home folder.
- Cache refreshes help only where the cache lasts an hour, so turn them off with
/handoff refresh offon API keys. - Run
/handofffor the current state, including the latest failure and the path of the notes file.
FAQ
- Does ctx-handoff use my Claude quota?
- Yes. It has no servers of its own, but it makes model requests through your Claude Code sign-in. A cache refresh is a tiny request, and a notes update sends only the new part of the conversation to Sonnet 5.5 at low effort. A full handoff is one request.
- Where does it write files?
- Project notes go to ctx-handoff.md in the memory folder under ~/.claude/projects/ (or CLAUDE_CONFIG_DIR) for the workspace. Everything else lives in the plugin's own store. Deleting a note from the panel backs up the old file first.
- Will it clear my conversation by itself?
- Only if you turn on auto_handoff, which is off by default. With it off, Claude Code's own compact handles a full context. Away handoffs are saved without clearing, and you choose whether to resume from them.
- Can it block Claude's tool calls?
- Only through guards. The mod drafts them from rules you keep repeating, and nothing applies until you approve a guard. Separately, a default-on check can hold back a "done" answer once if files were edited and nothing was tested.
- How do I turn the background parts off?
- Run /handoff distill off for notes, /handoff refresh off for cache refreshes, or open /handoff panel and use the Settings tab for the nudges and the reply-language reminder.
# Related mods
FeaturedProject Sentinel
A status band, context handoff, prompt cache tracking and permission rules for long Claude Code runs.
- above-prompt
- pane
- spinner
- status
- toast
- Reads files
- Runs commands
- Calls the model (uses your quota)
- Intercepts tool calls
- Reads your prompts
- Changes the UI
- Adds commands/tools
- Stores data
tested with v2.1.296
FeaturedCache Clock
A prompt-cache line under your Claude Code status line: time left while warm, hit rate, and tokens re-cached once cold.
- status
- Reads files
- Writes files
- Runs commands
- Adds commands/tools
tested with v2.1.296
FeaturedWhere Am I
A recap above the Claude Code prompt: the session goal, what is happening now, what waits on you and the next step.
- above-prompt
- Reads files
- Calls the model (uses your quota)
- Intercepts tool calls
- Reads your prompts
- Changes the UI
- Adds commands/tools
tested with v2.1.303
More in Timers, todos, standups, Context, quota, cost.