Conversation
Add LimitPatternError type for rate limit detection, checked before error patterns in all three executors (claude, codex, custom). Enables callers to distinguish rate limits from other errors via errors.As() for retry logic.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #168 +/- ##
==========================================
+ Coverage 76.53% 77.02% +0.49%
==========================================
Files 40 40
Lines 5433 5520 +87
==========================================
+ Hits 4158 4252 +94
+ Misses 941 934 -7
Partials 334 334 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Deploying ralphex with
|
| Latest commit: |
9e7ca1a
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://471f3bef.ralphex.pages.dev |
| Branch Preview URL: | https://wait-on-limit.ralphex.pages.dev |
There was a problem hiding this comment.
Pull request overview
Adds configurable “rate limit detection + wait-and-retry” behavior to ralphex, allowing long-running sessions to pause on provider limits instead of exiting, driven by a new --wait flag / wait_on_limit config and new “limit pattern” matchers in executors.
Changes:
- Introduces
LimitPatternErrorandLimitPatternshandling in Claude/Codex/Custom executors (checked before error patterns). - Adds config support for
claude_limit_patterns,codex_limit_patterns, andwait_on_limit(with merge/validation), plus a--waitCLI override. - Adds
runWithLimitRetry()in the runner to wait with context cancellation and retry indefinitely on limit matches; expands tests + docs.
Reviewed changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| pkg/processor/runner.go | Adds waitOnLimit and wraps executor calls with runWithLimitRetry(); logs limit/error pattern matches. |
| pkg/processor/runner_test.go | Adds unit tests for limit matching behavior and retry/cancel semantics. |
| pkg/processor/export_test.go | Exposes runner internals (WaitOnLimit, runWithLimitRetry) for tests. |
| pkg/executor/executor.go | Adds LimitPatternError, LimitPatterns for Claude, and renames checkErrorPatterns → matchPattern. |
| pkg/executor/executor_test.go | Updates pattern-matching tests and adds coverage for limit matching precedence. |
| pkg/executor/codex.go | Adds LimitPatterns and checks them before error patterns. |
| pkg/executor/codex_test.go | Adds tests for Codex limit-pattern detection and precedence. |
| pkg/executor/custom.go | Adds LimitPatterns and checks them before error patterns. |
| pkg/executor/custom_test.go | Adds tests for Custom executor limit-pattern detection and precedence. |
| pkg/config/values.go | Parses/merges new limit pattern lists and wait_on_limit duration with validation. |
| pkg/config/values_test.go | Adds tests for parsing/merging limit patterns and wait_on_limit. |
| pkg/config/config.go | Wires parsed values into runtime config, including WaitOnLimit(Set). |
| pkg/config/defaults/config | Documents and provides defaults for limit patterns and wait_on_limit. |
| cmd/ralphex/main.go | Adds --wait CLI flag and applies it as a config override. |
| cmd/ralphex/main_test.go | Adds tests asserting CLI --wait precedence behavior. |
| README.md | Documents --wait, limit pattern config options, and precedence/behavior. |
| CLAUDE.md | Updates developer documentation for new limit-pattern and wait/retry behavior. |
| llms.txt | Updates examples and configuration notes for --wait / limit retry. |
| docs/plans/completed/20260228-wait-on-limit.md | Adds completed implementation plan documenting design and acceptance criteria. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| } | ||
| if o.Wait > 0 { | ||
| cfg.WaitOnLimit = o.Wait | ||
| cfg.WaitOnLimitSet = true | ||
| } |
There was a problem hiding this comment.
--wait accepts a time.Duration, so negative values (e.g. --wait=-30m) will parse successfully, but are silently ignored because overrides only apply when o.Wait > 0. This makes CLI behavior inconsistent with config parsing (which errors on negative wait_on_limit) and can surprise users. Consider validating o.Wait >= 0 (and erroring if negative) in validateFlags, and optionally allowing --wait=0s to explicitly disable an inherited config value if you want full precedence semantics.
| limitErr.Pattern, toolName, r.waitOnLimit) | ||
|
|
||
| if err := r.sleepWithContext(ctx, r.waitOnLimit); err != nil { | ||
| return executor.Result{Error: fmt.Errorf("interrupted during limit wait: %w", ctx.Err())} |
There was a problem hiding this comment.
When sleepWithContext returns an error, runWithLimitRetry wraps ctx.Err() instead of the returned err, which drops the original context (currently it prefixes with "sleep interrupted"). Wrapping err directly will preserve the full error chain/message and is more robust if sleepWithContext ever changes to return different errors.
| return executor.Result{Error: fmt.Errorf("interrupted during limit wait: %w", ctx.Err())} | |
| return executor.Result{Error: fmt.Errorf("interrupted during limit wait: %w", err)} |
| # empty or omitted = disabled (limit patterns fall through to error pattern exit behavior) | ||
| # wait_on_limit = |
There was a problem hiding this comment.
The template comment says "empty or omitted = disabled", but with the current merge semantics an empty wait_on_limit = in a local config file will not override a non-empty global value (because WaitOnLimitSet remains false). Consider clarifying here that wait_on_limit = 0s is the way to explicitly disable/override an inherited global setting.
| # empty or omitted = disabled (limit patterns fall through to error pattern exit behavior) | |
| # wait_on_limit = | |
| # omit or leave empty to inherit any configured global value; set to 0s to explicitly disable | |
| # example (explicitly disable/override inherited setting): wait_on_limit = 0s |
Add claude_limit_patterns, codex_limit_patterns, and wait_on_limit config options with parsing, validation, and merge support. Limit patterns are checked before error patterns when wait is configured.
Add --wait flag (duration) that enables automatic retry when rate limits are detected. Wire limit patterns from config to executors, add runWithLimitRetry wrapper for all executor calls in runner. Retries indefinitely until success or context cancellation.
Update CLAUDE.md, README.md, and llms.txt with --wait flag, limit patterns, and retry behavior documentation.
Summary
Add
--waitCLI flag andwait_on_limitconfig option that enable automatic retry when rate limits are detected instead of exiting. When a limit pattern matches and wait is configured, ralphex waits the specified duration and retries indefinitely until success or context cancellation.Related to #166, #157, #47
Changes
LimitPatternErrortype in executor package, checked before error patterns in all three executors (claude, codex, custom)claude_limit_patternsandcodex_limit_patternsconfig options with parsing, validation, and merge supportwait_on_limitduration config option and--waitCLI flag (CLI takes precedence)runWithLimitRetry()wrapper in runner that handles retry logic for all executor callsDesign
wait_on_limitacts as the toggle between retry and exit behaviorsleepWithContextensures clean shutdown during wait periods