Files
claude-auto-retry/README.md
T
CheapestInference 1aad1e0313 feat: claude-auto-retry v0.1.0
Auto-retry Claude Code sessions when hitting Anthropic subscription rate limits.
Uses tmux monitoring + send-keys to detect rate limit messages, wait for reset,
and send "continue" automatically. Zero dependencies, zero workflow change.

- Shell wrapper intercepts `claude` command transparently
- Background monitor polls tmux pane for rate limit patterns
- Timezone-aware reset time parsing with DST safety
- Safe send-keys with foreground process verification
- --print mode: buffers output, retries cleanly for pipes
- Config validation prevents bad values from causing crashes
- 59 tests, 0 dependencies

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 11:43:36 +01:00

300 lines
11 KiB
Markdown

# 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.**
[![npm version](https://img.shields.io/npm/v/claude-auto-retry.svg)](https://www.npmjs.com/package/claude-auto-retry)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Node.js >= 18](https://img.shields.io/badge/node-%3E%3D18-brightgreen.svg)](https://nodejs.org)
---
## 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
```bash
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:
1. Detects the rate limit message in the terminal
2. Parses the reset time (timezone-aware)
3. Waits until the limit resets + 60s margin
4. Verifies Claude is still the foreground process
5. 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 `claude` command, 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
- **`--print` mode 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`
## Rate Limit Patterns Detected
The tool detects these real-world Claude Code messages:
| Pattern | Example |
|---------|---------|
| N-hour limit reached | `5-hour limit reached - resets 3pm (UTC)` |
| 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` |
Custom patterns can be added via config for future message format changes.
## Configuration
Optional. Create `~/.claude-auto-retry.json`:
```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.
## CLI Commands
```bash
claude-auto-retry install # Install shell wrapper + tmux
claude-auto-retry uninstall # Remove shell wrapper
claude-auto-retry status # Show monitor activity + last log entries
claude-auto-retry logs # Tail today's log file in real-time
claude-auto-retry version # Print version
```
## Platform Support
### Operating Systems
| OS | tmux auto-install | Status |
|----|-------------------|--------|
| Ubuntu / Debian | `apt-get` | Fully supported |
| CentOS / RHEL / Fedora | `dnf` | Fully supported |
| Rocky Linux / Amazon Linux | `dnf` | Fully supported |
| macOS | `brew` | Fully supported |
| Arch Linux | `pacman` | Fully supported |
| Alpine | `apk` | Fully supported |
### Requirements
- **Node.js** >= 18
- **tmux** >= 2.1 (auto-installed if missing)
### Shell Support
| Shell | Status |
|-------|--------|
| bash | Full (auto-install to `~/.bashrc`) |
| zsh | Full (auto-install to `~/.zshrc`) |
| fish | Manual setup (instructions printed on `install`) |
## `--print` Mode
For scripted/piped usage (`claude -p "..." | jq`), the tool:
1. Buffers all output (nothing goes to stdout until done)
2. If rate-limited: discards partial output, waits, re-executes with same args
3. Consumer receives a single clean response
```bash
# This just works — retries transparently if rate-limited
claude -p "Generate a JSON schema" | jq .
```
## Logging
Logs are written to `~/.claude-auto-retry/logs/YYYY-MM-DD.log`:
```
[2026-03-18 15:00:05] [INFO] Monitor started for pane %3 (claude PID: 12345)
[2026-03-18 15:32:10] [INFO] Rate limit detected: "5-hour limit reached - resets 3pm". Waiting 3547s...
[2026-03-18 16:01:10] [INFO] Sent retry message (attempt 1)
```
Logs rotate daily. Files older than 7 days are cleaned automatically.
## Uninstall
```bash
claude-auto-retry uninstall
npm uninstall -g claude-auto-retry
```
This removes the shell function from your rc files. tmux is left installed.
## Known Limitations
1. **Retry message context** — The retry message is sent as plain text. If Claude was mid-confirmation or in a special input state, it may not interpret it as a continuation. You can customize the message via config.
2. **Node version lock** — The launcher path is resolved at install time. If you switch Node versions with nvm, re-run `claude-auto-retry install`.
3. **tmux required** — The tool needs tmux to monitor terminal output and inject keystrokes. It auto-installs if missing, but requires sudo for system package managers.
## Contributing
Contributions are welcome! Here's how to get started:
### Development Setup
```bash
git clone https://github.com/cheapestinference/claude-auto-retry.git
cd claude-auto-retry
npm test # Run all 59 tests
npm link # Install locally for testing
```
### Project Structure
```
claude-auto-retry/
├── bin/cli.js # CLI: install/uninstall/status/logs/version
├── src/
│ ├── patterns.js # Rate limit detection + ANSI stripping
│ ├── time-parser.js # Reset time parsing with timezone support
│ ├── config.js # Config loading + validation
│ ├── logger.js # File-based logging with rotation
│ ├── tmux.js # tmux command wrappers (execFile-based)
│ ├── monitor.js # Core monitoring loop + retry logic
│ ├── launcher.js # Process orchestration + signal forwarding
│ └── wrapper.sh # Shell function template
├── test/ # 59 tests across 7 test files
├── package.json
├── LICENSE
└── README.md
```
### Architecture Decisions
- **Zero dependencies** — only Node.js built-ins. Reduces supply chain risk and install size.
- **`execFile` over `exec`** — all child process calls use array-based args to prevent shell injection.
- **`stdio: 'inherit'`** — Claude gets the real TTY for full TUI support. The monitor reads pane content independently via `tmux capture-pane`.
- **Iterative DST correction** — timezone offset is computed via 3-iteration convergence loop, not a single-shot formula that breaks at DST boundaries.
- **Config validation** — invalid user config values fall back to safe defaults instead of producing NaN/undefined behavior.
### Running Tests
```bash
npm test # All tests
node --test test/patterns.test.js # Single file
node --test --watch test/ # Watch mode
```
### Submitting Changes
1. Fork the repo
2. Create a feature branch (`git checkout -b feat/my-feature`)
3. Write tests first (TDD)
4. Make your changes
5. Ensure all tests pass (`npm test`)
6. Submit a Pull Request
### Areas for Contribution
- **New rate limit patterns** — If you see a Claude Code rate limit message that isn't detected, open an issue with the exact text.
- **Fish shell support** — Auto-install for fish shell (currently manual).
- **Windows support** — WSL works, but native Windows would need a different approach.
- **Notification integration** — Desktop/Slack notification when rate limit detected or when Claude resumes.
## Related Projects
- [claude-code-queue](https://github.com/JCSnap/claude-code-queue) — Queue-based task system for Claude Code with rate limit handling
- [opencode-claude-quota](https://github.com/nguyenngothuong/opencode-claude-quota) — Rate limit quota monitoring (display only)
## FAQ
**Q: Does this work with Claude Max/Pro/Team?**
A: Yes. It works with any Anthropic subscription that has usage-based rate limits.
**Q: Does it work outside of tmux?**
A: Yes. If you're not in tmux, it creates a tmux session transparently. You won't notice a difference.
**Q: What if I continue manually before the retry fires?**
A: The monitor checks if the rate limit is still visible before sending keys. If you already continued, it resets and keeps watching.
**Q: What if Claude exits while the monitor is waiting?**
A: The monitor checks the Claude process every 30 seconds during the wait. If Claude exits, the monitor shuts down cleanly.
**Q: Does it consume a lot of resources?**
A: No. `tmux capture-pane` is extremely lightweight. The monitor uses ~0% CPU at a 5-second polling interval.
**Q: Can it accidentally type into the wrong program?**
A: The monitor verifies the foreground process is `node` or `claude` before sending keys. If you've switched to vim, bash, or anything else, it skips the retry.
## License
MIT — see [LICENSE](LICENSE) for details.
---
Made with care by [CheapestInference](https://github.com/cheapestinference).