Ralph Loop Primer¶
Give this document to an AI agent to quickly set up a Ralph loop for any project.
What is a Ralph Loop?¶
Ralph is an autonomous AI coding loop that ships features incrementally while you work on other things (or sleep).
Key Concept: Instead of one massive prompt, Ralph: - Works on small, well-defined user stories one at a time - Uses a fresh context window each iteration (stays lightweight) - Persists memory through git commits, JSON files, and learnings - Learns patterns and improves as it goes - Runs tests/typecheck after each story - Only commits when tests pass
The Loop:
for i in $(seq 1 MAX_ITERATIONS); do
cat prompt.md | claude-code
# If all stories complete, exit
if grep -q "<promise>COMPLETE</promise>"; then exit 0; fi
done
When to Use Ralph Loops¶
✅ Good for: - Building features with clear acceptance criteria - Repetitive implementations following patterns - Projects with good test coverage - Learning by watching AI work incrementally - Non-critical/experimental code
❌ Bad for: - Exploratory work without clear criteria - Security-critical code - Major refactors without clear goals - Anything needing human judgment - Production code without review
File Structure¶
scripts/ralph/
├── ralph.sh # The loop script
├── prompt.md # Instructions for each iteration
├── prd.json # User stories and status
└── progress.txt # Learnings log
Template Files¶
1. ralph.sh¶
#!/bin/bash
set -e
MAX_ITERATIONS=${1:-10}
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
echo "🚀 Starting Ralph loop"
for i in $(seq 1 $MAX_ITERATIONS); do
echo "═══ Iteration $i/$MAX_ITERATIONS ═══"
OUTPUT=$(cat "$SCRIPT_DIR/prompt.md" \
| claude code --dangerously-skip-permissions 2>&1 \
| tee /dev/stderr) || true
if echo "$OUTPUT" | grep -q "<promise>COMPLETE</promise>"; then
echo "✅ All stories complete!"
exit 0
fi
sleep 2
done
echo "⚠️ Max iterations reached without completion"
exit 1
Make it executable:
chmod +x scripts/ralph/ralph.sh
Usage:
./scripts/ralph/ralph.sh 25 # Run up to 25 iterations
2. prompt.md¶
# Ralph Agent Instructions
You are Ralph, an autonomous coding agent. Work on ONE story at a time.
## Your Task (Each Iteration)
1. Read `scripts/ralph/prd.json` to see all user stories
2. Read `scripts/ralph/progress.txt` to learn from previous iterations
- Check **Codebase Patterns** section first
3. Verify you're on the correct branch (from prd.json)
4. Pick the highest priority story where `passes: false`
5. Implement ONLY that ONE story
6. Run tests and typecheck:
- `npm run typecheck` (or equivalent)
- `npm test` (or pytest, go test, etc.)
7. If tests pass:
- Commit with message: `feat: [STORY-ID] - [Story Title]`
- Update prd.json: set `passes: true` for that story
- Append learnings to progress.txt (see format below)
8. If tests fail:
- Fix the issues
- Try again
- Log what you learned
## Progress Log Format
APPEND to `scripts/ralph/progress.txt`:
[Date] - [Story ID]: [Title]¶
- What was implemented: Brief description
- Files changed: List of files
- Learnings:
- Patterns discovered
- Gotchas encountered
- Dependencies found
## Codebase Patterns Section
At the TOP of progress.txt, maintain a "Codebase Patterns" section:
Codebase Patterns¶
- When modifying X, also update Y
- Tests require Z to be running
- Use pattern A for feature B
Update this when you discover reusable patterns. ## Stop Condition If ALL user stories have `passes: true`, reply ONLY:COMPLETE Otherwise, end your turn normally after implementing one story. ## Important Rules - ONE story per iteration - Always run tests before committing - Keep stories small (fits in one context window) - Learn from progress.txt - Commit only when tests pass - Be explicit in learnings
3. prd.json¶
{
"branchName": "ralph/feature-name",
"userStories": [
{
"id": "US-001",
"title": "Descriptive title",
"acceptanceCriteria": [
"Specific requirement 1",
"Specific requirement 2",
"Tests pass",
"Typecheck passes"
],
"priority": 1,
"passes": false,
"notes": "Optional context or constraints"
},
{
"id": "US-002",
"title": "Next feature",
"acceptanceCriteria": [
"Clear, testable criteria",
"Builds on US-001"
],
"priority": 2,
"passes": false,
"notes": ""
}
]
}
Important:
- branchName - Git branch to work on
- priority - Lower number = done first
- passes - Set to true when story is complete
- Keep stories SMALL (one context window each)
4. progress.txt¶
# Ralph Progress Log
Started: [Date]
Project: [Project Name]
## Codebase Patterns
(Ralph will populate patterns here as it learns)
## Key Files
(Ralph will document important files here)
---
(Ralph appends learnings after each story below)
Writing Good User Stories¶
❌ Too Vague:¶
{
"title": "Add authentication",
"acceptanceCriteria": ["Users can log in"]
}
✅ Clear and Explicit:¶
{
"title": "Add login form component",
"acceptanceCriteria": [
"Form has email and password fields",
"Email field validates format",
"Shows error message on invalid input",
"Submits to /api/login endpoint",
"Tests pass for validation logic",
"Component renders at /login route"
]
}
❌ Too Big:¶
{
"title": "Build entire authentication system"
}
✅ Right Size (break into multiple stories):¶
[
{"id": "US-001", "title": "Add login form UI"},
{"id": "US-002", "title": "Add login API endpoint"},
{"id": "US-003", "title": "Add session management"},
{"id": "US-004", "title": "Add logout functionality"}
]
Best Practices¶
- Start Small: 3-5 stories for your first Ralph loop
- Clear Criteria: Every story needs testable acceptance criteria
- Fast Feedback: Must have automated tests (unit tests, typecheck, linters)
- One Story = One Commit: Keep commits focused
- Review Everything: Ralph is autonomous but you still review/merge
- Learn from Failures: If Ralph gets stuck, improve the story criteria
- Compound Learning: Later stories benefit from earlier learnings
Quick Start Guide¶
Step 1: Create the Structure¶
mkdir -p scripts/ralph
cd scripts/ralph
Step 2: Create Files¶
- Create
ralph.sh(use template above) - Create
prompt.md(use template above) - Create
prd.jsonwith your user stories - Create empty
progress.txtwith header
Step 3: Prepare Your Project¶
# Make sure you have tests
npm test # or pytest, go test, etc.
# Make sure typecheck works
npm run typecheck # or tsc, mypy, etc.
# Create the feature branch
git checkout -b ralph/your-feature
Step 4: Run Ralph¶
chmod +x scripts/ralph/ralph.sh
./scripts/ralph/ralph.sh 20 # Run up to 20 iterations
Step 5: Monitor Progress¶
# Check story status
cat scripts/ralph/prd.json | jq '.userStories[] | {id, passes}'
# Read learnings
cat scripts/ralph/progress.txt
# See commits
git log --oneline -10
Step 6: Review and Merge¶
# Review all changes
git diff main
# Run tests yourself
npm test && npm run typecheck
# Merge when satisfied
git checkout main
git merge ralph/your-feature
Monitoring a Running Ralph Loop¶
While Ralph is running, you can:
# Watch git commits in real-time
watch -n 5 'git log --oneline -5'
# Monitor progress file
tail -f scripts/ralph/progress.txt
# Check JSON status
watch -n 10 'cat scripts/ralph/prd.json | jq ".userStories[] | {id, title, passes}"'
Troubleshooting¶
Ralph Gets Stuck on One Story¶
- Story criteria might be too vague
- Tests might be flaky
- Check progress.txt for errors
- Manually fix and let Ralph continue
Ralph Completes Too Fast Without Actually Working¶
- Acceptance criteria not specific enough
- Missing test validation
- Add more explicit criteria
Tests Keep Failing¶
- Story might be too complex
- Break into smaller stories
- Check if dependencies are correct
Ralph Changes Wrong Files¶
- Criteria too broad
- Add constraints: "Only modify files in src/components/"
- Be explicit about scope
Example Ralph Loop Projects¶
Example 1: CLI Tool¶
{
"branchName": "ralph/cli-tool",
"userStories": [
{
"id": "US-001",
"title": "Add argument parser",
"acceptanceCriteria": [
"Accepts --input and --output flags",
"Shows help with --help",
"Tests pass"
]
},
{
"id": "US-002",
"title": "Add file reading function",
"acceptanceCriteria": [
"Reads file from --input path",
"Handles file not found error",
"Returns file contents",
"Unit tests pass"
]
}
]
}
Example 2: Web Feature¶
{
"branchName": "ralph/search-feature",
"userStories": [
{
"id": "US-001",
"title": "Add search input component",
"acceptanceCriteria": [
"Input field with placeholder",
"Debounces input (500ms)",
"Emits onChange event",
"Component tests pass"
]
},
{
"id": "US-002",
"title": "Add search API endpoint",
"acceptanceCriteria": [
"GET /api/search?q=query",
"Returns JSON array of results",
"Handles empty query",
"API tests pass"
]
}
]
}
Tips for Security/Pentesting Projects¶
Since you work in security/pentesting:
⚠️ Special Considerations: - Always review Ralph's code before running it - Don't use Ralph for client/production pentesting - Perfect for personal tools and CTF practice - Add security checks to acceptance criteria: - "No hardcoded credentials" - "Validates all user input" - "Doesn't execute arbitrary commands"
Good Ralph Projects for Pentesting: - Enumeration script wrappers - Report generators - Log parsers - CTF toolkit utilities - Practice exploit development - Automation scripts for HTB/TryHackMe
Bad Ralph Projects for Pentesting: - Actual client engagement tools - Security-critical components - Exploit chains (too complex/sensitive)
Ready to Build?¶
When you're ready to create a Ralph loop, provide: 1. Project description: What are you building? 2. Language/framework: Python, Go, Node.js, etc. 3. Test setup: What test command? (pytest, npm test, go test) 4. Feature goal: What should the end result do?
The AI will help you: - Break it into user stories - Create the file structure - Write initial tests - Set up the Ralph loop - Monitor progress
Reference: Original Ralph Loop Article¶
Key points from the Ralph loop concept: - Autonomous coding while you sleep - Fresh context window each iteration - Memory through git + text files - Learns patterns as it goes - 13 stories ~= 15 iterations ~= 1 hour - By story 10, Ralph knows your patterns
Remember: Ralph is a tool, not magic. You still: - Define the stories - Review the code - Merge when satisfied - Learn from watching it work