🪨 why use many token when few token do trick — Claude Code skill that cuts 65% of tokens by talking like caveman
Auto-retry wrapper for Claude Code in tmux
This tool sits around Claude Code and watches for limit banners, overload errors, safeguard flags, and interrupted streams. When it sees one, it waits, retries, or resumes by sending the next message automatically. It uses tmux so the monitor can keep running even if your terminal disconnects.
Builders who run Claude Code on long sessions and want retries to happen without manual babysitting.
You can leave Claude Code running through limits and transient errors without coming back to retype continue.
What it does
Usage limit retry
Detects printed reset times, waits until the limit clears, and sends `continue` automatically.
Tmux-aware session handling
Creates or reuses a tmux session so monitoring keeps working across disconnects.
Overload backoff
Retries terminal `429/5xx/529` overload errors with exponential backoff and jitter.
Safeguard retry
Re-sends a short retry message when Claude Code falsely flags a message with safeguards.
Interrupted stream resume
Resumes after sleep, disconnect, or stalled-response errors that leave the prompt idle.
Hook-based overload detection
Can install a `StopFailure` hook so overload retries use event markers instead of terminal scraping.
Reconcile support
Can re-arm monitors for live Claude sessions that lost their watcher.
How to get it
- 1Run
⏺ Approaching your 5-hour usage limit — Claude will wrap up the current step.
- 2Run
git clone https://github.com/cheapestinference/claude-auto-retry.git cd claude-auto-retry npm test # Run all 128 tests npm link # Install locally for testing
README
claude-auto-retry
Automatically retry Claude Code sessions when you hit Anthropic subscription rate limits.
When Claude Code shows "5-hour limit reached - resets 3pm", this tool waits for the reset and sends "continue" automatically. You come back to find your work done.
No dependencies. No workflow change. Just install and forget.
📢 Status (Aug 2026): The Claude Desktop app now does this natively — an "☑ Auto-continue when limits reset" checkbox (confirmed in the wild). The CLI still doesn't have it — that's the gap this tool covers today. Track anthropics/claude-code#35744 for the native CLI version; until it lands,
npm i -g claude-auto-retryis the way.
💡 Why wait out the limit at all? This tool auto-resumes Claude Code the moment you're rate-limited — but if you run overnight jobs or always-on agents, there's a way to stop hitting the wall in the first place. See how it's done →
The Problem
You're in the middle of a complex task with Claude Code. After a while, you see:
You've hit your limit · resets 3pm (Europe/Dublin)
Claude stops. You have to wait hours, come back, and type "continue". If you're running long tasks overnight or while AFK, this kills your productivity.
The Solution
npm i -g claude-auto-retry
claude-auto-retry install
That's it. Type claude as you always do. When the rate limit hits, the tool:
- Detects the rate limit message in the terminal
- Parses the reset time (timezone-aware)
- Waits until the limit resets + 60s margin
- Verifies Claude is still the foreground process
- Sends "continue" automatically
You come back to find your task completed.
How it Works
You type "claude"
│
▼
Shell function (injected in .bashrc/.zshrc)
│
├─ Already in tmux? ──▶ Start background monitor
│ Launch claude with full TUI
│
└─ Not in tmux? ──▶ Create tmux session transparently
Launch claude + monitor inside
Attach (looks the same to you)
MONITOR (background, ~0% CPU):
│
├─ Polls tmux pane every 5 seconds
├─ Detects rate limit text
├─ Parses reset time from message
├─ Waits until reset + safety margin
├─ Verifies Claude is still the foreground process
└─ Sends "continue" via tmux send-keys
Why tmux?
When you disconnect (SSH drops, close terminal, laptop sleeps), tmux keeps running. The monitor keeps waiting. When you reconnect with tmux attach, you find Claude working on your task. This is the key advantage over wrapper scripts.
Features
- Zero workflow change — same
claudecommand, same TUI, same everything - Works with and without tmux — auto-creates tmux session if you're not already in one
- Auto-installs tmux if missing (apt, dnf, brew, pacman, apk)
- Timezone-aware — parses reset times with full IANA timezone support (including half-hour offsets)
- DST-safe — iterative offset correction handles daylight saving transitions
- Safe send-keys — verifies Claude is still the foreground process before injecting text
- Self-healing coverage —
reconcilere-arms monitors for any liveclaudesession that lost one; an optional timer (systemd --useron Linux, launchd on macOS) runs it automatically (details) - Overload backoff — detects sustained API overload (
429/500/502/503/504/529) and retries on a configurable exponential backoff with jitter and a cumulative-wait cap, distinct from the usage-reset path (details) - Safeguard retry — auto-continues past an AUP-safeguard false-positive (often transient), capped at a few tries so a sticky flag can't loop (details)
- Interrupted-stream resume — picks the work back up when a laptop suspend or a dropped connection truncates a response mid-turn and leaves the session parked at an idle prompt (details)
- Near-limit wrap-up nudge — when Claude Code winds the turn down at ~95% of the 5-hour window ("Approaching your 5-hour usage limit — Claude will wrap up the current step") and parks the session at an idle prompt with no limit banner, sends one
continueso the work runs on to the real limit, where the usage wait takes over (details) - tmux status bar indicator — see at a glance whether a pane is being monitored, waiting on a reset, backing off from overload, or has given up (details)
--printmode support — buffers output, retries cleanly for piped/scripted usage- Configurable — retry count, wait margin, custom patterns, retry message
- Config validation — bad config values fall back to safe defaults instead of crashing
- Zero dependencies — pure Node.js, no
node_modules
Messages Detected (verbatim)
The tool acts on these real-world Claude Code renders — if you landed here after pasting one of these errors into a search engine or an AI assistant: yes, this tool automates the wait-and-retry for all of them.
Usage / session limits — waits until the printed reset, then continues
| Render | Example |
|---|---|
| N-hour limit | 5-hour limit reached - resets 3pm (UTC) |
| Session limit | You've hit your session limit · resets 2am (Europe/Zurich) |
| Weekly limit | You've hit your weekly limit · resets Oct 9, 10am |
| Usage limit | Claude usage limit reached. Resets at 2pm |
| Out of extra usage | You're out of extra usage · resets 3pm |
| Try again | Please try again in 5 hours |
| Hit your limit | You've hit your limit · resets 3pm (Europe/Dublin) |
| Rate limit | Rate limit hit. Resets at 4pm |
| Live-limit companion hint | /usage-credits to finish what you're working on. |
The /rate-limit-options menu — driven to "Stop and wait", never "Upgrade"
What do you want to do?
❯ 1. Upgrade your plan
2. Stop and wait for limit to reset (3pm)
Handled across any menu layout (the option order varies by Claude Code version); the tool locates the cursor and the "Stop and wait" option, and refuses to press Enter if the layout is unreadable.
API overload / transient errors — exponential backoff with jitter
| Render | Example |
|---|---|
| Terminal API error (colon form) | API Error: 529 {"type":"error","error":{"type":"overloaded_error","message":"Overloaded"}} |
| 5xx family | API Error: 500 / 502 / 503 / 504 … (including bodyless renders like 503 no healthy upstream) |
| API-level 429 | API Error: Server is temporarily limiting requests (not your usage limit) · Rate limited |
Safeguard false positives — bounded immediate re-send
API Error: <model>'s safeguards flagged this message (https://www.anthropic.com/legal/aup).
They may flag safe, normal content as well. … Claude Code can't respond to this request with <model>.
Interrupted streams — one resume, then stop
API Error: Your computer went to sleep mid-response. The response above may be incomplete.
API Error: Connection lost mid-response. The response above may be incomplete.
API Error: The response stopped arriving. The response above may be incomplete.
API Error: Server error mid-response. The response above may be incomplete.
…and the three "before a response was produced. Try again." variants (suspend, stall, connection). All seven come from the same stream finalizer and leave the same wreckage: a truncated turn at an idle prompt.
Near-limit wrap-up — one nudge, then the usage wait
⏺ Approaching your 5-hour usage limit — Claude will wrap up the current step.
Not an error: Claude Code prints this at ~95% of the window and tells the model to
checkpoint. The model finishes the step, lists what's left and ends the turn — no banner,
idle prompt, nothing resumes it. One continue picks the work back up.
Custom patterns can be added via config for future message format changes.
Detection is chrome-aware: it looks at the live bottom of the pane, but first skips
past Claude Code's UI furniture — the input box, footer, key hints, the todo/task widget,
the status spinner, and the /usage-credits hint. So a genuine limit banner still
registers even when a tall task list or background-agent status pushes it well above the
prompt, while a banner merely quoted in scrollback (with real output below it) does not
trigger a retry.
Your own customPatterns are the exception: they are matched against the raw last-N
lines (not the chrome-skipped view), so a pattern keyed on footer text — a usage
percentage, a model name — keeps firing. You own the false-positive tradeoff for your
regexes; the built-in detection keeps the chrome-aware discipline.
Configuration
Optional. Create ~/.claude-auto-retry.json:
{
"maxRetries": 5,
"pollIntervalSeconds": 5,
"marginSeconds": 60,
"fallbackWaitHours": 5,
"retryMessage": "Continue where you left off. The previous attempt was rate limited.",
"customPatterns": ["my custom pattern"]
}
| Option | Default | Description |
|---|---|---|
maxRetries | 5 | Max retry attempts per rate-limit event |
pollIntervalSeconds | 5 | How often to check the terminal (seconds) |
marginSeconds | 60 | Extra wait after reset time (seconds) |
fallbackWaitHours | 5 | Wait time if reset time can't be parsed |
retryMessage | "Continue where..." | Message sent to Claude on retry |
customPatterns | [] | Additional regex patterns to detect rate limits |
All fields optional. Invalid values fall back to defaults automatically.
Launch wrapper
Set CLAUDE_AUTO_RETRY_LAUNCH_WRAPPER to a prefix command and it's prepended to each
interactive session — useful for keeping a machine awake while Claude works, or any other
per-process wrapper:
# macOS: don't sleep while a session runs
export CLAUDE_AUTO_RETRY_LAUNCH_WRAPPER="caffeinate -i"
Generic (not macOS-specific — e.g. nice, chrt … work too). Unset or blank spawns
claude directly, unchanged.
Session lifetime
When claude exits cleanly inside the auto-created tmux session, the session now
ends with it — tmux reaps it, nothing lingers. When the launcher exits non-zero
(a crash), the pane falls through to your login shell so the scrollback survives for
inspection. Two opt-outs:
# Always keep a shell in the pane after claude exits (the pre-0.7 behavior)
export CLAUDE_AUTO_RETRY_KEEP_SHELL=1
# Never create a tmux session (e.g. you're inside Zellij/screen and don't want nesting).
# Note: the monitor needs a tmux pane to watch, so this disables auto-retry for the run.
export CLAUDE_AUTO_RETRY_NO_TMUX=1
Environment forwarding
Your full shell environment reaches claude inside the tmux session via a 0600
snapshot file under ~/.claude-auto-retry/tmp/ that only the launcher reads (and
deletes immediately). Nothing about your environment — names or values — ever appears
on a tmux command line, so secrets can't surface in /proc/<pid>/cmdline.
Overload backoff
Separate from subscription rate limits, this fork also detects sustained API
overload — Claude Code's own terminal API Error: <code> line for the retryable
set (429 / 500 / 502 / 503 / 504 / 529, or an overloaded_error JSON body) — and
retries on an exponential backoff instead of waiting for a usage reset. The two
paths never collide; usage limits always take precedence.
Sustained only. Claude Code already retries transient 5xx/529 internally with its own backoff. This feature fires only when those internal retries are exhausted and a terminal error is left in the pane. It should rarely trigger.
Terminal vs. transient. Claude Code renders an in-progress retry as the parens form
API Error (529 …) · Retrying in 5s · attempt 3/10, and the final exhausted error as the colon formAPI Error: 529 …. Detection requires the colon form and suppresses the· Retrying…/attempt n/msuffix, so the tool never interrupts Claude's own backoff.
Anchored, tail-only matching (why it won't fire on your code). Patterns are case-insensitive regexes matched against only the last 12 lines of the pane — never the full scrollback. They are anchored to Claude Code's
API Error: <code>render, so a bare503in code you're editing (res.status(503)), a port number, a quoted log, or astatus.claude.comlink in a comment will not trip detection. The one residual: a live tail that literally containsAPI Error: 529(e.g. editing this tool, or docs about Claude errors) will match — set"enabled": falsewhile doing that. (Earlier versions matched bare status numbers across the whole capture, which injected spurious retries during ordinary web-dev sessions.) For a structured, ambiguity-free trigger seeDESIGN-NOTES.md.
Configured under an overload block (shown with its defaults):
{
"overload": {
"enabled": true,
"patterns": ["API Error:\\s*(429|500|502|503|504|529)\\b", "overloaded_error", "temporarily limiting requests"],
"backoffSeconds": [30, 60, 120, 240, 300],
"steadyStateSeconds": 300,
"jitterPct": 15,
"maxTotalWaitMinutes": 120,
"retryMessage": "Continue where you left off.",
"relaunchOnExit": false,
"relaunchCommand": "claude --continue"
}
}
| Option | Default | Description |
|---|---|---|
enabled | true | Turn the overload path on/off |
patterns | (see above) | Case-insensitive regexes matching a terminal overload error in the pane tail (last 12 lines) |
backoffSeconds | [30,60,120,240,300] | Wait before each retry; index i for attempt i |
steadyStateSeconds | 300 | Wait once the backoffSeconds array is exhausted |
jitterPct | 15 | ±% jitter applied to every wait (clamped 0–100) |
maxTotalWaitMinutes | 120 | Cumulative-wait cap — give up loudly past this |
retryMessage | "Continue where you left off." | Sent to Claude on each retry |
relaunchOnExit | false | See the gating decision below |
relaunchCommand | "claude --continue" | Command used by relaunchOnExit |
The waits go 30 → 60 → 120 → 240 → 300 → 300 …, each with ±15% jitter, until the
error clears (success) or the cumulative wait reaches maxTotalWaitMinutes (give
up — the cap guards against hammering a genuinely-down endpoint or masking a real
outage; check status.claude.com).
Event-driven detection (recommended — no scraping)
The scraper above is a heuristic over terminal output. For an exact, ambiguity-free
trigger, install the StopFailure hook — Claude Code fires it precisely when a
turn ends in an API error, with a typed error class:
claude-auto-retry install-hook # into $CLAUDE_CONFIG_DIR or ~/.claude
claude-auto-retry install-hook /path/to/config # repeat per CLAUDE_CONFIG_DIR you use
This adds a StopFailure hook (matcher overloaded|server_error) that writes a
pane-keyed marker the monitor consumes — no terminal scraping, so it cannot
false-positive on code or scrollback. Sessions launched via the wrapper after
installing the hook use it automatically; the first marker latches event mode and
disables the scraper for that session. Sessions without the hook (or pre-install) fall
back to the anchored scraper. Remove with uninstall-hook. See DESIGN-NOTES.md for
the architecture.
Why not
rate_limit? The event path handles only transient overloads (seconds-scale backoff). Arate_limitis the subscription session/usage limit — an hours-scale wait until a printed reset time — so it's handled by the usage-wait path above, not the overload path. Routing it through the hook would fire premature retries against a session that's simply out of quota.
Gating decision (alive-at-prompt vs exited-to-shell)
A transient API error in interactive Claude Code surfaces inline and leaves the
process alive at its prompt — it does not exit to the shell. So the default,
robust behavior reuses the existing usage-limit mechanism: only retry when the
foreground process is claude/node and the session is idle, not working
(the esc to interrupt footer is absent). Retrying mid-internal-retry would
double-drive the session, so that case is deferred, never sent.
If a 500 ever does drop you to the shell, send-keys is correctly blocked by
the foreground check (it never types into bash), and the tool logs
overload-exited-to-shell rather than masking it. Auto-relaunch is off by
default — blindly typing claude --continue into a shell the user may be using
is worse than surfacing the stall. Set relaunchOnExit: true (and adjust
relaunchCommand) only if you actually observe shell-exits on overload.
Safeguard retry
A third failure mode, separate from usage limits and 5xx overloads: the model's safeguards flag your message and Claude Code can't respond. It renders like:
● API Error: Fable 5's safeguards flagged this message (…/legal/aup). They may flag
safe, normal content as well. … Claude Code can't respond to this request with Fable 5.
Double press esc to edit your last message, or try a different model with /model.
These flags are often false positives (the message says so) and semi-random, so an
immediate re-send frequently clears them. When the tool sees this render at an idle
prompt, it sends a short retry message (continue by default), waits a few seconds, and
repeats — but only up to maxRetries times, then gives up loudly (logged) rather
than looping. A sticky flag means the content/model combination is genuinely blocked;
switch models with /model or rephrase.
Detection is tail-anchored (last 12 pane lines) like the overload path, and a match
additionally requires the API Error render line nearby — so the phrases appearing in
scrollback or in a conversation about safeguards won't trigger it.
Configured under a safeguard block (defaults shown):
{
"safeguard": {
"enabled": true,
"patterns": ["safeguards flagged this message", "can't respond to this request with", "legal/aup"],
"maxRetries": 3,
"retryDelaySeconds": 8,
"retryMessage": "continue"
}
}
| Option | Default | Description |
|---|---|---|
enabled | true | Turn the safeguard-retry path on/off |
patterns | (see above) | Case-insensitive regexes marking the safeguard render (matched in the pane tail, near an API Error line) |
maxRetries | 3 | Re-send attempts before giving up — kept small; retrying a sticky flag won't help |
retryDelaySeconds | 8 | Wait between re-sends |
retryMessage | "continue" | Message sent to nudge past the flag |
Usage limits always take precedence; the safeguard path only acts when Claude is idle
(no esc to interrupt footer) and the foreground process is claude/node.
Interrupted-stream resume
Close your laptop lid while Claude is mid-answer and the work does not survive. Claude Code wraps the response body in a byte watchdog; when the bytes stop arriving it aborts the stream and finalizes whatever had already been printed, naming the cause:
⏺ API Error: Your computer went to sleep mid-response. The response above may be
incomplete.
The turn is then over. The prompt returns idle and nothing resumes it, so the session
sits there — potentially for hours — with a half-finished answer on screen. Claude Code
retries by itself only while the response is still thinking-only; once real content has
been yielded it declines to retry, which is exactly when this render appears. That is the
gap this closes: seeing it at an idle prompt, the tool sends continue, bounded at
maxRetries because a machine that just woke may not have its network back yet.
The same finalizer emits the render for a dropped connection, a stalled stream and a mid-response server error. All are the same truncated-turn state with the same remedy, so all are matched — sleeping is just the cause we can name.
Detection is anchored on the shape of the line, not its vocabulary: a real render
begins with API Error:, behind at most Claude's message glyph. The "an API Error
line nearby" rule the overload and safeguard paths use is deliberately not enough here —
these sentences are ordinary English, so a session merely explaining them quotes the
whole render, anchor included, mid-sentence. Prose carries it mid-line and your own typed
line carries ❯, so neither trips it.
Configured under a streamInterrupted block (defaults shown):
{
"streamInterrupted": {
"enabled": true,
"patterns": ["went to sleep mid-response", "Connection lost mid-response", "…"],
"maxRetries": 2,
"retryDelaySeconds": 5,
"retryMessage": "continue"
}
}
| Option | Default | Description |
|---|---|---|
enabled | true | Turn the interrupted-stream path on/off |
patterns | (all 7 renders) | Case-insensitive regexes, matched only against a line that begins with the API Error: render |
maxRetries | 2 | Resume attempts before giving up loudly |
retryDelaySeconds | 5 | Wait before resuming — lets the network settle after a wake |
retryMessage | "continue" | Message sent to pick the work back up |
Usage limits take precedence, and like the safeguard path this only acts when Claude is
idle and the foreground process is claude/node.
Near-limit wrap-up nudge
At roughly 95% of the 5-hour window, Claude Code injects a checkpoint instruction into the model's context — finish the current step, then list up to three short bullets of the most impactful remaining work, don't start subagents or long-running work — and prints:
⏺ Approaching your 5-hour usage limit — Claude will wrap up the current step.
The model does exactly that and ends the turn. There is no limit banner (the limit has not been hit), the prompt returns idle, and nothing resumes the session — so an overnight run winds down at 95% and stays parked long after the window has reset. This is a server-side Claude Code behavior with no user-facing switch (it is feature-flagged, not a setting), so the tool handles the render instead.
Seeing the notice at an idle prompt, the tool sends one continue. The session then either
finishes its work or runs into the real limit, where the usage wait takes
over as usual. Unlike the retry families above this is not a bounded machine: the nudge
renders as a user row under the notice, and a notice with a user row below it — yours or
ours — belongs to a turn that has already been answered, so it is never nudged twice. The
maxRetries cap only bounds the pathological case where the nudge never renders.
Detection is anchored on the shape of the line, like the interrupted-stream render: the notice begins its line, behind at most Claude's message glyph, so prose quoting it and your own typed copy don't trip it.
Configured under a nearLimitWrapUp block (defaults shown):
{
"nearLimitWrapUp": {
"enabled": true,
"maxRetries": 3,
"retryMessage": "continue"
}
}
Set "enabled": false if
Files in the repo
- bin
- launchd
- src
- systemd
- test
- .gitignore
- CHANGELOG.md
- DESIGN-NOTES.md
- LICENSE
- llms.txt
- package.json
- README.md
Discussion (0)
Ask about usage, or say what you built with itSign in to join the discussion.
No comments yet. Be the first to say what this is good for.
More tools
The best-benchmarked open-source AI memory system. And it's free.
Orca is the ADE for working with a fleet of parallel agents. Run any coding agent with your own subscription. Available on desktop, mobile and remote runtime.

A cross-platform desktop All-in-One assistant for Claude Code, Codex, OpenCode, OpenClaw, Grok Build & Hermes Agent. Only official website: ccswitch.io
Never stop coding. Free MIT AI gateway: one endpoint, 352 providers (150+ free), 1200+ models Kimi, Claude, GPT, Gemini, GLM, DeepSeek, MiniMax. Works with Claude Code, Codex, Cursor, OpenCode, Cline & Copilot. Quota-aware auto-fallback, RTK+Caveman compression saves 15-95% tokens, MCP/A2A, Desktop/PWA. Built by 550+ contributors
Compress tool outputs, logs, files, and RAG chunks before they reach the LLM. 20% fewer tokens for coding agents, 60-95% fewer tokens for JSON, same answers. Library, proxy, MCP server.