ONE feature per iteration. Test thoroughly. Leave clean.
# In your project directory:
# 1. Create wrapper script
cat > ralph-local.sh << 'EOF'
#!/bin/bash
RALPH_DIR="$HOME/code/ralph"
AGENT_PROMPT_FILE="$RALPH_DIR/AGENT_PROMPT.md" \
"$RALPH_DIR/ralph.sh" "$@"
EOF
chmod +x ralph-local.sh
# 2. Create .ralph directory
mkdir -p .ralph && echo ".ralph/" >> .gitignore
# 3. Create PRD and progress
cp $RALPH_DIR/prd.json.template .ralph/prd.json
echo "=== Progress ===" > .ralph/progress.txt
# 4. Run Ralph!
./ralph-local.shHuman-in-the-Loop (Default):
./ralph.sh- Runs ONE iteration then stops
- Review changes after each iteration
- Run again when ready
Continuous AFK Mode:
RUN_MODE=continuous ./ralph.sh- Runs until all features complete
- Great for overnight runs
pwd # Where am I?
cat .ralph/progress.txt | tail -50 # What happened recently?
git log --oneline -20 # What commits were made?
cat .ralph/prd.json # What features remain?# If .ralph/init.sh exists:
./.ralph/init.sh # Start dev server
# Otherwise use standard project commands:
npm run dev # or pnpm dev, etc.Note: .ralph/init.sh is optional for existing projects.
- Run basic smoke tests
- If broken, fix immediately
- Don't start new work on broken code
- Find
"passes": falsein.ralph/prd.json - Choose highest priority
- State: "I am working on: [feature]"
- Write clean code
- Follow existing patterns
- Add error handling
- Document complex logic
# Type checking
npm run typecheck
# Tests
npm test
# Linting
npm run lint
# Browser automation (for web apps)
# Use Playwright/Puppeteer to test as user wouldOnly if fully verified AND all quality gates pass:
"passes": false → "passes": true
"iterations_taken": 0 → "iterations_taken": 1Quality Gates that MUST pass:
- ✅ Code formatting (prettier/black)
- ✅ Linting (eslint/pylint) - BLOCKING
- ✅ Type checking (tsc/mypy) - BLOCKING
- ✅ Test suite - BLOCKING
- ✅ Test coverage - BLOCKING for feature/bug types
- Features MUST have tests
- Bugs MUST follow TDD red-green workflow
Append to .ralph/progress.txt:
--- [Date/Time] ---
Feature: [description]
Implementation: [what was built]
Testing: [what was verified]
Challenges: [issues and solutions]
Next: [suggestions]
---
git add -A
git commit -m "feat: [clear feature description]"grep '"passes": false' .ralph/prd.jsonIf none found, output: PROMISE COMPLETE
- Work on ONE feature only
- Test before marking complete
- Leave code working and clean
- Update .ralph/progress.txt
- Make git commit
- Verify with actual testing (browser/API/unit)
- Multiple features at once
- Mark complete without testing
- Edit feature descriptions in .ralph/prd.json
- Leave broken code
- Skip commits
- Overwrite .ralph/progress.txt (append only)
- Assume code works without verification
// Use browser automation
await page.goto("http://localhost:3000");
await page.click('[data-testid="add-button"]');
await page.fill('input[name="todo"]', "Test todo");
await page.click('button[type="submit"]');
expect(await page.textContent(".todo-list")).toContain("Test todo");# Test endpoints
curl -X POST http://localhost:3000/api/todos \
-H "Content-Type: application/json" \
-d '{"title":"Test"}'
# Verify response
# Check status code
# Verify data// Unit tests
import { myFunction } from "./myModule";
expect(myFunction("input")).toBe("expected output");- Read error messages
- Fix the issue
- Verify fix works
- Continue with feature
git log- when did it break?git diff- what changed?- Fix the regression
- Verify with tests
- Commit fix
- Document blocker in .ralph/progress.txt
- Leave
"passes": false - Try different feature
- Leave clear notes
- Complete current feature if close
- Otherwise, reach clean stopping point
- Commit work
- Detailed .ralph/progress.txt notes
- Next session continues
- One commit per feature
- Decreasing false count in .ralph/prd.json
- Detailed progress notes
- Tests passing
- Clean git history
- Multiple commits per feature
- Stale .ralph/progress.txt
- Failing tests
- Vague commit messages
- Commented-out code
- ✅ "User can click 'Add' button and see todo form"
- ✅ "API returns 400 for invalid email format"
- ✅ "Navigation highlights active page"
- ❌ "Implement authentication" (too broad)
- ❌ "Make it look nice" (not testable)
- ❌ "Fix bugs" (not specific)
# Check remaining features
grep -c '"passes": false' .ralph/prd.json
# View recent progress
tail -50 .ralph/progress.txt
# See what's changed
git diff
# Undo uncommitted changes
git checkout .
# View specific commit
git show HEAD
# Run all checks
npm run typecheck && npm test && npm run lint# Run mode
RUN_MODE=once # Default: one iteration then stop
RUN_MODE=continuous # Run until complete or max iterations
# Max iterations (continuous mode only)
MAX_ITERATIONS=100 # Default: 100
# AI agent mode
AI_AGENT_MODE=claude # Default: use Claude API
AI_AGENT_MODE=manual # Manual: interactive prompts# Protected branches (default: main,master)
PROTECTED_BRANCHES="main,master"
# Auto-create feature branches (default: true)
AUTO_CREATE_BRANCH=true
# Allow git push (default: false - safety first!)
ALLOW_GIT_PUSH=false# Auto-fix prettier formatting (default: true)
AUTOFIX_PRETTIER=true
# Rollback on failure (default: true)
ROLLBACK_ON_FAILURE=true
# Verify before complete (default: true)
VERIFY_BEFORE_COMPLETE=true
# Test output mode (default: failures)
TEST_OUTPUT_MODE=failures # Show only failing tests
TEST_OUTPUT_MODE=summary # Show only stats
TEST_OUTPUT_MODE=full # Show everything# Log level (default: INFO)
LOG_LEVEL=DEBUG # Most verbose
LOG_LEVEL=INFO # Normal (default)
LOG_LEVEL=WARN # Warnings + errors only
LOG_LEVEL=ERROR # Errors only
# Persistent logging
LOG_FILE=".ralph/ralph.log"
# Progress header (default: true)
SHOW_PROGRESS_HEADER=true# PRD storage mode (default: file)
PRD_STORAGE=file # Use local .ralph/prd.json
PRD_STORAGE=sanity # Use Sanity CMS (requires config)
# Custom PRD file path
PRD_FILE=".ralph/prd.json"
# Custom progress file path
PROGRESS_FILE=".ralph/progress.txt"
# Sanity configuration (when PRD_STORAGE=sanity)
SANITY_PROJECT_ID="your-project-id"
SANITY_DATASET="production"
SANITY_TOKEN="your-write-token"# Help
./ralph.sh --help
# Verbose mode (LOG_LEVEL=DEBUG)
./ralph.sh --verbose
# Quiet mode (LOG_LEVEL=ERROR)
./ralph.sh --quiet
# Health check
./ralph.sh --doctor
# Custom branch name (auto-creation)
./ralph.sh --branch-name my-custom-branch{
"project": "Project Name",
"description": "Project description",
"schema_version": "2.0",
"features": [
{
"id": "001",
"type": "feature", // feature|bug|refactor|test|spike
"category": "functional", // setup|infrastructure|functional|testing|quality|documentation
"priority": "critical", // critical|high|medium|low
"description": "Feature description",
"estimated_complexity": "small", // small|medium|large
"depends_on": [], // Array of feature IDs
"passes": false, // true when complete
"iterations_taken": 0, // Auto-tracked
"blocked_reason": null, // Explanation if blocked
"test_files": [ // Optional: required test files
"tests/my-feature.test.js"
],
"acceptance_criteria": { // Optional: structured testing
"unit_tests": ["tests/unit/foo.test.js"],
"e2e_tests": ["tests/e2e/bar.test.js"],
"manual_checks": ["Verify UI displays correctly"]
}
}
]
}Field Meanings:
- type:
feature(new),bug(fix),refactor(improve),test(add tests),spike(research) - category:
setup,infrastructure,functional,testing,quality,documentation - priority:
critical,high,medium,low - estimated_complexity:
small(<1hr),medium(1-3hrs),large(>3hrs) - depends_on: Feature IDs that must be complete first
- test_files: Optional array of test files to verify exist
- acceptance_criteria: Optional structured testing requirements
- Get bearings: Read .ralph/progress.txt, git log, .ralph/prd.json
- Start env:
./.ralph/init.sh - Test existing: Verify nothing broke
- Select feature: ONE with
"passes": false - Implement: Clean, documented code
- Test: Browser automation + unit tests + type check
- Update PRD: Change
passestotrueonly if verified - Log: Append to .ralph/progress.txt
- Commit:
git commit -m "feat: ..." - Check done: If all pass, say
PROMISE COMPLETE
Remember: Small, verified steps lead to robust applications. 🎯