An autonomous AI coding loop that ships features while you sleep.
Ralph runs your AI coding agent (Claude Code, Amp, OpenCode, Codex) repeatedly until all tasks in your PRD are complete. Each iteration is a fresh context window, with memory persisting via git history and text files.
Based on the Ralph methodology by Geoffrey Huntley.
curl -fsSL https://raw.githubusercontent.com/kylemclaren/ralph/main/install.sh | sh# Using go install
go install github.com/kylemclaren/ralph/cmd/ralph@latest
# Or clone and build
git clone https://github.com/kylemclaren/ralph.git
cd ralph
mise run build# Initialize Ralph in your project
ralph init
# Add user stories to the PRD
ralph add -t "Add login form" -p 1 -a "Email field validates" -a "Password field works"
ralph add -t "Add authentication" -p 2 -a "JWT tokens generated" -a "Session persists"
# Check status
ralph status
# Run the loop
ralph runRalph implements a simple but powerful pattern:
- Read the PRD and find the highest priority pending story
- Execute your AI agent with a prompt containing the PRD and progress log
- Agent implements the story, runs tests, commits, and marks it done
- Check if all stories are complete
- Repeat until done or max iterations reached
Memory persists between iterations through:
- Git commits - Each story = one commit
- progress.txt - Learnings and patterns discovered
- prd.json - Task status tracking
| Command | Description |
|---|---|
ralph init |
Initialize Ralph in your project |
ralph status |
Show PRD status with progress bar |
ralph add |
Add a user story (interactive or via flags) |
ralph edit <id> |
Edit an existing story |
ralph done <id> |
Mark a story as complete |
ralph reset <id> |
Reset a story to pending |
ralph delete <id> |
Delete a story |
ralph prompt |
View/edit/render the prompt template |
ralph log |
View/edit the progress log |
ralph run |
Start the Ralph loop |
ralph stop |
Stop a running Ralph loop gracefully |
ralph version |
Print version information |
Ralph supports configuration via file, environment variables, and CLI flags (in order of precedence: flags > env > file).
agent:
type: claude-code # claude-code, amp, opencode, codex, custom
command: "" # custom command (only if type: custom)
flags: [] # additional flags
timeout: 30m # max time per iteration
loop:
maxIterations: 25
sleepBetween: 2s
stopOnFirstFailure: false
paths:
prd: .ralph/prd.json
progress: .ralph/progress.txt
prompt: .ralph/prompt.md
hooks:
enabled: true
onStart: []
onIteration: []
onComplete: []
onFailure: []All config options can be set via environment variables with the RALPH_ prefix:
export RALPH_AGENT_TYPE=claude-code
export RALPH_LOOP_MAXITERATIONS=50ralph run --max-iterations 10 --agent claude-code| Agent | Command |
|---|---|
| claude-code | claude --dangerously-skip-permissions |
| amp | amp --dangerously-allow-all |
| opencode | opencode |
| codex | codex |
| custom | User-defined command |
The PRD (Product Requirements Document) is a JSON file containing user stories:
{
"branchName": "ralph/feature",
"userStories": [
{
"id": "US-001",
"title": "Add login form",
"description": "Create a login form with email and password fields",
"acceptanceCriteria": [
"Email field with validation",
"Password field with show/hide toggle",
"Submit button disabled until valid",
"typecheck passes",
"tests pass"
],
"priority": 1,
"passes": false,
"notes": ""
}
]
}For more control, run Ralph one iteration at a time:
ralph run --onceThis lets you review each change before continuing.
See what Ralph would do without executing:
ralph run --dry-runRun custom commands at different stages:
hooks:
enabled: true
onStart:
- "git checkout -b ralph/feature"
onIteration:
- "npm run lint"
onComplete:
- "./notify.sh 'Ralph finished!'"
onFailure:
- "./notify.sh 'Ralph failed'"Hook environment variables:
RALPH_ITERATION- Current iteration numberRALPH_STORY_ID- Current story IDRALPH_HOOK- Hook type being executed
Ralph exposes its state via environment variables that Claude Code hooks can access. This allows Claude Code's PreToolUse, PostToolUse, UserPromptSubmit, and other hooks to be aware of Ralph's context.
When Ralph executes Claude Code, these environment variables are set:
| Variable | Description |
|---|---|
RALPH_ACTIVE |
"true" when Ralph is running |
RALPH_ITERATION |
Current iteration number |
RALPH_MAX_ITERATIONS |
Maximum iterations configured |
RALPH_STORY_ID |
Current story ID (e.g., "US-001") |
RALPH_STORY_TITLE |
Current story title |
RALPH_BRANCH |
Git branch from PRD |
RALPH_PRD_PATH |
Path to PRD file |
RALPH_PROGRESS_PATH |
Path to progress file |
RALPH_PROMPT_PATH |
Path to prompt file |
RALPH_TOTAL_STORIES |
Total number of stories |
RALPH_DONE_STORIES |
Completed stories count |
RALPH_PENDING_STORIES |
Pending stories count |
RALPH_AGENT_TYPE |
Agent type (claude-code, amp, etc.) |
Create a hook in .claude/settings.json:
{
"hooks": {
"UserPromptSubmit": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "if [ \"$RALPH_ACTIVE\" = \"true\" ]; then echo \"Ralph iteration $RALPH_ITERATION: Working on $RALPH_STORY_ID\"; fi"
}
]
}
]
}
}The environment variables are set for all agents, not just Claude Code. This means:
- Amp, OpenCode, Codex, and custom agents also receive these variables
- Hook scripts can check
RALPH_AGENT_TYPEto behave differently per agent - Third-party tools can integrate with Ralph by reading these variables
Stories should fit in a single context window. Break large features into smaller pieces:
Bad: "Build entire auth system"
Good: "Add login form"
"Add email validation"
"Add auth server action"
"Add session management"
Be specific and testable:
Bad: "Users can log in"
Good: "Email field validates format"
"Password requires 8+ characters"
"Error message shows on invalid credentials"
"typecheck passes"
"tests pass"
Always include verification criteria:
typecheck passestests passnpm run lint passes
Ralph appends learnings to progress.txt. By story 10, it knows patterns from stories 1-9.
After ralph init:
your-project/
├── ralph.yaml # Configuration
└── .ralph/
├── prd.json # User stories
├── progress.txt # Progress log
└── prompt.md # Agent prompt template
Ralph stops when:
- All stories have
passes: true - Max iterations reached
- Agent outputs
<promise>COMPLETE</promise>
MIT
