Claude Code Tools

ccbaton

official

Claude Code plugin: context statusline, session snapshots via BATON.md, PreCompact safety net, and AI sidecar reviews with Codex/Gemini.

Version
0.3.7
Last Updated
2026-05-06
Source
official

baton mascot — a small pixel-art runner with a green headband carrying a baton

baton

Snapshot-and-resume for Claude Code sessions. Never lose context to auto-compaction again.

baton is a Claude Code session snapshot and handoff tool. It writes the current working state into a structured BATON.md so a fresh Claude Code session can resume with the goal, recent decisions, active files, gotchas, and next concrete action intact instead of relying on degraded compacted context.

Prerequisites

  • Node.js >=20
  • Claude Code

Bun is only required for local development from this repository.

Install

npx ccbaton@latest

Or with Bun:

bunx ccbaton@latest

The installer patches ~/.claude/settings.json with self-locating commands that keep working after npx/bunx exits. Published installs use the bundled Node.js CLI; source-tree installs use bun run src/cli.ts.

If you install globally (npm install -g ccbaton), the postinstall script runs the installer automatically.

What gets installed:

  • a statusline command
  • UserPromptSubmit, PreCompact, and SessionStart hooks
  • /baton, /drop, /baton-codex, and /baton-gemini slash commands

After installing, restart Claude Code so the slash commands and statusline reload.

Daily Flow

Use /baton when you reach a natural stopping point and want a fresh Claude Code session to pick up from the current one. Claude writes .claude/baton/BATON.md with the current session state.

Use /clear to start a clean session that automatically resumes from the baton. The SessionStart hook injects the baton into context, then archives it so the resume is one-shot.

Use /drop before /clear when you want to discard the pending baton and start completely fresh.

Use /baton-codex or /baton-gemini after writing a baton when you want a read-only second opinion in the current Claude Code session. These commands do not start a new session and do not replace /baton + /clear; they run a sidecar model, relay its output back into the active conversation, and leave the user to decide what to do next. Each command asks whether the sidecar should run in review, critique, or alternative mode, then sends the current BATON.md through the same redaction pipeline used by the fallback writer. The Codex sidecar runs with codex exec --sandbox read-only --ephemeral; the Gemini sidecar runs headlessly with --approval-mode plan.

Use baton catch when the original session or terminal is already gone but .claude/baton/BATON.md still exists. If installed from the renamed package binary, use baton catch.

baton catch
baton catch --dry-run
baton sidecar codex --mode review --dry-run
baton sidecar gemini --mode review --dry-run

Statusline

The statusline shows model, branch, context usage, baton state, rate limit, duration, and cost in one compact row:

Sonnet 4.5 │ main* │ [======----] 82k/200k │ BATON: Refactor settings-patch │ 5h 71% │ 12m │ $1.24

When context gets high, baton nudges Claude to snapshot. At the hard threshold, it injects the baton protocol directly so Claude writes the baton before auto-compaction can discard useful state.

When the 5-hour rate-limit is above 90%, baton escalates the hard nudge earlier (at ~45% of the context window instead of 60%), so you snapshot before one more long turn hits the rate wall and prevents Claude from authoring a baton on demand.

Configuration

BATON_FRESH_MS controls how long an existing BATON.md is considered fresh. The default is ten minutes:

BATON_FRESH_MS=1800000 claude

SESSION_AGE_NUDGE_MS controls the session-age nudge threshold. After 5 hours in a session with at least 30k tokens in context, baton suggests a snapshot even if token pressure is low. Configurable if you prefer a different window:

SESSION_AGE_NUDGE_MS=10800000 claude  # nudge after 3 hours instead

Custom baton template

Create ~/.claude/baton-template.md to override the default baton skeleton. The file must start with frontmatter:

---
name: baton
description: Your description
---

To add sections instead of fully replacing, include <!-- baton:extend --> in your file — the bundled template body is spliced in at that point.

Re-run npx ccbaton to apply changes.

Redaction

The PreCompact fallback baton (written when auto-compact was about to fire and no fresh /baton existed) is passed through a redaction step before writing to disk. Default patterns cover common API keys, AWS/GitHub tokens, JWTs, and bearer headers.

Add custom patterns to:

  • ~/.claude/baton-ignore — user-level, applied to every project
  • .batonignore — project-level, applied to the current cwd only

Format: one regex per line, # for comments, optional LABEL:::REGEX to name the pattern. Empty lines ignored.

Redaction only applies to the fallback writer, not to Claude-authored /baton output. Don’t paste secrets into your own batons.

To disable entirely (not recommended): BATON_NO_REDACT=1.

Recovering from a lost baton

If you lost a baton but still have the transcript (Claude Code writes them to ~/.claude/projects/<slug>/<session-id>.jsonl), you can rebuild a best-effort baton:

baton reconstruct ~/.claude/projects/my-project/abc123.jsonl

By default this writes to <cwd>/.claude/baton/BATON.md. Use --out for a custom location. The rebuilt baton uses the same fallback format as the PreCompact auto-write — deterministic, less structured than a Claude-authored baton, but enough to resume.

Commands

Archive

Archived batons are moved to ~/.claude/baton/archive/. You can view, search, and clean up the archive:

baton list                    # list archived batons (newest first)
baton show <id|prefix>        # read a specific archived baton
baton recall <query>          # search across your archive
baton prune --older-than-days 30 --keep 50  # clean up old archives

Example baton list output:

baton archive (3 entries)

  2026-04-21 19:32   baton           Implement rate-limit nudge
  2026-04-21 14:05   baton           Refactor settings-patch
  2026-04-19 08:12   other-proj      _(dropped)_

General

npx ccbaton@latest          # install or upgrade
npx ccbaton check           # verify current install state (exits 1 if anything missing)
npx ccbaton uninstall       # remove hooks, statusline, commands; restore settings.json from backup

After installing globally, the baton binary is available directly:

baton --version
baton install [--force]     # --force replaces a non-baton statusLine
baton uninstall
baton check
baton catch [--dry-run]
baton drop

Development

Bun is used to run tests and build the npm package:

bun install
bun test
bun run build
bun run src/cli.ts install

The package binary is baton; bun run build writes the portable Node.js CLI to dist/cli.js with a Node shebang for npm/npx execution.

Migrating From Handoff To Baton

  • In-flight .claude/baton/HANDOFF.md files can be renamed to BATON.md manually and will be picked up by the SessionStart hook as usual.
  • The installer automatically removes old ~/.claude/commands/handoff*.md and ~/.claude/skills/handoff/ on next install.