npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@codeprakhar25/agent-baton

v0.3.2

Published

Cross-agent handoff tool: transfer work between Cursor, Claude Code, and Codex when limits are hit

Downloads

425

Readme

agent-baton

Don't lose your work when an AI coding agent hits its usage limit.

baton monitors usage for Claude Code and Codex, warns you before the threshold, and registers a rich Markdown handoff written by the active agent, with Baton metadata and git evidence appended so the next agent picks up exactly where you left off.

npm license node


Baton interactive quota prompt inside Claude Code

When Claude crosses the threshold, Baton injects an interactive AskUserQuestion prompt — you choose between continuing on remaining quota or writing a handoff so you can pick up in another agent.


The problem

You are deep in a task — three files modified, a bug half-fixed. Claude or Codex hits its hourly usage limit. You either:

  • Lose track of what was in progress and start explaining from scratch in another agent.
  • Manually copy-paste diffs and notes into a new session.

Baton fixes that. It intercepts at the threshold, gives you a choice, and writes a structured handoff that the next agent can read cold.


Install

npm install -g @codeprakhar25/agent-baton

Requirements: Node.js 18+


Quick Start

# 1. Initialize once per project
cd ~/your-project
baton init

# 2. Work normally — baton hooks into Claude automatically
#    For Codex, use the baton wrapper instead of running codex directly
baton codex "continue the auth refactor"

# 3. When baton warns you, choose: continue or hand off
#    If you choose handoff, pick up in the next agent
baton pickup --to codex

That's it. Every handoff is written to ~/.local/state/agent-baton/projects/<slug>/handoffs/ and never touches your repo.


How It Works

Baton has two integration paths:

Claude Codebaton init installs global hooks into ~/.claude/settings.json so every Claude session in every project is covered. On SessionStart, UserPromptSubmit, and PreToolUse, baton guard reads cached usage with a three-tier TTL (15 min below 50%, 5 min from 50% to the warning band, no cache TTL in the warning band). SessionStart and UserPromptSubmit always refresh Claude usage before the next model response. When you cross the warning band or the hard threshold, Claude is instructed to fire an interactive AskUserQuestion prompt to continue or write a handoff. Soft warnings respect a re-notify cooldown, but the hard threshold is rechecked on every user prompt. PreToolUse keeps a separate fetch throttle so tool-heavy turns do not spam the usage API.

Codexbaton codex wraps the codex binary. Usage is checked before Codex launches. If you're over the threshold, Baton asks whether to continue, launch Codex to write a handoff, or run baton pickup. Continuing injects a first prompt that tells Codex to ask before doing more work.

baton guard / baton codex
          │
          ▼
    fetch usage (cached)
          │
     over threshold?
     ┌────┴────┐
    no         yes
     │          │
  allow     ask user
  work       │      │
          continue  handoff
                     │
              agent writes Markdown
              + Baton appends evidence
                     │
              write HANDOFF-latest.md
                     │
              baton pickup --to <agent>

Handoff format

Each handoff is a Markdown file with:

  • Agent-authored task summary, progress, decisions, remaining work, and next step
  • Baton metadata and source handoff path
  • Git branch, status, diff stat, and last commits
  • Full uncommitted diff appended as evidence (truncated at handoff_extraction.max_diff_chars)
  • Instructions for the next agent

Git state is the durable source of truth — if transcript extraction is incomplete, the diff tells the full story.

~/.local/state/agent-baton/projects/<project-slug>-<hash>/
  handoffs/
    HANDOFF-latest.md      ← always points to the most recent
    HANDOFF-<timestamp>.md ← timestamped copy
  usage-cache.json
  pending-transfer.json

Supported Agents

| Agent | Integration | Detection method | |-------|-------------|-----------------| | Claude Code | SessionStart, UserPromptSubmit, PreToolUse hooks | OAuth token → Claude usage API | | Codex | baton codex wrapper | ~/.codex/sessions/**/rollout-*.jsonl token_count.rate_limits events | | Cursor | Watch / transcript fallback | Hard-limit error text in transcripts | | Gemini CLI | Watch / transcript fallback | Hard-limit error text in transcripts |

Claude and Codex have proactive detection — Baton knows you're near the limit before it's actually hit. Cursor and Gemini rely on the hard-limit text appearing in transcripts.


Commands

| Command | Description | |---------|-------------| | baton init | Install global config/state and Claude hooks for the current project | | baton usage --from <agent> | Print current usage-limit status | | baton guard --from claude --hook | Claude hook driver (called automatically) | | baton codex [-- <args>] [prompt] | Launch Codex with usage preflight | | baton handoff --from <agent> | Manually write a handoff from the current transcript and git state | | baton handoff --from <agent> --file <path> | Register a complete Markdown handoff written by the handing-off agent | | baton pickup [--to <agent>] | Launch an agent with a prompt pointing to the latest handoff |

# Check usage
baton usage --from claude
baton usage --from claude --json       # machine-readable
baton usage --from claude --refresh    # skip cache

# Codex wrapper
baton codex                            # bare launch with preflight
baton codex "finish the login flow"    # with initial prompt
baton codex -- --model o4-mini        # pass codex flags

# Handoff
baton handoff --from codex
baton handoff --from claude --reason rate-limit
baton handoff --from claude --reason rate-limit --file /tmp/baton-handoff.md
baton handoff --from claude --launch   # write + immediately run pickup

# Pickup
baton pickup                           # choose agent interactively
baton pickup --to claude
baton pickup --to codex

Configuration

Global config lives at:

~/.config/agent-baton/config.json

Per-project overrides (never committed):

.baton/config.json

baton init adds .baton/ to .gitignore automatically.

{
  "agents": {
    "cursor":  { "enabled": true, "priority": 1 },
    "claude":  { "enabled": true, "priority": 2 },
    "codex":   { "enabled": true, "priority": 3 },
    "gemini":  { "enabled": true, "priority": 4 }
  },
  "limits": {
    "mode": "ask",
    "handoff_percent": 95,
    "warning_buffer_percent": 5,
    "auto_handoff_on_hard_limit": true,
    "windows": {
      "claude": {
        "five_hour": { "enabled": true, "handoff_percent": 95 },
        "weekly": { "enabled": true, "handoff_percent": 98 },
        "extra": { "enabled": true, "handoff_percent": 95 }
      },
      "codex": {
        "five_hour": { "enabled": true, "handoff_percent": 95 },
        "weekly": { "enabled": true, "handoff_percent": 95 },
        "unknown": { "enabled": true, "handoff_percent": 95 }
      }
    }
  },
  "usage_cache": {
    "safe_ttl_ms": 900000,
    "approach_percent": 50,
    "approach_ttl_ms": 300000,
    "near_limit_ttl_ms": 0,
    "near_limit_percent": 75,
    "pretool_ttl_ms": 60000,
    "notify_cooldown_ms": 900000
  },
  "usage_sources": {
    "claude": {
      "oauth_credentials_path": "~/.claude/.credentials.json"
    }
  },
  "handoff_dir": "handoffs",
  "handoff_extraction": {
    "max_transcript_lines": 100,
    "include_git_diff": true,
    "max_diff_chars": 8000,
    "scan_secrets": true
  }
}

Key options:

| Key | Default | Description | |-----|---------|-------------| | limits.mode | "ask" | ask — prompt before acting; auto_handoff — write immediately; warn_only — log only | | limits.handoff_percent | 95 | Hard threshold; Baton blocks and asks at this level | | limits.warning_buffer_percent | 5 | Warning band starts this many points below handoff_percent (default warns at 90%) | | limits.windows.<agent>.<window> | see config | Per-agent, per-window threshold policy | | limits.auto_handoff_on_hard_limit | true | Auto-write a handoff when hard-limit text appears | | usage_cache.safe_ttl_ms | 900000 | Cache TTL below approach_percent (15 min) | | usage_cache.approach_percent | 50 | Usage percentage where the 5-minute approach TTL starts | | usage_cache.approach_ttl_ms | 300000 | Cache TTL from approach_percent up to the warning band (5 min) | | usage_cache.near_limit_ttl_ms | 0 | Cache TTL inside the warning band; 0 means recheck at hook boundaries | | usage_cache.pretool_ttl_ms | 60000 | Minimum interval between fresh API fetches triggered by PreToolUse | | usage_cache.notify_cooldown_ms | 900000 | Cooldown before re-notifying after the user chose continue | | handoff_extraction.max_diff_chars | 8000 | Per-file diff truncation cap |

Environment overrides: AGENT_BATON_CONFIG_HOME, AGENT_BATON_STATE_HOME, XDG_CONFIG_HOME, XDG_STATE_HOME.


Troubleshooting

No Codex usage found Start or continue a Codex session so it emits token_count.rate_limits events into its rollout JSONL. Baton reads from ~/.codex/sessions/**/rollout-*.jsonl.

Claude usage unavailable Ensure Claude Code is OAuth-authenticated and ~/.claude/.credentials.json exists. Run baton usage --from claude --refresh to force a fetch.

Pickup says agent missing The target CLI is not on PATH. Install it or check your shell config.

Hooks not firing Re-run baton init in the project directory. Check that ~/.claude/settings.json (global) contains the Baton guard hooks under hooks. Codex hooks live in ~/.codex/hooks.json.


Current Limits

  • Context-window fullness is not monitored. Baton only handles usage-limit signals.
  • Cursor and Gemini CLI have partial support — proactive detection requires hard-limit text to appear in transcripts.
  • There is no automatic agent exit. Baton warns and writes the handoff; you exit the current agent and run baton pickup manually.

License

MIT