Minimal loop runner for Claude Code or Codex CLI. Ralph executes an agentic loop that works through a PRD (Product Requirements Document) one task at a time, committing progress as it goes.
- Video: Ralph in Action
- Article: The Ralph Pattern
- Anthropic: Effective Harnesses for Long-Running Agents
Ralph implements a simple but effective pattern for long-running AI agents:
┌─────────────────────────────────────────────────────────┐
│ Ralph Loop │
├─────────────────────────────────────────────────────────┤
│ │
│ 1. Read PRD (prd.json) │
│ ↓ │
│ 2. Pick highest-priority incomplete task │
│ ↓ │
│ 3. Implement the task │
│ ↓ │
│ 4. Run tests/typecheck │
│ ↓ │
│ 5. Update PRD (mark task complete) │
│ ↓ │
│ 6. Append notes to progress.txt │
│ ↓ │
│ 7. Git commit │
│ ↓ │
│ 8. Sleep, then repeat from step 1 │
│ (until PRD complete or stopped) │
│ │
└─────────────────────────────────────────────────────────┘
Each iteration is a fresh context—the agent reads the current state from files, does one unit of work, persists its progress, and exits. This prevents context bloat and makes the process resumable.
Ralph builds the final prompt by layering multiple sources:
┌─────────────────────────────────────┐
│ 1. Base Prompt │ ← RALPH_PROMPT_FILE, or ./prompt.md, or built-in default
├─────────────────────────────────────┤
│ 2. Session Prompt (if using session)│ ← .agent/sessions/<name>/prompt.md
├─────────────────────────────────────┤
│ 3. Append File (if set) │ ← RALPH_PROMPT_APPEND_FILE
└─────────────────────────────────────┘
File paths in the prompt use the @/path/to/file syntax that Claude Code and Codex recognize for file references.
Install the global ralph wrapper:
./install.shThen use it from any repo:
# Simple mode: uses ./prompt.md or built-in prompt
ralph claude
# or
ralph codexStop with Ctrl+C, or create .agent/STOP.
Sessions keep your PRD, progress, and prompt organized per feature/project.
ralph init feature-xThis creates:
.agent/sessions/feature-x/
├── spec.md # Combined: specs + task list + acceptance criteria
├── progress.txt # Append-only log of work done
└── prompt.md # Session-specific instructions and context anchors
spec.md - Combined spec and task list:
# Session: Auth Flow
## Overview
Implement user authentication with email/password login.
## Context & Requirements
- JWT-based session management
- Password must be hashed with bcrypt
- Failed logins rate-limited after 5 attempts
## Tasks
### ⬜ Task: add-login-form
**Priority:** high
**Status:** incomplete
Users can sign in with email/password.
**Acceptance:**
- [ ] Form renders on /login
- [ ] Invalid credentials show error
- [ ] Successful login redirects to /dashboard
---prompt.md - Context anchors and instructions:
# Context Anchors (read these first)
These files contain the source of truth:
- `spec.md` - session spec with all tasks
- `specs/auth.md` - authentication requirements
- `src/services/auth.ts` - existing auth code
# Build Commands
- TypeScript: `pnpm typecheck`
- Tests: `pnpm test --bail` (only show failures)
# Scope
- Focus on `src/auth/` directory
- Do NOT modify database schemaralph --session feature-x claude
# or
ralph --session feature-x codexralph --session feature-x --once clauderalph listEach run creates a single combined markdown file:
.agent/logs/claude_20260105_120000.md
The file contains:
- Prompt (only if changed from previous run)
- Transcript (full JSON stream of all tool calls and responses)
- Summary (for Codex runs)
For sessions, logs go to .agent/sessions/<name>/logs/.
Log management:
- Prompts are deduplicated (only saved when changed)
- Old logs (>1 day) are automatically compressed with gzip
- Use
ralph cleanto manually clean up
# Clean logs in default directory
ralph clean
# Clean logs for a specific session
ralph clean --session feature-x| Variable | Description | Default |
|---|---|---|
RALPH_PROMPT_FILE |
Override base prompt file | ./prompt.md |
RALPH_PROMPT_APPEND_FILE |
Append extra instructions | (none) |
RALPH_SPEC_FILE |
Override spec.md path | ./spec.md or session spec |
RALPH_PROGRESS_FILE |
Override progress path | ./progress.txt |
RALPH_SESSION |
Default session name | (none) |
RALPH_SLEEP_SECONDS |
Sleep between iterations | 10 |
RALPH_MAX_ITERATIONS |
Max iterations before stopping | (unlimited) |
RALPH_PROMISE_PATTERN |
Completion marker | <promise>COMPLETE</promise> |
RALPH_SUPERVISOR_SCRIPT |
Executable script to check iterations | (none) |
RALPH_SUPERVISOR_NUDGE |
Nudge prompt when check fails | (none) |
RALPH_NOTIFY |
macOS notification on completion | 0 |
RALPH_NOTIFY_CMD |
Custom command on completion | (none) |
RALPH_COMPRESS_LOGS |
Gzip logs immediately after each run | 0 |
Caution: Claude runs with
bypassPermissionsby default, which skips all permission prompts so the agent can run autonomously. If you're concerned about security, setRALPH_CLAUDE_PERMISSION_MODE=defaultto restore interactive approval prompts.
| Variable | Description | Default |
|---|---|---|
RALPH_CLAUDE_OUTPUT_FORMAT |
Output format | stream-json |
RALPH_CLAUDE_PERMISSION_MODE |
Permission mode | bypassPermissions |
RALPH_CLAUDE_PRETTY |
Pretty print results | 1 |
RALPH_CLAUDE_PARTIAL |
Include partial messages | 0 |
Caution: Codex runs in YOLO mode by default (
--yolo), which bypasses all approval prompts and sandboxing. This gives the agent full system access. If you're concerned about security, disable it withRALPH_CODEX_YOLO=0to use approval and sandbox controls instead.
| Variable | Description | Default |
|---|---|---|
RALPH_CODEX_YOLO |
Bypass approvals/sandbox | 1 |
RALPH_CODEX_APPROVAL |
Approval mode (when YOLO=0) | never |
RALPH_CODEX_SANDBOX |
Sandbox mode (when YOLO=0) | workspace-write |
ralph <claude|codex> # Run loop
ralph --once <claude|codex> # Single iteration
ralph --session <name> <claude|codex> # Run with session
ralph --iterations <n> <claude|codex> # Limit iterations
ralph --prd /path/to/spec.md <cli> # Override spec path
ralph --progress /path/to/progress.txt <cli> # Override progress path
ralph init <name> # Create session
ralph list # List sessions
ralph clean # Clean logs (remove empty, compress old)
ralph clean --session <name> # Clean session logs- Ralph stops when the agent outputs
<promise>COMPLETE</promise> - Set
RALPH_MAX_ITERATIONSor--iterations <n>to cap runs - Create
.agent/STOP(or.agent/sessions/<name>/STOP) to stop gracefully
Ralph supports an optional supervisor pattern for checking that iterations completed expected work:
┌─────────────────────────────────────────────────────────┐
│ Supervisor Loop │
├─────────────────────────────────────────────────────────┤
│ │
│ 1. Run main Ralph iteration │
│ ↓ │
│ 2. Check completion via supervisor script │
│ ↓ │
│ 3. If check fails → Run nudge iteration │
│ (one-off with supervisor prompt appended) │
│ ↓ │
│ 4. Continue main loop │
│ │
└─────────────────────────────────────────────────────────┘
Example use case: Ensure translations are updated after each feature.
- Create supervisor check script (
.agent/sessions/myapp/supervisor.sh):
#!/bin/bash
# Check if translations were updated
LOG_FILE="$1"
# Parse what files were modified from the log
if ! grep -q "i18n/translations" "$LOG_FILE"; then
echo "Missing: translations not updated"
exit 1 # Needs nudge
fi
exit 0 # All good- Create nudge prompt (
.agent/sessions/myapp/supervisor-nudge.md):
# Supervisor Check: Translations Missing
The previous iteration completed but did not update translations.
Please:
1. Add translations to `i18n/translations/en.json` for any new UI text
2. Verify translations are complete
3. Commit the translation updates- Run with supervisor:
export RALPH_SUPERVISOR_SCRIPT=.agent/sessions/myapp/supervisor.sh
export RALPH_SUPERVISOR_NUDGE=.agent/sessions/myapp/supervisor-nudge.md
ralph --session myapp claudeThe supervisor script examines the log after each successful iteration. If it returns non-zero, Ralph runs one additional iteration with the nudge prompt to fix the issue.
Ralph's effectiveness depends on efficient context usage. Understanding token limits helps you stay in the "smart zone."
- Total context: ~200k tokens
- Model overhead: ~16k tokens
- Harness overhead: ~16k tokens
- Usable context: ~176k tokens (~136KB text, or 1-2 movie scripts)
As the context window fills, model performance degrades. Signs you're in the "dumb zone":
- Model forgets earlier instructions
- Test fixing becomes scrambling/flailing
- Repeated attempts at the same fix
- Forgetting what task it was working on
Mitigations:
- Keep each task small - One feature = one iteration (Ralph handles this by design)
- Minimize test output - Only show failing tests, not full passing logs
- Keep prompts concise - Session
prompt.mdshould be <100 lines - Use deliberate malicking - Explicitly mention file paths to anchor context
Most test runners output too many tokens. Configure yours to only show failures:
# Example: wrapper script that filters test output
# .agent/test-wrapper.sh
#!/bin/bash
pnpm test --bail 2>&1 | grep -A10 "FAIL\|Error\|✗" || echo "All tests passed"Then in your session prompt.md:
# Build Commands
- Tests: `./.agent/test-wrapper.sh` (only shows failures)Token savings: A full test suite with 200 passing tests can output 50k+ tokens. Filtered output: <5k tokens.
"Malicking" = deliberately allocating context. The first ~5k tokens of each iteration should anchor critical context:
# Context Anchors (read these first)
- `spec.md` - all tasks and acceptance criteria
- `specs/api-contract.md` - API requirements
- `src/services/auth.ts` - existing implementationWhy this works: Mentioning file paths by name triggers the model to read them at the start of iteration, ensuring they stay in the "smart zone" rather than being compressed or forgotten.
Ralph works best with observation-driven tuning rather than constant intervention:
- Watch like a fireplace - Let iterations run and observe patterns
- Notice behaviors - What does it do repeatedly? What does it miss?
- Tune your specs - If it keeps making the same mistake, the spec is wrong
- Never blame the model - Garbage in = garbage out
| Observation | Likely Cause | Fix |
|---|---|---|
| Forgets translations every time | Not in acceptance criteria | Add to task acceptance: - [ ] Translations updated |
| Verbose test output causes confusion | Default test runner | Add filtered test wrapper script |
| Repeats same fix attempt | Ambiguous spec | Make spec more specific and testable |
| Skips certain file types | Not mentioned in context | Add to context anchors in prompt.md |
| Works on multiple tasks per iteration | Unclear instructions | Emphasize "ONE task" in session prompt |
- Human IN the loop: Model asks permission for each action (slow, interrupts flow)
- Human ON the loop: Model runs autonomously, human observes and tunes (Ralph's design)
You are the orchestrator. Ralph is the inner loop. You tune:
- Task granularity (how big each task is)
- Acceptance criteria (what "done" means)
- Context anchors (what files to read)
- Supervisor checks (what to verify)
Some patterns you might discover:
- Opus doesn't have context window anxiety (unlike earlier models)
- Opus can be forgetful about certain categories of work
- Test runner output bloat is the #1 cause of context issues
- One bad spec line = 10,000 lines of wrong code
The fireplace mindset: Treat Ralph like a live stream you check in on. Watch for patterns, notice when behavior changes, ask yourself why—then tune the specs and prompts accordingly.
The ralph-planner skill helps shape work into PRD tasks without running Ralph:
# Install to Claude Code
cp -r skills/ralph-planner ~/.claude/skills/
# Install to Codex
cp -r skills/ralph-planner ~/.codex/skills/Then invoke with /ralph-planner in Claude Code or Codex.
After pulling changes:
./install.shThis re-copies ralph.sh to ~/.local/share/ralph/ralph.sh.
- Claude Code CLI (for
claudemode) - Codex CLI (for
codexmode) jq(optional, for pretty-printed Claude output)