# Ralph Reference Guide This reference guide provides essential information for troubleshooting and understanding Ralph's autonomous development loop. In bmalph-managed projects, start Ralph with `bmalph run`. When you need direct loop flags such as `--reset-circuit` or `--live`, invoke `bash .ralph/ralph_loop.sh ...` from the project root. ## Table of Contents 1. [Configuration Files](#configuration-files) 2. [Project Configuration (.ralph/.ralphrc)](#project-configuration-ralphralphrc) 3. [Session Management](#session-management) 4. [Circuit Breaker](#circuit-breaker) 5. [Exit Detection](#exit-detection) 6. [Live Streaming](#live-streaming) 7. [Troubleshooting](#troubleshooting) --- ## Configuration Files Ralph uses several files within the `.ralph/` directory, plus an optional legacy fallback config at the project root: | File | Purpose | |------|---------| | `.ralph/PROMPT.md` | Main prompt that drives each loop iteration | | `.ralph/@fix_plan.md` | Prioritized task list that Ralph follows | | `.ralph/@AGENT.md` | Build and run instructions maintained by Ralph | | `.ralph/status.json` | Real-time status tracking (JSON format) | | `.ralph/logs/` | Execution logs for each loop iteration | | `.ralph/.ralph_session` | Current session state | | `.ralph/.circuit_breaker_state` | Circuit breaker state | | `.ralph/live.log` | Live streaming output file for monitoring | | `.ralph/.loop_start_sha` | Git HEAD SHA captured at loop start for progress detection | | `.ralph/.ralphrc` | Project-specific configuration installed by bmalph | | `.ralphrc` (project root, legacy fallback) | Optional legacy configuration for older standalone Ralph layouts | ### Rate Limiting - Default: 100 API calls per hour (configurable via `--calls` flag or `.ralph/.ralphrc`) - Automatic hourly reset with countdown display - Call tracking persists across script restarts --- ## Project Configuration (.ralph/.ralphrc) In bmalph-managed projects, Ralph reads `.ralph/.ralphrc` for per-project settings. For backward compatibility with older standalone Ralph layouts, it also falls back to a project-root `.ralphrc` when the bundled config file is missing. ### Precedence Environment variables > Ralph config file > script defaults ### Available Settings | Variable | Default | Description | |----------|---------|-------------| | `PROJECT_NAME` | `my-project` | Project name for prompts and logging | | `PROJECT_TYPE` | `unknown` | Project type (javascript, typescript, python, rust, go) | | `MAX_CALLS_PER_HOUR` | `100` | Rate limit for API calls | | `CLAUDE_TIMEOUT_MINUTES` | `15` | Timeout per loop driver invocation | | `CLAUDE_OUTPUT_FORMAT` | `json` | Output format (json or text) | | `ALLOWED_TOOLS` | `Write,Read,Edit,MultiEdit,Glob,Grep,Task,TodoWrite,WebFetch,WebSearch,EnterPlanMode,ExitPlanMode,NotebookEdit,Bash` | Claude Code only. Ignored by codex, cursor, and copilot | | `CLAUDE_PERMISSION_MODE` | `bypassPermissions` | Claude Code only. Prevents interactive approval workflows from blocking unattended loops without relying on beta headers | | `PERMISSION_DENIAL_MODE` | `continue` | How Ralph responds to permission denials: continue, halt, or threshold | | `SESSION_CONTINUITY` | `true` | Maintain context across loops | | `SESSION_EXPIRY_HOURS` | `24` | Session expiration time | | `RALPH_VERBOSE` | `false` | Enable verbose logging | | `CB_NO_PROGRESS_THRESHOLD` | `3` | Loops with no progress before circuit opens | | `CB_SAME_ERROR_THRESHOLD` | `5` | Loops with same error before circuit opens | | `CB_OUTPUT_DECLINE_THRESHOLD` | `70` | Output decline percentage threshold | | `CB_COOLDOWN_MINUTES` | `30` | Minutes before OPEN auto-recovers to HALF_OPEN | | `CB_AUTO_RESET` | `false` | Reset circuit to CLOSED on startup | | `TASK_SOURCES` | `local` | Where to import tasks from (local, beads, github) | ### Generation bmalph copies `ralphrc.template` to `.ralph/.ralphrc` during `bmalph init`. Untouched managed configs are updated on upgrade, while customized `.ralph/.ralphrc` files are preserved. --- ## Session Management Ralph maintains session continuity across loop iterations using `--resume` with explicit session IDs. ### Session Continuity Ralph uses `--resume ` instead of `--continue` to resume sessions. This ensures Ralph only resumes its own saved sessions and avoids hijacking unrelated active sessions. This applies to every driver that exposes resumable IDs today: - Claude Code - OpenAI Codex - Cursor ### Session Files | File | Purpose | |------|---------| | `.ralph/.ralph_session` | Current Ralph session state (active or reset/inactive) | | `.ralph/.ralph_session_history` | History of last 50 session transitions | | `.ralph/.claude_session_id` | Persisted driver session ID (shared filename for historical reasons; used by Claude Code, Codex, and Cursor) | ### Session Lifecycle Sessions are automatically reset when: - Circuit breaker opens (stagnation detected) - Manual interrupt (Ctrl+C / SIGINT) - Project completion (graceful exit) - Manual circuit breaker reset (`bash .ralph/ralph_loop.sh --reset-circuit`) - Manual session reset (`bash .ralph/ralph_loop.sh --reset-session`) ### Session Expiration Sessions expire after 24 hours (configurable via `SESSION_EXPIRY_HOURS` in `.ralph/.ralphrc`). When expired: - A new session is created automatically - Previous context is not preserved - Session history records the transition ### Session State Structure Active session payload: ```json { "session_id": "uuid-string", "created_at": "ISO-timestamp", "last_used": "ISO-timestamp" } ``` Reset/inactive payload: ```json { "session_id": "", "reset_at": "ISO-timestamp", "reset_reason": "reason string" } ``` --- ## Circuit Breaker The circuit breaker prevents runaway loops by detecting stagnation. ### States | State | Description | Action | |-------|-------------|--------| | **CLOSED** | Normal operation | Loop continues | | **HALF_OPEN** | Monitoring after recovery | Testing if issue resolved | | **OPEN** | Halted due to stagnation | Loop stops | ### Thresholds | Threshold | Default | Description | |-----------|---------|-------------| | `CB_NO_PROGRESS_THRESHOLD` | 3 | Open circuit after N loops with no file changes | | `CB_SAME_ERROR_THRESHOLD` | 5 | Open circuit after N loops with repeated errors | | `CB_OUTPUT_DECLINE_THRESHOLD` | 70% | Open circuit if output declines by >N% | | `CB_PERMISSION_DENIAL_THRESHOLD` | 2 | Open circuit after N loops with permission denials | | `CB_COOLDOWN_MINUTES` | 30 | Minutes before OPEN auto-recovers to HALF_OPEN | | `CB_AUTO_RESET` | false | Reset to CLOSED on startup (bypasses cooldown) | ### Permission Denial Detection When the active driver is denied permission to execute commands, Ralph: 1. Detects permission denials from the JSON output 2. Applies `PERMISSION_DENIAL_MODE` from `.ralph/.ralphrc` 3. Keeps `last_action: permission_denied` visible in the status file and dashboard `PERMISSION_DENIAL_MODE` behavior: - `continue` keeps looping and logs the denial - `halt` stops immediately with reason `permission_denied` - `threshold` keeps looping until `CB_PERMISSION_DENIAL_THRESHOLD` opens the circuit breaker ### Auto-Recovery Cooldown After `CB_COOLDOWN_MINUTES` (default: 30) in OPEN state, the circuit auto-transitions to HALF_OPEN. From HALF_OPEN, if progress is detected, circuit goes to CLOSED; otherwise back to OPEN. Set `CB_AUTO_RESET=true` in `.ralph/.ralphrc` to bypass cooldown entirely and reset to CLOSED on startup. ### Circuit Breaker State Structure ```json { "state": "CLOSED|HALF_OPEN|OPEN", "consecutive_no_progress": 0, "consecutive_same_error": 0, "consecutive_permission_denials": 0, "last_progress_loop": 5, "total_opens": 0, "reason": "string (when OPEN)", "opened_at": "ISO-timestamp (when OPEN)", "current_loop": 10 } ``` ### Recovery To reset the circuit breaker: ```bash bash .ralph/ralph_loop.sh --reset-circuit ``` --- ## Exit Detection Ralph uses multiple mechanisms to detect when to exit the loop. ### Exit Conditions | Condition | Threshold | Description | |-----------|-----------|-------------| | Consecutive done signals | 2 | Exit on repeated completion signals | | Test-only loops | 3 | Exit if too many test-only iterations | | Fix plan complete | All [x] | Exit when all tasks are marked complete | | EXIT_SIGNAL + completion_indicators | Both | Dual verification for project completion | ### EXIT_SIGNAL Gate The `completion_indicators` exit condition requires dual verification: | completion_indicators | EXIT_SIGNAL | Result | |-----------------------|-------------|--------| | >= 2 | `true` | **Exit** ("project_complete") | | >= 2 | `false` | **Continue** (agent still working) | | >= 2 | missing | **Continue** (defaults to false) | | < 2 | `true` | **Continue** (threshold not met) | **Rationale:** Natural language patterns like "done" or "complete" can trigger false positives during productive work. By requiring an explicit `EXIT_SIGNAL` confirmation, Ralph avoids exiting mid-iteration. When the agent outputs `STATUS: COMPLETE` with `EXIT_SIGNAL: false`, the explicit `false` takes precedence. This allows marking a phase complete while indicating more phases remain. ### RALPH_STATUS Block The coding agent should include this status block at the end of each response: ``` ---RALPH_STATUS--- STATUS: IN_PROGRESS | COMPLETE | BLOCKED TASKS_COMPLETED_THIS_LOOP: 0 | 1 FILES_MODIFIED: TESTS_STATUS: PASSING | FAILING | NOT_RUN WORK_TYPE: IMPLEMENTATION | TESTING | DOCUMENTATION | REFACTORING EXIT_SIGNAL: false | true RECOMMENDATION: ---END_RALPH_STATUS--- ``` ### When to Set EXIT_SIGNAL: true Set EXIT_SIGNAL to **true** when ALL conditions are met: 1. All items in `@fix_plan.md` are marked `[x]` 2. All tests are passing (or no tests exist for valid reasons) 3. No errors or warnings in the last execution 4. All requirements from specs/ are implemented 5. Nothing meaningful left to implement ### Progress Detection Ralph detects progress through both uncommitted file changes AND git commits made within a loop. Before each loop, Ralph captures `git rev-parse HEAD`; if HEAD changes during the loop, committed files count as progress alongside working tree changes. --- ## Live Streaming Ralph supports real-time streaming output with the `--live` flag. ### Usage ```bash bash .ralph/ralph_loop.sh --live # Live streaming output bash .ralph/ralph_loop.sh --monitor --live # Live streaming with tmux monitoring ``` ### How It Works - Live mode switches the active driver to its structured streaming format and pipes the stream through `jq` - Cursor background loop execution stays on `json` output and switches to `stream-json` for live display - Claude Code also uses `stream-json` for live display, while Codex streams its native JSONL events directly - Shows text deltas and tool invocations in real-time - Requires `jq` and `stdbuf` (from coreutils); falls back to background mode if unavailable ### Monitoring Layout When using `--monitor` with `--live`, tmux creates a 3-pane layout: - **Left pane:** Ralph loop with live streaming - **Right-top pane:** `tail -f .ralph/live.log` (live driver output) - **Right-bottom pane:** status dashboard (`bmalph watch` when available) --- ## Troubleshooting ### Common Issues #### Ralph exits too early **Symptoms:** Loop stops before work is complete **Causes:** - EXIT_SIGNAL set to true prematurely - completion_indicators triggered by natural language - All `@fix_plan.md` items marked complete **Solutions:** 1. Ensure EXIT_SIGNAL is only true when genuinely complete 2. Add remaining tasks to `@fix_plan.md` 3. Check `.ralph/.response_analysis` for exit reasons #### Ralph doesn't exit when complete **Symptoms:** Loop continues with busywork **Causes:** - EXIT_SIGNAL not being set to true - `@fix_plan.md` has unmarked items - completion_indicators threshold not met **Solutions:** 1. Ensure RALPH_STATUS block is included in responses 2. Set EXIT_SIGNAL: true when all work is done 3. Mark all completed items in `@fix_plan.md` #### Circuit breaker opens unexpectedly **Symptoms:** "OPEN - stagnation detected" message **Causes:** - Same error recurring across loops - No file changes for multiple loops - Output volume declining significantly **Solutions:** 1. Check `.ralph/logs/` for the recurring error 2. Fix the underlying issue causing the error 3. Reset circuit breaker: `bash .ralph/ralph_loop.sh --reset-circuit` #### Permission denied blocks progress **Symptoms:** "OPEN - permission_denied" message **Causes:** - The active driver denied permission to run commands - `ALLOWED_TOOLS` in `.ralph/.ralphrc` too restrictive for Claude Code - The active non-Claude driver rejected a tool under its native permission model **Solutions:** 1. For Claude Code, update `ALLOWED_TOOLS` in `.ralph/.ralphrc` to include needed tools 2. For Claude Code unattended loops, keep `CLAUDE_PERMISSION_MODE="bypassPermissions"` in `.ralph/.ralphrc` 3. For codex, cursor, and copilot, review the driver's native permission settings; `ALLOWED_TOOLS` is ignored 4. If you want unattended behavior, keep `PERMISSION_DENIAL_MODE="continue"` in `.ralph/.ralphrc` 5. Reset circuit breaker if needed: `bash .ralph/ralph_loop.sh --reset-circuit` #### Session expires mid-project **Symptoms:** Context lost, session age > 24h **Causes:** - Long gaps between loop iterations - Session not being refreshed **Solutions:** 1. Sessions are designed to expire after 24h (configurable via `SESSION_EXPIRY_HOURS`) 2. Start a new session with `bash .ralph/ralph_loop.sh --reset-session` 3. Context will be rebuilt from `@fix_plan.md` and `specs/` #### Cursor preflight fails **Symptoms:** `bmalph doctor` or `bmalph run --driver cursor` fails before the loop starts **Causes:** - `command -v jq` fails in the bash environment Ralph uses - `command -v cursor-agent` fails in that same bash environment - `cursor-agent status` reports an authentication problem **Solutions:** 1. Run `command -v jq` in the same bash shell Ralph uses and install `jq` if missing 2. Run `command -v cursor-agent` and ensure the official Cursor CLI is on the bash `PATH` 3. Run `cursor-agent status` and sign in to Cursor before starting Ralph ### Diagnostic Commands ```bash # Check Ralph status bash .ralph/ralph_loop.sh --status # Check circuit breaker state bash .ralph/ralph_loop.sh --circuit-status # Reset circuit breaker bash .ralph/ralph_loop.sh --reset-circuit # Auto-reset circuit breaker (bypasses cooldown) bash .ralph/ralph_loop.sh --auto-reset-circuit # Reset session bash .ralph/ralph_loop.sh --reset-session # Enable live streaming bash .ralph/ralph_loop.sh --live # Live streaming with monitoring bash .ralph/ralph_loop.sh --monitor --live ``` ### Log Files Loop execution logs are stored in `.ralph/logs/`: - Each loop iteration creates a timestamped log file - Logs contain Claude's output and status information - Use logs to diagnose issues with specific iterations ### Status File Structure `.ralph/status.json`: ```json { "timestamp": "ISO-timestamp", "loop_count": 10, "calls_made_this_hour": 25, "max_calls_per_hour": 100, "last_action": "description", "status": "running|completed|halted|paused|stopped|success|graceful_exit|error", "exit_reason": "reason (if exited)", "next_reset": "timestamp for rate limit reset" } ``` `bmalph status` normalizes these raw bash values to `running`, `blocked`, `completed`, `not_started`, or `unknown`. --- ## Error Detection Ralph uses two-stage error filtering to eliminate false positives. ### Stage 1: JSON Field Filtering Filters out JSON field patterns like `"is_error": false` that contain the word "error" but aren't actual errors. ### Stage 2: Actual Error Detection Detects real error messages: - Error prefixes: `Error:`, `ERROR:`, `error:` - Context-specific: `]: error`, `Link: error` - Occurrences: `Error occurred`, `failed with error` - Exceptions: `Exception`, `Fatal`, `FATAL` ### Multi-line Error Matching Ralph verifies ALL error lines appear in ALL recent history files before declaring a stuck loop, preventing false negatives when multiple distinct errors occur. --- ## Further Reading - [BMAD-METHOD Documentation](https://github.com/bmad-code-org/BMAD-METHOD) - [Ralph Repository](https://github.com/snarktank/ralph)