Pass the baton between AI coding agents - hit a limit in Claude Code, resume exactly where you left off in Codex, Gemini, or Cursor.
Project description
tapout
Your coding agent tapped out? Tag in the next one.
Hit your Claude Code limit mid-task — tap codex and it picks up exactly where you left off. Same task, same plan, same progress. No re-explaining.
Install
pip install tapout
Installs two equivalent console commands, tap and tapout. Python 3.10+.
How it works
tap out— prints a summarization prompt (also copied to your clipboard). Paste it into your current agent; it replies with a task-state JSON block.tap out --from <file>— ingests that reply and writes two artifacts:HANDOFF.md(human/agent readable) and.tapout/task-state.json(schema, git-friendly).tap <agent>— opens the target agent in the repo, seeded with the handoff. Works forclaude,codex,gemini,cursor, and any agent you add yourself.
Run tap scan to see which agents are installed on this machine.
Zero-effort capture (Claude Code plugin)
Heads up: auto-capture hooks are not yet wiring up on the current Claude Code plugin runtime — see issue #1. The statusline works today; until #1 lands, use the one-command capture below.
Install the bundled Claude Code plugin so capture happens automatically — no manual tap out:
git clone https://github.com/MIthunvasanth/tapout.git
cd tapout
claude plugin marketplace add ./
claude plugin install tapout-claude@tapout
- PreCompact + SessionEnd hooks refresh
HANDOFF.md+.tapout/task-state.jsonbefore Claude compacts context or the session ends. /tapout:pausecaptures on demand mid-session.tap watchshows a live usage line and printsrun: tap codexwhen your 5-hour window is spent. Add the statusline to~/.claude/settings.json:{ "statusLine": { "type": "command", "command": "tap statusline", "refreshInterval": 5 } }
tap statuslineprintstap: N%and records state thattap watchreads.
tap capture --agent claude is the machine-invoked capture (used by the hooks): it summarizes the session transcript into the artifacts and writes them atomically.
Auto-capture from a Claude Code session (works today)
After a Claude Code session, find the transcript and capture:
# Find the latest session file for your project
dir $env:USERPROFILE\.claude\projects -Recurse -Filter *.jsonl `
| Sort-Object LastWriteTime -Descending | Select-Object -First 1
python -m tapout capture --agent claude --session-transcript "<path from above>"
tap codex # or tap cursor, tap gemini
Note: the packaged Claude Code plugin includes a SessionEnd hook and
/tapout:pauseslash command intended to run capture automatically. On some Claude Code versions the plugin runtime does not wire these up (tracked in issue #1, Slice 2.5). Until that's fixed, use the command above — it's the exact same capture logic the hook would invoke.
Zero-install via uvx
Once published, the hooks (and you) can run tapout without installing it: uvx tapout <command>. The plugin's hook launcher prefers your installed package and falls back to uvx tapout.
Adding your own agent
Agents are data, not code. Drop a ~/.tapout/agents.toml to add or override any agent — no package changes:
[mytool]
display_name = "My Tool"
binaries = ["mytool"]
config_dirs = ["~/.mytool"]
resume_style = "cli_prompt" # or clipboard_gui / clipboard_only
launch_template = ["{binary}", "{prompt}"] # {binary} {prompt} {cwd} substituted
version_probe = { args = ["--version"], timeout_sec = 5 }
Then tap resume mytool (or tap scan to confirm it's detected). User keys win over the bundled registry.
Each entry can also set prompt_delivery: "argv" (default), "stdin" (pipe the prompt to the child — bypasses cmd.exe, the safe default for codex/gemini/claude), "file:<flag>" (write the prompt to a file, pass the path via <flag>), or "clipboard".
Note: Gemini CLI's free tier was deprecated in December 2025 — the registry flags this, and
tap scansurfaces the note.
First run in a new folder
The first tap <agent> in a repo may hit the receiving agent's own setup: trust/workspace-approval dialogs, IDE-connect prompts, or a sign-in. That's the target agent, not tapout. Get through those once — subsequent handoffs into that folder go straight to work.
Windows notes
- npm-installed agents ship both an extensionless shim and a real
.cmd; tapout resolves the.cmd(PATHEXT-aware) so launches don't fail with WinError 193. - When an argv-delivery launcher is a
.cmd/.batand the handoff contains shell metacharacters (& | % " ^ < >), tapout will not pass the prompt as a command-line argument (cmd.exe would re-parse it — the "BatBadBut" class of bug). It falls back to clipboard. Agents usingstdinorfiledelivery (codex, gemini, claude) avoid this entirely. - PowerShell's
typemay mangle UTF-8; runchcp 65001first, or openHANDOFF.mdin an editor.
Early alpha (0.1.0.dev0). Manual + auto (Claude Code plugin) handoff; usage monitor via tap watch.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tapout-0.1.0.tar.gz.
File metadata
- Download URL: tapout-0.1.0.tar.gz
- Upload date:
- Size: 30.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
953fdb665744532b66485d1423b749996a32d9c0382cabd568e320a4057ead3c
|
|
| MD5 |
2d95886d9e4a69b5f517afac0e77e5ca
|
|
| BLAKE2b-256 |
b8e36112c3e2ef7fbea2fd095b1da0f28ce8f336aa0fd2feb8c23993ba6225bd
|
Provenance
The following attestation bundles were made for tapout-0.1.0.tar.gz:
Publisher:
release.yml on MIthunvasanth/tapout
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tapout-0.1.0.tar.gz -
Subject digest:
953fdb665744532b66485d1423b749996a32d9c0382cabd568e320a4057ead3c - Sigstore transparency entry: 2081950607
- Sigstore integration time:
-
Permalink:
MIthunvasanth/tapout@669a5ca15026f48789f191015663329ee24a2090 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/MIthunvasanth
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@669a5ca15026f48789f191015663329ee24a2090 -
Trigger Event:
release
-
Statement type:
File details
Details for the file tapout-0.1.0-py3-none-any.whl.
File metadata
- Download URL: tapout-0.1.0-py3-none-any.whl
- Upload date:
- Size: 24.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9ffb40f0d03c23f98200f4456cf73345645d91d623b60940d769e274cc47a45d
|
|
| MD5 |
8b81c92924bfdf9a4321b0b12b5639de
|
|
| BLAKE2b-256 |
fb174a4624ee4a1e856e90a0aeff730c10fd76701b17fdf865f509095c6ddb61
|
Provenance
The following attestation bundles were made for tapout-0.1.0-py3-none-any.whl:
Publisher:
release.yml on MIthunvasanth/tapout
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
tapout-0.1.0-py3-none-any.whl -
Subject digest:
9ffb40f0d03c23f98200f4456cf73345645d91d623b60940d769e274cc47a45d - Sigstore transparency entry: 2081950661
- Sigstore integration time:
-
Permalink:
MIthunvasanth/tapout@669a5ca15026f48789f191015663329ee24a2090 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/MIthunvasanth
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@669a5ca15026f48789f191015663329ee24a2090 -
Trigger Event:
release
-
Statement type: