# How the Rate Limit Wait Daemon Auto-Resumes Claude Code Sessions in oh-my-claudecode

> Learn how the rate limit wait daemon in oh-my-claudecode auto-resumes Claude Code sessions. Discover how it monitors API usage and automatically unblocks tmux panes when rate limits reset.

- Repository: [Bellman/oh-my-claudecode](https://github.com/Yeachan-Heo/oh-my-claudecode)
- Tags: internals
- Published: 2026-03-27

---

**The rate limit wait daemon monitors Anthropic API usage quotas every 60 seconds and automatically sends a "1" followed by Enter to blocked tmux panes once limits reset, resuming Claude Code sessions without manual intervention.**

The oh-my-claudecode toolkit provides a background **rate limit wait daemon** that eliminates the need to manually restart Claude Code after hitting API quotas. By continuously polling the Anthropic usage API and detecting blocked tmux sessions, the daemon orchestrates seamless auto-resume functionality. This article explains the implementation details, from the polling loop in [`daemon.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/daemon.ts) to the tmux detection logic that identifies stalled sessions.

## Core Architecture Components

The daemon’s architecture consists of specialized modules that handle API monitoring, process detection, and secure state management.

### The Polling Loop (`pollLoop`)

Located in [`src/features/rate-limit-wait/daemon.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/features/rate-limit-wait/daemon.ts) at lines 42–56, the `pollLoop` function executes the main control cycle. It runs repeatedly at a default interval of 60 seconds, recording system status and driving the auto-resume logic. This loop determines whether to scan for blocked panes based on current rate limit conditions.

### Rate Limit Monitoring (`checkRateLimitStatus`)

The `checkRateLimitStatus` function in [`src/features/rate-limit-wait/rate-limit-monitor.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/features/rate-limit-wait/rate-limit-monitor.ts) (lines 15–71) queries the Anthropic usage API via [`hud/usage-api.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/hud/usage-api.ts). It retrieves 5-hour, weekly, and monthly usage percentages, calculates the next reset time, and returns a boolean indicating whether any quota is exhausted. When the API returns a 429 status code, the function triggers degraded monitoring mode.

### tmux Pane Detection (`scanForBlockedPanes`)

The detection engine resides in [`src/features/rate-limit-wait/tmux-detector.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/features/rate-limit-wait/tmux-detector.ts) (lines 71–138) and comprises three coordinated functions:

- **`listTmuxPanes`** enumerates all active tmux sessions and their pane IDs
- **`capturePaneContent`** retrieves the last N lines from each pane for analysis
- **`analyzePaneContent`** flags a pane as **blocked** when it detects Claude Code patterns, rate-limit-related phrases, and a prompt state indicating the process awaits user input

The system validates all pane IDs against the strict regex `/^%\\d+$/` to prevent injection attacks.

### Resume Sequence Execution (`sendResumeSequence`)

Once quotas reset, the daemon invokes `sendResumeSequence` (lines 258–314 in [`tmux-detector.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/tmux-detector.ts)) to resume blocked sessions. This function executes `tmux send-keys` to transmit the sequence `1` followed by Enter (the default "continue" choice), plus any optional custom text configured by the user. The operation targets specific pane IDs collected during the detection phase.

### State Persistence and Security Hardening

The daemon maintains operational state in `~/.omc/state/rate-limit-daemon.json` with strict `0600` file permissions, ensuring only the owner can read the PID and blocked pane lists. Security measures include:

- **Environment sanitization**: Only whitelisted environment variables pass to the child process via `createMinimalDaemonEnv`
- **Config isolation**: Settings serialize to a temporary JSON file that the daemon reads, preventing shell injection
- **Process tracking**: The `writePidFile` and `removePidFile` utilities manage the daemon’s PID for clean shutdowns via `SIGTERM`

## The Auto-Resume Workflow

The daemon follows a precise state machine to ensure it resumes sessions exactly once per rate-limit cycle:

1. **Daemon initialization**: `startDaemon()` forks a detached Node process that imports `pollLoopWithConfigFile` from the compiled daemon module
2. **Status polling**: Every interval, the loop calls `checkRateLimitStatus()` to assess API quotas
3. **Block detection**: When limits are active, `shouldMonitorBlockedPanes` returns true, triggering `scanForBlockedPanes` to populate `state.blockedPanes` with stalled tmux sessions
4. **Quota reset detection**: When the next poll reports no active limits and `state.blockedPanes` contains entries, the daemon iterates over the list
5. **Resume execution**: For each blocked pane, the daemon calls `sendResumeSequence(pane.id)`, records successful resumes, and clears the blocked pane list

If no tmux environment is available, the daemon logs a warning and enters a passive monitoring state.

## Programmatic API and CLI Usage

### Starting the Daemon from TypeScript

```typescript
import { startDaemon, stopDaemon } from './features/rate-limit-wait/daemon.js';

// Start (will no-op if already running)
const resp = startDaemon();
if (resp.success) {
  console.log(`Daemon started (PID ${resp.state?.pid})`);
} else {
  console.warn(`Daemon not started: ${resp.message}`);
}

// Later, stop it gracefully
// stopDaemon();

```

### Using the Command Line Interface

```bash

# Start the background watcher (daemon)

$ omc wait --start
Daemon started with PID 12345

# Check operational status

$ omc wait status
Rate-limit daemon is running (PID 12345)

# Stop auto-resume functionality

$ omc wait --stop
Daemon stopped

```

### Manual Resume Triggering

For edge cases requiring immediate intervention, the resume logic is exposed directly:

```typescript
import { sendResumeSequence } from './features/rate-limit-wait/tmux-detector.js';

// Target a specific pane ID
const paneId = '%3';
if (sendResumeSequence(paneId)) {
  console.log('Sent resume keys to pane', paneId);
} else {
  console.error('Failed to send resume to pane', paneId);
}

```

## Summary

- The **rate limit wait daemon** runs as a detached background process that polls the Anthropic API every 60 seconds via `pollLoop`
- **Auto-resume** triggers only when the daemon detects a transition from active rate limiting to available quota, ensuring sessions resume immediately upon reset
- **tmux detection** relies on content analysis of pane buffers to identify Claude Code sessions paused at rate-limit prompts
- The system implements **security hardening** through file permission restrictions (mode `0600`), environment variable whitelisting, and regex validation of pane identifiers
- Both **programmatic APIs** (`startDaemon`, `stopDaemon`) and **CLI commands** (`omc wait --start`) provide flexible control over the daemon lifecycle

## Frequently Asked Questions

### How does the daemon know when Claude Code is waiting for a rate limit to reset?

The daemon uses `scanForBlockedPanes` in [`src/features/rate-limit-wait/tmux-detector.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/src/features/rate-limit-wait/tmux-detector.ts) to capture the last several lines of each tmux pane. It analyzes this content for Claude Code-specific patterns combined with rate-limit-related phrases and a prompt indicating the process awaits user input. Only panes meeting all three criteria are flagged as blocked and added to the resume queue.

### What specific keys does the daemon send to resume a session?

According to the source code in [`tmux-detector.ts`](https://github.com/Yeachan-Heo/oh-my-claudecode/blob/main/tmux-detector.ts), the `sendResumeSequence` function transmits the character `1` followed by an Enter keystroke (represented as `C-m` in tmux send-keys syntax). This corresponds to the default "continue" option presented by Claude Code when it pauses due to quota exhaustion. Users can optionally append custom text to this sequence via configuration.

### Where does the daemon store its process state and blocked pane information?

The daemon persists operational data to `~/.omc/state/rate-limit-daemon.json` with strict `0600` permissions, ensuring only the file owner can access the PID and blocked pane lists. Additionally, the daemon writes its process ID to a PID file for management by the `stopDaemon` function, which sends `SIGTERM` to cleanly terminate the background process.

### Can the daemon run without tmux?

No, the auto-resume functionality requires a tmux environment. If the daemon starts and cannot detect tmux sessions, it logs a warning message and continues polling the API without attempting pane detection. The resume logic specifically depends on `tmux send-keys` to interact with Claude Code sessions, making tmux a hard dependency for the auto-resume feature.