
Setup Ralph
- 120 installs
- 2k repo stars
- Updated April 1, 2026
- glittercowboy/taches-cc-resources
For development and infrastructure management.
About
setup-ralph is an AI coding tool that enhances development workflows. Builders use it for infrastructure, integration, and platform development within the catalog ecosystem.
- setup-ralph
- Development
Setup Ralph by the numbers
- 120 all-time installs (skills.sh)
- Ranked #2,832 of 4,347 Backend & APIs skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/glittercowboy/taches-cc-resources --skill setup-ralphAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 120 |
|---|---|
| repo stars | ★ 2k |
| Last updated | April 1, 2026 |
| Repository | glittercowboy/taches-cc-resources ↗ |
What it does
For development and infrastructure management.
Files
<essential_principles>
What is Ralph?
Ralph is Geoffrey Huntley's autonomous AI coding methodology that uses iterative loops with task selection, execution, and validation. In its purest form, it's a Bash loop:
while :; do cat PROMPT.md | claude ; doneThe loop feeds a prompt file to Claude, the agent completes one task, updates the implementation plan, commits changes, then exits. The loop restarts immediately with fresh context.
Core Philosophy
The Ralph Wiggum Technique is deterministically bad in an undeterministic world. Ralph solves context accumulation by starting each iteration with fresh context—the core insight behind Geoffrey's approach.
Three Phases, Two Prompts, One Loop
1. Planning Phase: Gap analysis (specs vs code) outputs prioritized TODO list—no implementation, no commits 2. Building Phase: Picks tasks from plan, implements, runs tests (backpressure), commits 3. Observation Phase: You sit on the loop, not in it—engineer the setup and environment that allows Ralph to succeed
Key Principles
Your Role: Ralph does all the work, including deciding which planned work to implement next and how to implement it. Your job is to engineer the environment.
Backpressure: Create backpressure via tests, typechecks, lints, builds that reject invalid/unacceptable work.
Observation: Watch, especially early on. Prompts evolve through observed failure patterns.
Context Efficiency: With ~176K usable tokens from 200K window, allocating 40-60% to "smart zone" means tight tasks with one task per loop achieves maximum context utilization.
File I/O as State: The plan file persists between isolated loop executions, serving as deterministic shared state—no sophisticated orchestration needed.
Remote Backup: The loop automatically creates a private GitHub repo and pushes after each commit. This protects against accidental data loss from autonomous operations. Requires gh CLI authenticated. Disable with RALPH_BACKUP=false.
Safety Rules: PROMPT_build.md includes critical safety rules prohibiting dangerous operations like rm -rf on project directories. Tests must run in isolated temp directories. </essential_principles>
<intake> What would you like to do?
1. Set up a new Ralph loop - Initialize Ralph structure in a directory 2. Understand Ralph concepts - Learn about the technique and how it works 3. Customize existing loop - Modify prompts or configuration 4. Troubleshoot Ralph - Debug loop issues or improve performance
Wait for response before proceeding. </intake>
<routing>
| Response | Workflow |
|---|---|
| 1, "set up", "setup", "new", "initialize", "create" | workflows/setup-new-loop.md |
| 2, "understand", "learn", "concepts", "explain", "how" | workflows/understand-ralph.md |
| 3, "customize", "modify", "change", "update", "edit" | workflows/customize-loop.md |
| 4, "troubleshoot", "debug", "fix", "problem", "issue" | workflows/troubleshoot-loop.md |
| Other | Clarify intent, then select appropriate workflow |
After reading the workflow, follow it exactly. </routing>
<reference_index>
Domain Knowledge
All in references/:
Core Concepts: ralph-fundamentals.md - Three phases, two prompts, one loop Structure: project-structure.md - Required files and directory layout Prompts: prompt-design.md - Planning vs building mode instructions Backpressure: validation-strategy.md - Tests, lints, builds as steering Best Practices: operational-learnings.md - AGENTS.md guidance and evolution </reference_index>
<workflows_index>
| Workflow | Purpose |
|---|---|
| setup-new-loop.md | Initialize Ralph structure in a directory |
| understand-ralph.md | Learn Ralph concepts and philosophy |
| customize-loop.md | Modify prompts or loop configuration |
| troubleshoot-loop.md | Debug loop issues and improve performance |
</workflows_index>
<success_criteria> Skill is successful when:
- User understands which workflow they need
- Appropriate workflow loaded based on intent
- All required references loaded by workflow
- User can set up and run Ralph loops independently
</success_criteria>
setup-ralph
A Claude Code skill that sets up Ralph Wiggum loops - Geoffrey Huntley's autonomous AI coding technique.
What is Ralph?
Ralph is an autonomous coding methodology where Claude runs in a loop:
while :; do cat PROMPT.md | claude -p --dangerously-skip-permissions; doneEach iteration: 1. Reads specs and implementation plan 2. Picks the most important task 3. Implements it 4. Runs validation (tests, types, lint, build) 5. Commits changes 6. Exits → loop restarts with fresh context
The key insight: fresh context every iteration prevents hallucination accumulation and context poisoning.
Features
- Two-phase workflow: Planning mode (gap analysis) → Building mode (implementation)
- Docker isolation: Run Ralph in a container so it can't touch your system files
- OAuth token handling: Automatic token loading for headless mode
- Iteration summaries: See commits, files changed, and progress after each task
- Stuck detection: Auto-skips tasks after 3 failed attempts
- Session reports: Summary of what was accomplished when the loop ends
- File logging:
tail -f ralph.logto watch progress
Usage
In Claude Code, run:
/setup-ralphThen follow the prompts to configure:
- Project directory
- Tech stack (determines validation commands)
- Backpressure level (tests only → full validation)
- Docker mode (yes/no)
Generated Files
your-project/
├── loop.sh # Main loop script
├── loop-docker.sh # Docker-wrapped loop (if selected)
├── Dockerfile # Container definition (if selected)
├── PROMPT_plan.md # Planning mode instructions
├── PROMPT_build.md # Building mode instructions
├── AGENTS.md # Operational learnings (you update this)
├── IMPLEMENTATION_PLAN.md # Task list (generated by planning)
├── specs/ # Your requirement docs go here
└── src/ # Code goes hereRunning the Loop
Direct mode:
./loop.sh plan # Generate implementation plan
./loop.sh # Build until complete
./loop.sh 20 # Build max 20 iterationsDocker mode (isolated):
./loop-docker.sh --build-image # First time only
./loop-docker.sh plan # Generate plan
./loop-docker.sh # Build in containerIteration Output
After each iteration, you'll see:
━━━ Iteration 5 Complete (2m 34s) ━━━
✅ Commit: abc1234 [city] Add procedural building generation
📁 Files: +2 new, ~3 modified
🆕 src/CityGenerator.ts
🆕 src/Building.ts
✏️ src/Game.ts
✏️ src/World.ts
📊 Progress: 5/22 tasks (23%)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━Your Role
Sit on the loop, not in it.
You:
- Write specs in
specs/(one file per topic) - Watch for failure patterns
- Update
AGENTS.mdwith learnings - Ctrl+C to stop when needed
You don't:
- Jump in to fix code manually
- Interfere with the autonomous process
When Ralph struggles repeatedly, update the environment (specs, AGENTS.md, prompts) rather than fixing code directly.
OAuth Setup (Required for Headless Mode)
# Generate token
claude setup-token
# Save it
echo "sk-ant-oat01-YOUR-TOKEN" > ~/.claude-oauth-token
chmod 600 ~/.claude-oauth-tokenThe loop scripts automatically load this token.
Docker Mode
Docker mode runs Claude in an isolated container:
- ✅ Can only access the project directory
- ✅ Can't modify system files
- ✅ Uses your Claude Max subscription via OAuth token
- ✅ Non-root user (required for
--dangerously-skip-permissions)
First time setup:
./loop-docker.sh --build-imageThen just run ./loop-docker.sh - switches seamlessly between Docker and direct mode.
Writing Good Specs
Each spec file should pass the "one sentence without 'and'" test:
- ✅
specs/authentication.md- "User login with credentials" - ✅
specs/session-management.md- "Session lifecycle and validation" - ❌
specs/user-system.md- "Auth AND profiles AND billing" (too broad)
Include:
- Clear requirements
- Examples where helpful
- Acceptance criteria
- NOT implementation details (that's Ralph's job)
Credits
Based on Geoffrey Huntley's Ralph Wiggum technique.
License
MIT
Operational Learnings
Guidance on using AGENTS.md to capture and evolve Ralph's knowledge.
<what_is_agents_md>
What is AGENTS.md?
AGENTS.md is a file that contains project-specific learnings that Ralph needs to know. It's loaded every loop iteration alongside the prompt.
Purpose:
- Capture patterns Ralph should follow
- Document project-specific constraints
- Record discovered learnings from failures
- Provide build/test commands
- Share context that prompts don't include
Key insight: AGENTS.md evolves through observation. Start minimal, add only what's needed. </what_is_agents_md>
<start_minimal>
Start Minimal
Initial AGENTS.md (literally this):
# Operational Learnings
This file contains project-specific guidance for Ralph.
## Build/Test Commands
[To be filled as needed]
## Known Patterns
[To be filled as needed]
## Constraints
[To be filled as needed]Or even simpler (just empty sections):
# Operational LearningsDon't:
- Pre-populate with guessed patterns
- Copy from other projects
- Add rules you haven't observed need for
- Try to predict all failure modes
Do:
- Start empty or near-empty
- Add entries when Ralph fails repeatedly
- Remove entries when no longer relevant
- Keep it focused and minimal
</start_minimal>
<when_to_add_entries>
When to Add Entries
Add to AGENTS.md when you observe:
1. Repeated Mistakes
Observation: Ralph keeps implementing authentication without using the existing auth library Entry:
## Known Patterns
### Authentication
Always use src/lib/auth.ts for authentication. Do not implement custom auth logic.2. Project-Specific Commands
Observation: Tests require specific environment setup Entry:
## Build/Test Commands
### Running Testsexport NODE_ENV=test npm test
Tests require NODE_ENV=test to use test database.3. Discovered Constraints
Observation: Ralph keeps trying to use a library that's not available Entry:
## Constraints
### Dependencies
- Do NOT use lodash (not installed, use native JS instead)
- Do NOT use axios (use native fetch)
- DO use Zod for validation (already installed)4. Architectural Decisions
Observation: Ralph implements features in inconsistent locations Entry:
## Known Patterns
### Code Organization
- UI components: src/components/
- Business logic: src/lib/
- API routes: src/pages/api/
- Database: src/db/
New features should follow this structure.5. Gotchas and Edge Cases
Observation: Ralph forgets to handle specific edge case Entry:
## Known Patterns
### Date Handling
Always handle timezone conversion. User input is in local time, database stores UTC.
Use src/lib/dates.ts utilities for all date operations.</when_to_add_entries>
<when_not_to_add_entries>
When NOT to Add Entries
Don't add to AGENTS.md for:
1. One-Off Mistakes
Ralph made a mistake once, then corrected it. No pattern yet.
Wait for: Same mistake 2-3 times, then add guidance.
2. General Best Practices
Don't add universal programming wisdom:
Bad:
## Best Practices
- Write clean code
- Use meaningful variable names
- Handle errors properlyWhy: Claude already knows this. AGENTS.md is for project-specific knowledge.
3. Things in Specs
If it's already in the spec, don't duplicate in AGENTS.md.
Bad: Spec says "use JWT for auth", AGENTS.md repeats "use JWT for auth" Good: Spec says "handle auth", AGENTS.md says "use src/lib/auth.ts (JWT implementation)"
4. Temporary Workarounds
Bad:
## Workarounds
- API endpoint /v1/users is broken, use /v2/users insteadWhy: This will become stale. Fix the root cause or document in code comments, not AGENTS.md.
5. Overly Specific Instructions
Bad:
## Implementation Steps for User Profile Feature
1. Create src/components/UserProfile.tsx
2. Add props interface with name, email, avatar
3. Import Avatar component from src/components/ui/Avatar
4. Style using Tailwind classes: bg-white rounded-lg shadow-md
...Why: This is a task description, not a learning. Put this in specs or let Ralph figure it out. </when_not_to_add_entries>
<structure_guidance>
Structure Guidance
Keep AGENTS.md organized and scannable:
Use Clear Sections
# Operational Learnings
## Build/Test Commands
[Commands Ralph needs to run]
## Known Patterns
[Project-specific patterns to follow]
## Constraints
[Things Ralph can't or shouldn't do]
## Architecture
[High-level structure and decisions]
## Gotchas
[Edge cases and non-obvious behaviors]Use Subsections for Categories
## Known Patterns
### Authentication
[Auth-specific patterns]
### Database
[Database-specific patterns]
### API Design
[API-specific patterns]Keep Entries Concise
Bad:
### Error Handling
We have a comprehensive error handling system that was implemented
in PR #123. It uses custom error classes that extend the base Error
class. When implementing new features, you should follow this pattern
by creating appropriate error classes and throwing them with descriptive
messages. The error handling middleware will catch these and return
appropriate HTTP status codes. For validation errors, use 400. For
authentication errors, use 401. For authorization errors, use 403...Good:
### Error Handling
Use custom error classes from src/lib/errors.ts
- ValidationError → 400
- AuthenticationError → 401
- AuthorizationError → 403Use Code Examples
When patterns are easier to show than describe:
### API Response Format
Always return this structure:{ success: boolean data?: any error?: { message: string, code: string } }
</structure_guidance>
<evolution_over_time>
Evolution Over Time
AGENTS.md grows and changes with the project:
Phase 1: Initial Loops (Days 1-3)
- File is mostly empty
- Watching for patterns
- Taking notes but not committing to AGENTS.md yet
Phase 2: Pattern Recognition (Week 1)
- First entries added based on observed failures
- Mostly build/test commands and constraints
- 20-50 lines total
Phase 3: Stabilization (Weeks 2-4)
- Known patterns documented
- Architecture decisions captured
- Ralph following patterns more consistently
- 50-150 lines total
Phase 4: Maturity (Month 2+)
- Well-documented project knowledge
- New entries added rarely
- Occasional cleanup of stale entries
- 100-300 lines total
Phase 5: Maintenance
- AGENTS.md changes infrequently
- Entries removed when architecture changes
- Project patterns are stable
- Size stays constant or shrinks
</evolution_over_time>
<example_agents_md>
Example AGENTS.md
Real-world example from a TypeScript web app:
# Operational Learnings
## Build/Test Commands
### Running Testsnpm test # All tests npm test -- --watch # Watch mode npm test -- path/to/test # Specific test
### Type Checkingnpm run type-check # TypeScript validation
### Buildingnpm run build # Production build npm run dev # Development server
## Known Patterns
### Authentication
- Use src/lib/auth.ts for all auth operations
- JWT tokens stored in httpOnly cookies
- Refresh tokens in separate cookie
- Don't implement custom auth logic
### Database Queries
- Use Prisma client from src/db/client.ts
- Always use transactions for multi-step operations
- Include error handling for unique constraint violations
### API Design
Response format:{ success: boolean data?: T error?: { message: string, code: string } }
### Component Structure
- UI components: src/components/ui/ (no business logic)
- Feature components: src/components/features/ (can have logic)
- Shared hooks: src/hooks/
- Use TypeScript interfaces for all props
## Constraints
### Dependencies
- Use native fetch (not axios)
- Use Zod for validation (already installed)
- Use date-fns for dates (not moment.js)
- Use Tailwind for styling (no CSS modules)
### Database
- Do NOT use raw SQL (use Prisma)
- Do NOT expose internal IDs in API (use UUIDs or slugs)
### Testing
- Do NOT use shallow rendering (use Testing Library)
- Do NOT test implementation details (test behavior)
## Gotchas
### Dates
- User input is local time, database stores UTC
- Always convert using src/lib/dates.ts utilities
### File Uploads
- Max file size: 10MB (enforced by middleware)
- Store in S3, not local filesystem
- Generate signed URLs for access
### Rate Limiting
- API endpoints are rate-limited (100 req/min)
- Auth endpoints stricter (10 req/min)
- Handle 429 responses with exponential backoff</example_agents_md>
<common_categories>
Common Categories
Categories you might need in AGENTS.md:
Technical
- Build/Test Commands
- Dependencies and Versions
- Environment Variables
- API Endpoints
- Database Schema Notes
Patterns
- Code Organization
- Naming Conventions
- Error Handling
- Logging Strategy
- Authentication/Authorization
Constraints
- What NOT to use
- Performance Requirements
- Security Requirements
- Deployment Constraints
Business Logic
- Domain Rules
- Calculation Formulas
- State Machines
- Workflow Steps
Integration
- External APIs
- Third-party Services
- Webhook Handling
- Event Processing
Testing
- Test Strategy
- Mock Patterns
- Test Data Setup
- CI/CD Notes
</common_categories>
<keeping_it_current>
Keeping It Current
AGENTS.md can become stale. Regular maintenance:
Weekly Review
- Read through AGENTS.md
- Remove entries that are now in code patterns
- Remove entries that are outdated
- Add entries from the week's observations
After Major Changes
- Architecture refactor → update patterns
- Dependency updates → verify commands still work
- New features → add new patterns if emerging
Signs of Staleness
- Entries contradict current code
- Commands don't work anymore
- Patterns no longer followed
- Ralph ignoring entries (they're wrong)
Cleanup Triggers
- File over 500 lines → too much, condense
- Same information repeated → consolidate
- Entries no one references → remove
- Contradictory entries → reconcile
</keeping_it_current>
<antipatterns>
Anti-Patterns
Things to avoid:
1. The Novel
AGENTS.md shouldn't be 1000+ lines of comprehensive project documentation. That belongs in real docs.
2. The Rule Book
Don't make it a list of "thou shalt not" commands. Keep it practical and pattern-focused.
3. The Tutorial
Don't teach programming concepts. Assume Claude is a competent developer, just new to your project.
4. The Archive
Don't keep historical notes about decisions. Document current state only.
5. The Spec Duplicate
Don't repeat what's in your specs. Reference specs, don't duplicate them.
6. The Wishlist
Don't add patterns you wish existed. Document what actually is, not what should be. </antipatterns>
Project Structure
Required files and directory layout for a Ralph loop.
<essential_files>
Essential Files
loop.sh
Main orchestration script that runs the loop.
Minimal implementation:
#!/bin/bash
while :; do cat PROMPT.md | claude ; doneProduction implementation:
- Mode switching (plan vs build)
- Iteration limits
- CLI flag configuration
- Error handling
Located at project root.
PROMPT_plan.md
Instructions for planning mode. Tells Claude to:
- Study specs and existing code
- Perform gap analysis
- Generate/update
IMPLEMENTATION_PLAN.md - NOT implement anything
Located at project root.
PROMPT_build.md
Instructions for building mode. Tells Claude to:
- Read the implementation plan
- Select most important task
- Search existing code
- Implement functionality
- Run validation
- Update plan
- Commit changes
Located at project root.
IMPLEMENTATION_PLAN.md
The persistent task list that survives across iterations.
Generated by: Planning mode Updated by: Building mode (marks tasks complete, adds findings) Format: Markdown with prioritized list
This is the ONLY state that persists between loop iterations. Everything else is fresh context.
Initially empty. Created by first planning mode run.
AGENTS.md
Operational learnings specific to this project.
Purpose: Capture patterns Ralph needs to know Updated by: You (the observer) Format: Markdown with sections
Start minimal (even empty). Add guidance only when Ralph exhibits repeated failures or needs project-specific context.
Common sections:
- Build/Test Commands
- Known Patterns
- Discovered Constraints
- Learned Best Practices
Located at project root. </essential_files>
<directory_structure>
Directory Structure
project-root/
├── loop.sh # Orchestration script (executable)
├── PROMPT_plan.md # Planning mode instructions
├── PROMPT_build.md # Building mode instructions
├── AGENTS.md # Operational learnings (starts minimal)
├── IMPLEMENTATION_PLAN.md # Task list (generated by planning)
├── specs/ # Requirement documents
│ ├── topic-1.md
│ ├── topic-2.md
│ └── ...
└── src/ # Application source code
├── lib/ # Shared utilities
└── ...specs/ Directory
Requirement documents following "one sentence without 'and'" principle.
One file per topic of concern:
- ✓
specs/authentication.md- Describes auth requirements - ✓
specs/color-extraction.md- Describes color analysis requirements - ✗
specs/user-system.md- Too broad (auth AND profiles AND billing)
Format:
- Markdown
- Clear requirements
- Examples where helpful
- Acceptance criteria
- NOT implementation details (that's Ralph's job)
src/ Directory
Application source code. Structure depends on language/framework.
Common pattern:
src/
├── lib/ # Shared utilities
├── components/ # Reusable components
├── features/ # Feature-specific code
└── tests/ # Test filesRalph learns patterns from existing code in src/. Consistent structure helps Ralph maintain consistency. </directory_structure>
<optional_directories>
Optional Directories
.git/
Version control. Ralph commits after each task.
Required for:
- Tracking changes
- Reverting mistakes
- Reviewing what Ralph did
Initialize before starting loop:
git init
git add .
git commit -m "Initial commit"tests/
Test files for validation backpressure.
Location: Depends on language/framework
- JavaScript/TypeScript: Often
src/__tests__/ortests/ - Python: Often
tests/at root - Go: Test files alongside source (
*_test.go)
Ralph needs runnable tests to create backpressure. If no tests exist, Ralph has no feedback mechanism.
.github/ or .gitlab/
CI/CD configuration (optional).
Ralph can update these, but they're not core to the loop mechanism. </optional_directories>
<file_loading_order>
File Loading Order
Each loop iteration loads files in this order:
1. PROMPT.md (or mode-specific variant)
- First ~5,000 tokens
- Sets the objective
2. AGENTS.md
- Project-specific learnings
- Patterns Ralph needs to know
3. IMPLEMENTATION_PLAN.md
- Current task list
- What's done, what's pending
4. specs/
- Requirement documents
- Loaded via subagents (parallel)
5. src/
- Existing code (as needed)
- Loaded via subagents (parallel)
Total context budget: ~176K usable tokens from 200K window.
Optimize by:
- Keeping PROMPT.md tight
- Keeping AGENTS.md minimal
- Using parallel subagents for reading
- One task per iteration (focused context)
</file_loading_order>
<topic_of_concern_scope>
Topic of Concern Scope
Test: Can you describe the topic in one sentence without "and"?
Good examples:
- "Authentication handles user login and session management" → Split into:
authentication.md- User login with credentialssession-management.md- Session lifecycle and validation
- "Color extraction analyzes images for dominant colors" → Keep as one:
color-extraction.md- Single topic, no conjunction needed
Why this matters:
- Each spec file should have clear, focused requirements
- Ralph works better with well-scoped tasks
- Easier to validate completion
- Simpler to update when requirements change
If unsure:
- Start with separate files
- Merge later if topics are truly coupled
- Bias toward focused specs
</topic_of_concern_scope>
<minimal_viable_structure>
Minimal Viable Structure
Absolute minimum to start a Ralph loop:
project-root/
├── loop.sh # Minimal bash loop
├── PROMPT_build.md # Building instructions
├── IMPLEMENTATION_PLAN.md # Empty initially
└── src/ # Your codeYou can skip:
PROMPT_plan.md- Write plan manuallyAGENTS.md- Start with empty filespecs/- Embed requirements in PROMPT_build.md
But you should have:
- Version control (git)
- Tests (for backpressure)
- Clear requirements (somewhere)
Recommended: Use full structure. The overhead is minimal, and you'll want it as the loop runs. </minimal_viable_structure>
Prompt Design
Guidance for writing effective planning and building mode prompts.
<prompt_principles>
Prompt Principles
1. Prompts Are Signs, Not Rules
Ralph learns from:
- Existing code patterns
- AGENTS.md learnings
- Specs requirements
- Validation feedback
The prompt provides initial direction. The environment shapes actual behavior.
2. Start Minimal, Evolve Through Observation
Don't try to predict all failure modes. Start with simple instructions and add guidance when you observe specific failures.
Anti-pattern:
IMPORTANT: Don't do X
CRITICAL: Never do Y
WARNING: Avoid Z
REMEMBER: Always check for...Better:
1. Study specs
2. Implement task
3. Run tests
4. CommitAdd specifics to AGENTS.md as patterns emerge.
3. One Clear Objective Per Mode
Planning mode: Gap analysis only, no implementation Building mode: Implement one task, validate, commit
Mixing objectives (plan AND build) creates confusion.
4. Leverage Parallel Subagents
Claude Code can spawn hundreds of subagents for reading/searching. Use this:
Study specs/* (up to 500 parallel Sonnet subagents)This tells Claude it's safe and encouraged to use massive parallelism.
5. Context Budget Allocation
~176K usable tokens. Typical allocation:
- Prompt: ~5,000 tokens
- AGENTS.md: ~2,000 tokens
- IMPLEMENTATION_PLAN.md: ~5,000 tokens
- Specs: ~20,000 tokens
- Source code: ~100,000 tokens
- "Smart zone" (reasoning): ~40,000 tokens
Keep prompts tight to maximize smart zone. </prompt_principles>
<planning_prompt_template>
Planning Prompt Template
# Planning Mode
You are Ralph, an autonomous coding agent in planning mode.
## Objective
Study specifications and existing code, then generate a prioritized implementation plan. DO NOT implement anything.
## Process
0a. Study specs/* (use up to 250 parallel Sonnet subagents)
0b. Study @IMPLEMENTATION_PLAN.md (if exists)
0c. Study src/lib/* (shared utilities to understand patterns)
0d. Reference: src/* (as needed for gap analysis)
1. Gap Analysis
- Compare each spec against existing code
- Identify what's missing, incomplete, or incorrect
- IMPORTANT: Don't assume not implemented; confirm with code search first
- Consider TODO comments, placeholders, and partial implementations
2. Generate/Update IMPLEMENTATION_PLAN.md
- Prioritized list of tasks
- Most important/foundational work first
- Each task should be completable in one loop iteration
- Include brief context for why each task matters
3. Exit
- Do NOT implement anything
- Do NOT commit anything
- Just generate the plan and exit
## Success Criteria
- IMPLEMENTATION_PLAN.md exists and is prioritized
- Each task is specific and actionable
- Plan reflects actual gaps (confirmed via code search)
- No code changes madeCustomization points:
- Subagent counts (250-500 depending on project size)
- Source directory structure (src/lib/, src/features/, etc.)
- Project-specific analysis needs
</planning_prompt_template>
<building_prompt_template>
Building Prompt Template
# Building Mode
You are Ralph, an autonomous coding agent in building mode.
## Objective
Select the most important task from the implementation plan, implement it correctly, validate it works, and commit.
## Process
0a. Study specs/* (use up to 500 parallel Sonnet subagents)
0b. Study @IMPLEMENTATION_PLAN.md
0c. Reference: src/* (use parallel Sonnet subagents for code reading)
1. Select Task
- Pick the most important task from IMPLEMENTATION_PLAN.md
- Most important = most foundational or highest priority
- If unclear, pick the first uncompleted task
2. Investigate Before Implementing
- Search codebase first (don't assume missing)
- Understand existing patterns and conventions
- Use up to 500 Sonnet subagents for reading/searching
- Identify exactly what needs to change
3. Implement
- Follow patterns from existing code
- Reference specs for requirements
- Write clean, maintainable code
- Add tests if they don't exist
4. Validate
- Run: [VALIDATION_COMMANDS]
- Use only 1 Sonnet subagent for build/tests (creates backpressure)
- If validation fails, fix and retry
- Do not commit until validation passes
5. Update Plan
- Mark completed task in IMPLEMENTATION_PLAN.md
- Add any new tasks discovered during implementation
- Note any blockers or issues found
6. Commit
- Descriptive commit message
- Format: "[component] brief description"
- Push changes (if remote configured)
7. Exit
- End loop iteration
- Fresh context starts next iteration
## Success Criteria
- One task completed per iteration
- All validation passes
- Changes committed
- Plan updated with progressCustomization points:
[VALIDATION_COMMANDS]- Project-specific tests/checks- Subagent counts
- Source directory references
- Commit message format
- Push behavior (if using remote git)
</building_prompt_template>
<validation_commands>
Validation Commands
Replace [VALIDATION_COMMANDS] with project-specific commands:
JavaScript/TypeScript
Run:
- npm test (or yarn test, pnpm test)
- npm run type-check (if using TypeScript)
- npm run lint (if configured)
- npm run build (if applicable)Python
Run:
- pytest
- mypy . (if using type hints)
- ruff check . (or flake8, pylint)
- python -m build (if package)Go
Run:
- go test ./...
- go vet ./...
- golangci-lint run (if configured)
- go build ./...Rust
Run:
- cargo test
- cargo clippy -- -D warnings
- cargo build --releaseMinimal (no tooling yet)
Run:
- [language] [test_runner] (create if missing)
- Basic smoke test (does it run?)Principle: Validation must be automated and binary (pass/fail). If tests don't exist, Ralph should create them. </validation_commands>
<subagent_guidance>
Subagent Guidance
Why Specify Counts?
Claude Code is conservative about spawning subagents unless explicitly permitted. Specifying counts signals:
- It's safe to parallelize
- High counts are acceptable
- Performance is valued
Recommended Counts
Reading/searching (Sonnet):
- Small project (<100 files): 50-100 subagents
- Medium project (100-500 files): 250-500 subagents
- Large project (500+ files): 500+ subagents
Building/testing (Sonnet):
- Always 1 subagent
- Creates backpressure
- Sequential validation is intentional
Why Sonnet?
- Faster than Opus
- Cheaper than Opus
- Good enough for reading/searching and validation
- Opus is overkill for most Ralph tasks
Specifying in prompt:
Study specs/* (use up to 500 parallel Sonnet subagents)
Run tests (use only 1 Sonnet subagent)Main Agent Role
The main agent (Opus or Sonnet for loop) orchestrates:
- Task selection
- Strategy decisions
- Code generation (sometimes delegates to subagents)
- Plan updates
Keep main agent focused on reasoning, delegate I/O to subagents. </subagent_guidance>
<prompts_evolve>
Prompts Evolve
Initial Prompt (Minimal)
Start with basic structure:
1. Study specs
2. Pick task from plan
3. Implement
4. Run tests
5. CommitAfter Observing Failures
Ralph keeps reimplementing the same thing? Add:
2a. Search existing code first (don't assume missing)Ralph writes inconsistent code? Add:
3a. Study existing patterns in src/lib/*
3b. Match existing code style and conventionsRalph doesn't update plan? Add:
5a. Mark task complete in IMPLEMENTATION_PLAN.md
5b. Note any new tasks discoveredAfter Many Iterations
Prompts accumulate learnings. But watch for:
- Too many rules (sign of over-steering)
- Contradictory guidance
- Outdated assumptions
Periodically review and simplify. Move stable patterns to AGENTS.md. </prompts_evolve>
<common_prompt_mistakes>
Common Prompt Mistakes
Mistake 1: Mixing Modes
Bad:
Generate a plan, then start implementing the first task...Good:
Planning mode: Generate plan only, do not implement
Building mode: Implement from plan, one task per iterationMistake 2: Over-Specifying
Bad:
CRITICAL: Before implementing, you must:
1. Read all files in src/
2. Check for existing implementations of similar features
3. Review the git history for context
4. Consider performance implications
5. Think about edge cases
6. Validate against all specs
...Good:
1. Search existing code
2. Implement task
3. Run testsLet Ralph figure out the details. Add specifics only when failures occur.
Mistake 3: Assuming Sequential Reading
Bad:
Read spec-1.md, then spec-2.md, then spec-3.md...Good:
Study specs/* (use up to 500 parallel Sonnet subagents)Claude can read hundreds of files simultaneously. Let it.
Mistake 4: No Clear Exit
Bad:
Implement tasks from the plan until everything is done...Good:
6. Exit
- End this loop iteration
- One task per iteration
- Loop will restart with fresh contextRalph needs to know when to exit. Otherwise it may try to do multiple tasks or wait for input.
Mistake 5: Vague Validation
Bad:
Make sure everything works before committing...Good:
4. Validate
- Run: npm test
- Run: npm run type-check
- If any fail, fix and retry
- Do not commit until all passConcrete commands create reliable backpressure. </common_prompt_mistakes>
<context_references>
Context References
Use @filename to ensure files are loaded into context:
0b. Study @IMPLEMENTATION_PLAN.mdThis tells Claude Code to inline the file content, guaranteeing it's in context.
When to use:
- Critical files that must be loaded (plan, specs)
- Files Ralph needs for every iteration
- Relatively small files (<10K tokens)
When not to use:
- Large directories (use parallel subagents instead)
- Optional reference files
- Files that may not exist yet
</context_references>
Ralph Fundamentals
Core concepts and philosophy of Geoffrey Huntley's Ralph Wiggum autonomous coding technique.
<what_is_ralph>
What is Ralph?
Ralph is an autonomous AI coding methodology created by Geoffrey Huntley that went viral in late 2025. In its purest form, it's a Bash loop:
while :; do cat PROMPT.md | claude ; doneThe loop continuously feeds a prompt file to Claude Code CLI. The agent completes one task, updates the implementation plan on disk, commits changes, then exits. The loop restarts immediately with fresh context.
The core insight: Ralph solves context accumulation by starting each iteration with fresh context. This is "deterministically bad in an undeterministic world"—embracing the chaos rather than fighting it. </what_is_ralph>
<three_phases_two_prompts_one_loop>
Three Phases, Two Prompts, One Loop
Ralph isn't just "a loop that codes." It's a funnel with specific structure:
Phase 1: Planning Mode
Objective: Gap analysis only Input: Specs and existing code Output: IMPLEMENTATION_PLAN.md (prioritized TODO list) Rule: No implementation, no commits
The planning prompt instructs Claude to: 1. Study all specification files 2. Study existing source code 3. Compare specs against implementation 4. Generate or update IMPLEMENTATION_PLAN.md 5. Exit
Critical instruction: "Don't assume not implemented; confirm with code search first."
Phase 2: Building Mode
Objective: Implement from the plan Input: Plan, specs, existing code Output: Code changes + commits Rule: One task per loop iteration
The building prompt instructs Claude to: 1. Study the implementation plan 2. Select most important task 3. Search existing code (don't assume anything is missing) 4. Implement the functionality 5. Run validation (tests, type checks, lints) 6. Update the plan with findings 7. Commit with descriptive message 8. Exit
Phase 3: Observation (Your Role)
Objective: Sit on the loop, not in it Action: Engineer the environment that allows Ralph to succeed
You:
- Watch for failure patterns
- Update
AGENTS.mdwith learnings - Tune prompts based on observed behavior
- Regenerate plan when trajectory fails
- Add backpressure mechanisms
- Improve specs when Ralph misunderstands
You DON'T:
- Jump into the loop to fix things
- Manually implement features
- Edit code directly
- Interfere with the autonomous process
</three_phases_two_prompts_one_loop>
<core_principles>
Core Principles
1. Fresh Context Every Iteration
Each loop starts with a clean 200K context window. No accumulated conversation history, no stale assumptions. This prevents context poisoning and forces Ralph to ground decisions in files on disk.
2. File I/O as State
The IMPLEMENTATION_PLAN.md file is the only state that persists across iterations. This serves as deterministic shared state—no sophisticated orchestration needed. Claude reads it, updates it, commits it.
3. Backpressure as Steering
Tests, type checks, lints, and builds provide downstream steering. If Ralph's code doesn't pass validation, the loop continues until it does. This creates self-correcting behavior without manual intervention.
Validation must be:
- Automated (no human approval)
- Binary (pass/fail)
- Fast enough to run every iteration
- Relevant to code quality
4. Context Efficiency
200K advertised tokens ≈ 176K usable tokens. The "smart zone" (where Claude reasons best) is 40-60% of the window.
Optimization:
- Tight tasks + one task per loop = 100% smart zone utilization
- Use main agent as scheduler; spawn subagents for expensive work
- Prefer Markdown over JSON (more token-efficient)
- Keep prompts focused on current task
5. Parallel Subagents for Reads
The main agent orchestrates. Subagents do expensive work:
- Up to 250-500 Sonnet subagents for reading/searching code
- Only 1 subagent for builds/tests (to create backpressure)
- Subagents are cheap and fast for I/O-bound work
6. Prompts as Signs
Prompts aren't just instructions—they're discoverable patterns. Ralph learns from:
- Existing code patterns (how utilities are structured)
- AGENTS.md (project-specific learnings)
- Specs (requirements and constraints)
- Validation failures (what not to do)
7. Let Ralph Ralph
Trust the LLM's self-identification and self-correction ability:
- Don't micromanage
- Don't pre-optimize
- Observe and course-correct reactively
- "Tune it like a guitar" through iteration
Signs of over-steering:
- Prompts with too many rules
- Trying to predict all failure modes
- Not letting Ralph fail and learn
- Jumping in to fix instead of updating prompts
</core_principles>
<philosophy>
Philosophy
Deterministically Bad in an Undeterministic World
Traditional AI coding tries to maintain context across a long conversation. This fights against the probabilistic nature of LLMs and leads to:
- Context poisoning (earlier mistakes color later decisions)
- Assumption drift (LLM forgets what it "knew" earlier)
- Hallucination accumulation (errors compound)
Ralph embraces chaos:
- Fresh context = fresh start
- Plan on disk = deterministic state
- Validation = reality check
- Loop = inevitable progress
The Loop is the Product
You're not building software. You're building an environment that builds software. The loop is the unit of work, not the feature.
Good loop design:
- Clear specs that Ralph can understand
- Effective backpressure that rejects bad work
- Minimal prompts that evolve through observation
- AGENTS.md that captures learnings
Move Outside the Loop
Your role shifts from implementer to environment engineer:
- Inside the loop: Writing code, fixing bugs, implementing features (Ralph's job)
- Outside the loop: Writing specs, tuning prompts, adding tests, observing patterns (your job)
When Ralph fails repeatedly on the same thing, don't jump in and fix it. Update the environment: 1. Add guidance to AGENTS.md 2. Improve the spec 3. Add a test that would have caught it 4. Update the prompt pattern </philosophy>
<when_to_regenerate_plan>
When to Regenerate Plan
Discard IMPLEMENTATION_PLAN.md and restart planning when:
- Ralph implements wrong things or duplicates work
- Plan feels stale or mismatched to current state
- Too much completed-item clutter
- Significant spec changes made
- Confusion about actual completion status
Cost-benefit: One planning loop iteration is cheaper than Ralph circling on bad assumptions.
To regenerate:
rm IMPLEMENTATION_PLAN.md
./loop.sh plan</when_to_regenerate_plan>
<escape_hatches>
Escape Hatches
Stop the loop:
Ctrl+C # Stops current iterationRevert uncommitted changes:
git reset --hardRegenerate plan:
rm IMPLEMENTATION_PLAN.md
./loop.sh planLimit iterations:
./loop.sh 20 # Build mode, max 20 tasks
./loop.sh plan 5 # Plan mode, max 5 iterationsReview what Ralph did:
git log --oneline
git show [commit-hash]</escape_hatches>
Validation Strategy
Using tests, lints, and builds as backpressure to steer Ralph.
<what_is_backpressure>
What is Backpressure?
Backpressure is automated validation that rejects invalid work. It creates a self-correcting feedback loop:
1. Ralph implements task 2. Validation runs (tests, type checks, lints) 3. If validation fails, Ralph investigates and fixes 4. Loop continues until validation passes 5. Only then can Ralph commit and move to next task
Without backpressure: Ralph generates code that may not work, accumulates errors, goes off track.
With backpressure: Ralph must produce working code to progress. Quality is enforced, not hoped for. </what_is_backpressure>
<types_of_backpressure>
Types of Backpressure
1. Tests (Most Important)
Unit tests: Verify individual functions/components Integration tests: Verify components work together End-to-end tests: Verify full user workflows
Why tests are critical:
- Binary pass/fail (no ambiguity)
- Fast feedback (run every iteration)
- Specific to requirements (aligned with specs)
- Self-documenting (show expected behavior)
If no tests exist: Ralph should create them as part of implementation. Update building prompt:
3. Implement
- Write the functionality
- Add tests for new functionality
- Ensure tests pass2. Type Checking
TypeScript: tsc --noEmit or npm run type-check Python: mypy . Go: Built into go build Rust: Built into cargo build
Benefits:
- Catches type errors before runtime
- Enforces interface contracts
- Prevents common bugs
Limitation:
- Types can be correct but logic wrong
- Needs tests for behavior validation
3. Linting
JavaScript/TypeScript: ESLint, Biome Python: Ruff, flake8, pylint Go: golangci-lint Rust: clippy
Benefits:
- Enforces code style
- Catches common mistakes
- Maintains consistency
Limitation:
- Style != correctness
- Can be overly strict
- May slow down loop if too many rules
Recommendation: Start with minimal linting, add rules as patterns emerge.
4. Builds
Compiled languages: Ensure code compiles Bundlers: Ensure assets bundle correctly Docker: Ensure containers build
Benefits:
- Catches syntax errors
- Verifies dependencies
- Confirms deployment readiness
Limitation:
- Build success != working software
- Slower than tests (use sparingly in loop)
5. Custom Validation
Example: Visual regression tests
- Screenshot comparison
- LLM-as-judge for subjective criteria
Example: Performance benchmarks
- Response time thresholds
- Memory usage limits
Example: Security scans
- Dependency vulnerability checks
- Static analysis for common issues
When to use:
- Project-specific quality criteria
- Subjective acceptance criteria
- Non-functional requirements
</types_of_backpressure>
<validation_levels>
Validation Levels
Choose based on project maturity and speed needs:
Level 1: Tests Only (Fastest)
Run: npm testWhen to use:
- Early development
- Fast iteration needed
- No type system or linting configured
Pros: Fast loop, minimal friction Cons: May accumulate style inconsistencies
Level 2: Tests + Type Checking (Recommended)
Run:
- npm test
- npm run type-checkWhen to use:
- TypeScript/typed projects
- After initial implementation phase
- When interfaces are stabilizing
Pros: Good balance of speed and quality Cons: Type errors can slow down loop
Level 3: Full Validation (Slowest)
Run:
- npm test
- npm run type-check
- npm run lint
- npm run buildWhen to use:
- Mature projects
- Pre-release quality gates
- When consistency is critical
Pros: Highest quality output Cons: Slowest loop, most friction
Level 4: Custom Validation
Run:
- npm test
- npm run type-check
- npm run visual-test
- npm run security-scanWhen to use:
- Specific quality requirements
- Regulated industries
- User-facing products
Pros: Tailored to actual needs Cons: Complex to set up and maintain </validation_levels>
<validation_in_prompts>
Validation in Prompts
Planning Mode
No validation needed. Planning mode doesn't change code.
Building Mode
Include validation as a required step:
4. Validate
- Run: [specific commands]
- Use only 1 Sonnet subagent for build/tests
- If validation fails, investigate and fix
- Do not commit until all validation passes
- If repeatedly failing (3+ attempts), note blocker and move onKey points:
- Specific commands (not vague "make sure it works")
- Single subagent for validation (creates backpressure bottleneck)
- Failure requires investigation and fix
- Escape hatch for stuck tasks (note blocker, move on)
</validation_in_prompts>
<handling_validation_failures>
Handling Validation Failures
Expected Behavior
Ralph should: 1. See validation failure 2. Read error messages 3. Investigate cause 4. Fix the issue 5. Re-run validation 6. Repeat until passing
Failure Patterns
Pattern 1: Test failure due to incorrect implementation
- Ralph implemented wrong behavior
- Fix: Update implementation to match spec
Pattern 2: Test failure due to incorrect test
- Spec changed but test didn't
- Fix: Update test to match current spec
Pattern 3: Type error due to API mismatch
- Ralph used wrong types
- Fix: Correct types based on definitions
Pattern 4: Lint error due to style
- Code works but style is off
- Fix: Adjust formatting
Pattern 5: Build failure due to missing dependency
- Imported something not installed
- Fix: Add dependency or use different approach
Stuck in Loop
If Ralph repeatedly fails validation (3+ iterations on same task):
Option 1: Note blocker and skip
If repeatedly failing (3+ attempts), note blocker in plan and move to next taskOption 2: Regenerate plan
rm IMPLEMENTATION_PLAN.md
./loop.sh planOption 3: Manual intervention
# Stop loop
Ctrl+C
# Fix the issue manually
# Commit fix
# Restart loop
./loop.shOption 4: Update AGENTS.md Add guidance about the failure pattern so Ralph doesn't repeat it. </handling_validation_failures>
<backpressure_as_learning>
Backpressure as Learning
Validation failures teach Ralph:
- What "working" means for this project
- Edge cases to handle
- Patterns to follow
- Mistakes to avoid
Over time, validation failures should decrease as Ralph learns project patterns.
Early loops:
- Many validation failures
- Ralph learning patterns
- Prompts and AGENTS.md evolving
Later loops:
- Fewer validation failures
- Ralph aligned with patterns
- Stable prompts and learnings
If failures increase:
- Specs may have changed
- New complexity introduced
- Prompts may need update
- Consider plan regeneration
</backpressure_as_learning>
<no_tests_strategy>
No Tests? Start Here
If project has no tests:
Option 1: Ralph Creates Tests
Update building prompt:
3. Implement
- Write the functionality
- Add unit tests for new functionality
- Ensure tests pass before proceedingRalph will create tests as it implements features.
Option 2: Add Minimal Test Framework
Before starting loop:
# JavaScript/TypeScript
npm install --save-dev vitest
# or jest, or your preferred framework
# Python
pip install pytest
# Go
# Built-in, just use: go test ./...
# Rust
# Built-in, just use: cargo testCreate one example test to establish pattern.
Option 3: Use Type Checking Only
If tests are too much overhead initially:
4. Validate
- Run: tsc --noEmit # or equivalent
- Type errors must be fixedBetter than nothing. Add tests later when patterns stabilize.
Option 4: Manual Smoke Tests
Define manual checks in AGENTS.md:
## Validation
After each change:
- Run the application
- Test the changed feature manually
- Verify no errors in consoleNot ideal (not automated) but establishes quality baseline. </no_tests_strategy>
<tuning_backpressure>
Tuning Backpressure
Start strict, loosen if too slow:
Week 1: Full validation (tests + types + lint + build)
- See where Ralph struggles
- Identify slow validation steps
- Note which checks catch real issues
Week 2: Remove low-value checks
- If linting catches nothing, remove it
- If build is slow and redundant with tests, remove it
- Keep only checks that catch real problems
Week 3: Add custom checks
- Based on observed failure patterns
- Aligned with actual quality needs
- Fast enough to not slow loop significantly
Ongoing: Evolve with project
- Add checks when new failure patterns emerge
- Remove checks when no longer catching issues
- Balance speed vs quality based on project phase
</tuning_backpressure>
# Ralph Wiggum Loop - Docker Container
# Runs Claude Code CLI in isolated environment as non-root user
FROM node:22-slim
# Install system dependencies
RUN apt-get update && apt-get install -y git && rm -rf /var/lib/apt/lists/*
# Install Claude Code CLI globally
RUN npm install -g @anthropic-ai/claude-code
# Create non-root user for safety
# Claude blocks --dangerously-skip-permissions for root users
RUN useradd -m -s /bin/bash ralph && \
mkdir -p /workspace && \
chown ralph:ralph /workspace
# Switch to non-root user
USER ralph
# Set working directory
WORKDIR /workspace
# Configure git for commits (will be overwritten by mount)
RUN git config --global user.email "ralph@autonomous.ai" && \
git config --global user.name "Ralph Wiggum"
# Default command
CMD ["bash"]
#!/bin/bash
# Ralph Docker Loop
# Runs Claude in isolated container, backup/git runs on HOST
set -e
# Configuration
IMAGE_NAME="ralph-loop"
PROJECT_DIR="$(pwd)"
PROJECT_NAME=$(basename "$PROJECT_DIR")
BACKUP_ENABLED="${RALPH_BACKUP:-true}"
MODEL="${RALPH_MODEL:-opus}"
# Validate model against whitelist (security: prevents command injection)
validate_model() {
local model="$1"
case "$model" in
opus|sonnet|haiku) return 0 ;;
*)
echo "Error: Invalid model '$model'. Allowed: opus, sonnet, haiku"
exit 1
;;
esac
}
validate_model "$MODEL"
PLAN_FILE="IMPLEMENTATION_PLAN.md"
LOG_FILE="ralph.log"
# SAFETY: Verify PROJECT_DIR is safe to mount
if [ -z "$PROJECT_DIR" ] || [ "$PROJECT_DIR" = "/" ] || [ "$PROJECT_DIR" = "$HOME" ]; then
echo "FATAL: Refusing to mount unsafe directory: $PROJECT_DIR"
echo "Run this script from inside a project directory, not ~ or /"
exit 1
fi
# Verify we're in a Ralph project
if [ ! -f "PROMPT_build.md" ] && [ ! -f "PROMPT_plan.md" ]; then
echo "FATAL: Not a Ralph project directory (no PROMPT_*.md files)"
echo "Run /setup-ralph first or cd into a Ralph project"
exit 1
fi
# Load OAuth token (with security checks)
TOKEN_FILE="$HOME/.claude-oauth-token"
if [ -z "$CLAUDE_CODE_OAUTH_TOKEN" ]; then
if [ -f "$TOKEN_FILE" ]; then
# Security: Check file permissions (should be 600 or more restrictive)
if [[ "$OSTYPE" == "darwin"* ]]; then
TOKEN_PERMS=$(stat -f %Lp "$TOKEN_FILE" 2>/dev/null)
else
TOKEN_PERMS=$(stat -c %a "$TOKEN_FILE" 2>/dev/null)
fi
if [ -n "$TOKEN_PERMS" ] && [ "$((TOKEN_PERMS % 100))" -ne 0 ]; then
echo "⚠️ Security warning: $TOKEN_FILE has insecure permissions ($TOKEN_PERMS)"
echo " Run: chmod 600 $TOKEN_FILE"
echo ""
fi
CLAUDE_CODE_OAUTH_TOKEN=$(cat "$TOKEN_FILE")
else
echo "Error: No OAuth token found"
echo "Run 'claude setup-token' and save to ~/.claude-oauth-token"
echo "Then: chmod 600 ~/.claude-oauth-token"
exit 1
fi
fi
# Handle --build-image flag
if [ "$1" = "--build-image" ]; then
echo "Building Docker image..."
docker build -t "$IMAGE_NAME" .
echo "Image built: $IMAGE_NAME"
exit 0
fi
# Check if image exists
if ! docker image inspect "$IMAGE_NAME" &>/dev/null; then
echo "Docker image not found. Building..."
docker build -t "$IMAGE_NAME" .
fi
# Parse arguments
MODE="build"
LIMIT=""
while [[ $# -gt 0 ]]; do
case $1 in
plan) MODE="plan"; shift ;;
[0-9]*) LIMIT=$1; shift ;;
--model) MODEL=$2; validate_model "$MODEL"; shift 2 ;;
*) shift ;;
esac
done
# ============================================================================
# REMOTE BACKUP (runs on HOST with your gh auth)
# ============================================================================
setup_remote_backup() {
if [ "$BACKUP_ENABLED" != "true" ]; then
echo "Remote backup: disabled (set RALPH_BACKUP=true to enable)"
return 0
fi
if [ ! -d ".git" ]; then
echo "Initializing git..."
git init
git add -A
git commit -m "Initial commit" 2>/dev/null || true
fi
if git remote get-url origin &>/dev/null; then
echo "Remote backup: $(git remote get-url origin)"
return 0
fi
if ! command -v gh &>/dev/null; then
echo "Warning: gh CLI not found. Backup disabled."
BACKUP_ENABLED="false"
return 1
fi
if ! gh auth status &>/dev/null; then
echo "Warning: gh not authenticated. Backup disabled."
BACKUP_ENABLED="false"
return 1
fi
local repo_name="${PROJECT_NAME}-ralph-backup"
echo "Creating private backup: $repo_name"
if gh repo create "$repo_name" --private --source=. --push 2>/dev/null; then
echo "Remote backup: https://github.com/$(gh api user -q .login)/$repo_name"
else
echo "Warning: Could not create repo. Backup disabled."
BACKUP_ENABLED="false"
fi
}
push_to_backup() {
if [ "$BACKUP_ENABLED" = "true" ]; then
git add -A 2>/dev/null || true
git diff --quiet HEAD 2>/dev/null || git commit -m "Auto-save after iteration $ITERATION" 2>/dev/null || true
git push origin HEAD 2>/dev/null && echo "Pushed to backup" || echo "Push failed (continuing)"
fi
}
# ============================================================================
# COMPLETION DETECTION (runs on HOST)
# ============================================================================
check_complete() {
if [ ! -f "$PLAN_FILE" ]; then
return 1
fi
local incomplete=$(grep -c '^\s*- \[ \]' "$PLAN_FILE" 2>/dev/null || echo "0")
if [ "$incomplete" -eq 0 ]; then
local completed=$(grep -c '^\s*- \[x\]' "$PLAN_FILE" 2>/dev/null || echo "0")
[ "$completed" -gt 0 ] && return 0
fi
return 1
}
# ============================================================================
# MAIN
# ============================================================================
# Select prompt
if [ "$MODE" = "plan" ]; then
PROMPT_FILE="PROMPT_plan.md"
echo "Ralph Planning Mode (Docker)"
else
PROMPT_FILE="PROMPT_build.md"
echo "Ralph Building Mode (Docker)"
fi
if [ ! -f "$PROMPT_FILE" ]; then
echo "Error: $PROMPT_FILE not found"
exit 1
fi
echo "Project: $PROJECT_DIR"
echo "Model: $MODEL"
[ -n "$LIMIT" ] && echo "Limit: $LIMIT" || echo "Limit: until complete"
echo ""
setup_remote_backup
echo ""
echo "Starting loop..."
echo "---"
echo "=== Ralph Docker $(date '+%Y-%m-%d %H:%M:%S') ===" > "$LOG_FILE"
ITERATION=0
while true; do
ITERATION=$((ITERATION + 1))
echo ""
echo "Iteration $ITERATION - $(date '+%H:%M:%S')"
# Check completion (build mode only)
if [ "$MODE" = "build" ] && check_complete; then
echo "ALL TASKS COMPLETE"
push_to_backup
exit 0
fi
# Check limit
if [ -n "$LIMIT" ] && [ "$ITERATION" -gt "$LIMIT" ]; then
echo "Reached limit ($LIMIT)"
push_to_backup
exit 0
fi
# Run single iteration in Docker
# Container runs ONE iteration, then exits
# Backup runs on HOST after container exits
# Note: MODEL is already validated against whitelist above
if docker run --rm \
-v "$PROJECT_DIR:/workspace" \
-w /workspace \
-e "CLAUDE_CODE_OAUTH_TOKEN=$CLAUDE_CODE_OAUTH_TOKEN" \
"$IMAGE_NAME" \
bash -c "cat '$PROMPT_FILE' | claude --model '$MODEL' -p --dangerously-skip-permissions --output-format text" \
2>&1 | tee -a "$LOG_FILE"; then
echo "Iteration $ITERATION complete"
# Push to backup ON HOST (has gh auth)
push_to_backup
else
echo "Claude exited with error"
push_to_backup
exit 1
fi
sleep 1
done
#!/bin/bash
# Ralph Wiggum Loop - Autonomous AI Coding
# Based on Geoffrey Huntley's original technique
set -e # Exit on error
# Verify Claude CLI is installed
if ! command -v claude &>/dev/null; then
echo "Error: Claude CLI not found"
echo "Install with: npm install -g @anthropic-ai/claude-code"
exit 1
fi
# Cross-platform sed -i wrapper (macOS vs Linux compatibility)
sed_i() {
if [[ "$OSTYPE" == "darwin"* ]]; then
sed -i '' "$@"
else
sed -i "$@"
fi
}
# Configuration
MODEL="${RALPH_MODEL:-opus}"
VERBOSE="${RALPH_VERBOSE:-false}"
# Validate model against whitelist (security: prevents command injection)
validate_model() {
local model="$1"
case "$model" in
opus|sonnet|haiku) return 0 ;;
*)
echo "Error: Invalid model '$model'. Allowed: opus, sonnet, haiku"
exit 1
;;
esac
}
validate_model "$MODEL"
MAX_STUCK="${RALPH_MAX_STUCK:-3}" # Max failures on same task before skipping
PLAN_FILE="IMPLEMENTATION_PLAN.md"
REPORT_FILE="REPORT.md"
LOG_FILE="ralph.log"
START_TIME=$(date +%s)
BACKUP_ENABLED="${RALPH_BACKUP:-true}" # Push to remote after each commit
PROJECT_NAME=$(basename "$(pwd)")
# Load OAuth token for headless mode (with security checks)
TOKEN_FILE="$HOME/.claude-oauth-token"
if [ -z "$CLAUDE_CODE_OAUTH_TOKEN" ] && [ -f "$TOKEN_FILE" ]; then
# Security: Check file permissions (should be 600 or more restrictive)
if [[ "$OSTYPE" == "darwin"* ]]; then
TOKEN_PERMS=$(stat -f %Lp "$TOKEN_FILE" 2>/dev/null)
else
TOKEN_PERMS=$(stat -c %a "$TOKEN_FILE" 2>/dev/null)
fi
if [ -n "$TOKEN_PERMS" ]; then
# Check if group or others have any permissions
if [ "$((TOKEN_PERMS % 100))" -ne 0 ]; then
echo "⚠️ Security warning: $TOKEN_FILE has insecure permissions ($TOKEN_PERMS)"
echo " Run: chmod 600 $TOKEN_FILE"
echo ""
fi
fi
export CLAUDE_CODE_OAUTH_TOKEN=$(cat "$TOKEN_FILE")
fi
if [ -z "$CLAUDE_CODE_OAUTH_TOKEN" ]; then
echo "⚠️ Warning: No OAuth token found. Headless mode may fail."
echo " Run 'claude setup-token' and save to ~/.claude-oauth-token"
echo " Then: chmod 600 ~/.claude-oauth-token"
echo ""
fi
# Parse arguments
MODE="build"
LIMIT=""
while [[ $# -gt 0 ]]; do
case $1 in
plan)
MODE="plan"
shift
;;
[0-9]*)
LIMIT=$1
shift
;;
--verbose)
VERBOSE=true
shift
;;
--model)
MODEL=$2
validate_model "$MODEL"
shift 2
;;
*)
echo "Usage: $0 [plan] [limit] [--verbose] [--model opus|sonnet]"
echo ""
echo "Examples:"
echo " $0 # Build mode, unlimited (exits when all tasks done)"
echo " $0 20 # Build mode, max 20 iterations"
echo " $0 plan # Plan mode, exits when plan is complete"
echo " $0 plan 5 # Plan mode, max 5 iterations"
echo " $0 --verbose # Enable verbose logging"
echo " $0 --model sonnet # Use Sonnet instead of Opus"
echo ""
echo "Environment variables:"
echo " RALPH_MODEL=opus|sonnet Default model"
echo " RALPH_MAX_STUCK=3 Max failures before skipping task"
exit 1
;;
esac
done
# ============================================================================
# REMOTE BACKUP SETUP
# ============================================================================
setup_remote_backup() {
if [ "$BACKUP_ENABLED" != "true" ]; then
echo "Remote backup: disabled (set RALPH_BACKUP=true to enable)"
return 0
fi
# Check if git repo exists
if [ ! -d ".git" ]; then
echo "Initializing git repository..."
git init
git add -A
git commit -m "Initial commit" 2>/dev/null || true
fi
# Check if remote exists
if git remote get-url origin &>/dev/null; then
echo "Remote backup: $(git remote get-url origin)"
return 0
fi
# Check if gh CLI is available and authenticated
if ! command -v gh &>/dev/null; then
echo "Warning: gh CLI not found. Remote backup disabled."
echo "Install: https://cli.github.com/"
BACKUP_ENABLED="false"
return 1
fi
if ! gh auth status &>/dev/null; then
echo "Warning: gh CLI not authenticated. Remote backup disabled."
echo "Run: gh auth login"
BACKUP_ENABLED="false"
return 1
fi
# Create private backup repo
local repo_name="${PROJECT_NAME}-ralph-backup"
echo "Creating private backup repo: $repo_name"
if gh repo create "$repo_name" --private --source=. --push 2>/dev/null; then
echo "Remote backup: https://github.com/$(gh api user -q .login)/$repo_name"
return 0
else
echo "Warning: Could not create backup repo. Remote backup disabled."
BACKUP_ENABLED="false"
return 1
fi
}
push_to_backup() {
if [ "$BACKUP_ENABLED" != "true" ]; then
return 0
fi
# Push to remote (suppress errors, don't fail the loop)
if git push origin HEAD 2>/dev/null; then
echo "📤 Pushed to remote backup"
else
echo "⚠️ Push to remote failed (continuing anyway)"
fi
}
# ============================================================================
# COMPLETION DETECTION
# ============================================================================
check_all_tasks_complete() {
if [ ! -f "$PLAN_FILE" ]; then
return 1 # No plan file, not complete
fi
# Count incomplete tasks (lines with "- [ ]")
local incomplete=$(grep -c '^\s*- \[ \]' "$PLAN_FILE" 2>/dev/null || echo "0")
if [ "$incomplete" -eq 0 ]; then
# Double-check there are actually completed tasks
local completed=$(grep -c '^\s*- \[x\]' "$PLAN_FILE" 2>/dev/null || echo "0")
if [ "$completed" -gt 0 ]; then
return 0 # All tasks complete
fi
fi
return 1 # Still have incomplete tasks
}
get_current_task() {
if [ ! -f "$PLAN_FILE" ]; then
echo ""
return
fi
# Get first incomplete task
grep '^\s*- \[ \]' "$PLAN_FILE" 2>/dev/null | head -1 | sed 's/.*- \[ \] //' || echo ""
}
# ============================================================================
# STUCK DETECTION
# ============================================================================
STUCK_FILE=".ralph_stuck_tracker"
LAST_TASK=""
STUCK_COUNT=0
init_stuck_tracker() {
if [ -f "$STUCK_FILE" ]; then
# Security: Use safe parsing instead of source (prevents shell injection)
LAST_TASK=$(grep "^LAST_TASK=" "$STUCK_FILE" 2>/dev/null | cut -d'"' -f2 || echo "")
STUCK_COUNT=$(grep "^STUCK_COUNT=" "$STUCK_FILE" 2>/dev/null | cut -d= -f2 || echo "0")
# Ensure STUCK_COUNT is a number
[[ "$STUCK_COUNT" =~ ^[0-9]+$ ]] || STUCK_COUNT=0
else
LAST_TASK=""
STUCK_COUNT=0
fi
}
update_stuck_tracker() {
local current_task="$1"
if [ "$current_task" = "$LAST_TASK" ] && [ -n "$current_task" ]; then
STUCK_COUNT=$((STUCK_COUNT + 1))
else
LAST_TASK="$current_task"
STUCK_COUNT=1
fi
echo "LAST_TASK=\"$LAST_TASK\"" > "$STUCK_FILE"
echo "STUCK_COUNT=$STUCK_COUNT" >> "$STUCK_FILE"
}
is_stuck() {
[ "$STUCK_COUNT" -ge "$MAX_STUCK" ]
}
skip_stuck_task() {
local task="$1"
echo ""
echo "STUCK: Failed $MAX_STUCK times on: $task"
echo "Marking as blocked and moving on..."
# Add to blockers section or create it
# Note: We append to end instead of inserting after header (simpler, more portable)
if ! grep -q "^## Blocked" "$PLAN_FILE" 2>/dev/null; then
# Create Blocked section at end
echo "" >> "$PLAN_FILE"
echo "## Blocked" >> "$PLAN_FILE"
echo "" >> "$PLAN_FILE"
fi
echo "- $task (stuck after $MAX_STUCK attempts)" >> "$PLAN_FILE"
# Mark the task as skipped in place (change [ ] to [S])
# Escape regex metacharacters in task name for safe substitution
local escaped_task
escaped_task=$(printf '%s\n' "$task" | sed 's/[[\.*^$()+?{|/]/\\&/g')
sed_i "s/- \[ \] ${escaped_task}/- [S] $task/" "$PLAN_FILE"
# Reset stuck counter
LAST_TASK=""
STUCK_COUNT=0
echo "LAST_TASK=\"\"" > "$STUCK_FILE"
echo "STUCK_COUNT=0" >> "$STUCK_FILE"
}
# ============================================================================
# ITERATION SUMMARY
# ============================================================================
print_iteration_summary() {
local iteration_start="$1"
local iteration_end=$(date +%s)
local duration=$((iteration_end - iteration_start))
local mins=$((duration / 60))
local secs=$((duration % 60))
# Get the last commit (if any new one was made)
local last_commit=$(git log -1 --format="%h %s" 2>/dev/null || echo "")
local last_commit_time=$(git log -1 --format="%ct" 2>/dev/null || echo "0")
# Check if commit was made during this iteration
local commit_msg=""
if [ "$last_commit_time" -ge "$iteration_start" ]; then
commit_msg="$last_commit"
fi
# Get files changed in last commit
local files_new=0
local files_modified=0
local new_files=""
local modified_files=""
if [ -n "$commit_msg" ]; then
new_files=$(git diff-tree --no-commit-id --name-status -r HEAD 2>/dev/null | grep "^A" | cut -f2 || echo "")
modified_files=$(git diff-tree --no-commit-id --name-status -r HEAD 2>/dev/null | grep "^M" | cut -f2 || echo "")
files_new=$(echo "$new_files" | grep -c . 2>/dev/null || echo "0")
files_modified=$(echo "$modified_files" | grep -c . 2>/dev/null || echo "0")
fi
# Get progress
local completed=$(grep -c '^\s*- \[x\]' "$PLAN_FILE" 2>/dev/null || echo "0")
local total_tasks=$(grep -c '^\s*- \[' "$PLAN_FILE" 2>/dev/null || echo "0")
local pct=0
if [ "$total_tasks" -gt 0 ]; then
pct=$((completed * 100 / total_tasks))
fi
echo ""
echo "━━━ Iteration $ITERATION Complete (${mins}m ${secs}s) ━━━"
if [ -n "$commit_msg" ]; then
echo "✅ Commit: $commit_msg"
echo "📁 Files: +$files_new new, ~$files_modified modified"
# Show new files
if [ -n "$new_files" ]; then
echo "$new_files" | while read -r f; do
[ -n "$f" ] && echo " 🆕 $f"
done
fi
# Show modified files (limit to 5)
if [ -n "$modified_files" ]; then
echo "$modified_files" | head -5 | while read -r f; do
[ -n "$f" ] && echo " ✏️ $f"
done
local mod_count=$(echo "$modified_files" | wc -l | tr -d ' ')
if [ "$mod_count" -gt 5 ]; then
echo " ... and $((mod_count - 5)) more"
fi
fi
else
echo "⚠️ No commit this iteration"
fi
echo "📊 Progress: $completed/$total_tasks tasks ($pct%)"
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
}
# ============================================================================
# SUMMARY REPORT
# ============================================================================
generate_report() {
local end_time=$(date +%s)
local duration=$((end_time - START_TIME))
local minutes=$((duration / 60))
local seconds=$((duration % 60))
local completed=$(grep -c '^\s*- \[x\]' "$PLAN_FILE" 2>/dev/null || echo "0")
local skipped=$(grep -c '^\s*- \[S\]' "$PLAN_FILE" 2>/dev/null || echo "0")
local remaining=$(grep -c '^\s*- \[ \]' "$PLAN_FILE" 2>/dev/null || echo "0")
local total=$((completed + skipped + remaining))
local commit_count=$(git rev-list --count HEAD 2>/dev/null || echo "0")
local files_changed=$(git diff --name-only $(git rev-list --max-parents=0 HEAD 2>/dev/null) HEAD 2>/dev/null | wc -l | tr -d ' ' || echo "0")
cat > "$REPORT_FILE" << EOF
# Ralph Session Report
Generated: $(date '+%Y-%m-%d %H:%M:%S')
## Summary
| Metric | Value |
|--------|-------|
| Duration | ${minutes}m ${seconds}s |
| Iterations | $ITERATION |
| Tasks Completed | $completed / $total |
| Tasks Skipped | $skipped |
| Tasks Remaining | $remaining |
| Commits | $commit_count |
| Files Changed | $files_changed |
## Exit Reason
EOF
case "$1" in
"complete")
echo "All tasks completed successfully." >> "$REPORT_FILE"
;;
"limit")
echo "Reached iteration limit ($LIMIT)." >> "$REPORT_FILE"
;;
"interrupted")
echo "Manually interrupted (Ctrl+C)." >> "$REPORT_FILE"
;;
"error")
echo "Exited due to error (code $2)." >> "$REPORT_FILE"
;;
*)
echo "Unknown exit reason." >> "$REPORT_FILE"
;;
esac
# Add completed tasks
echo "" >> "$REPORT_FILE"
echo "## Completed Tasks" >> "$REPORT_FILE"
echo "" >> "$REPORT_FILE"
grep '^\s*- \[x\]' "$PLAN_FILE" 2>/dev/null | sed 's/- \[x\]/- ✓/' >> "$REPORT_FILE" || echo "None" >> "$REPORT_FILE"
# Add skipped tasks if any
if [ "$skipped" -gt 0 ]; then
echo "" >> "$REPORT_FILE"
echo "## Skipped Tasks (stuck)" >> "$REPORT_FILE"
echo "" >> "$REPORT_FILE"
grep '^\s*- \[S\]' "$PLAN_FILE" 2>/dev/null | sed 's/- \[S\]/- ⚠/' >> "$REPORT_FILE"
fi
# Add remaining tasks if any
if [ "$remaining" -gt 0 ]; then
echo "" >> "$REPORT_FILE"
echo "## Remaining Tasks" >> "$REPORT_FILE"
echo "" >> "$REPORT_FILE"
grep '^\s*- \[ \]' "$PLAN_FILE" 2>/dev/null >> "$REPORT_FILE"
fi
# Add recent commits
echo "" >> "$REPORT_FILE"
echo "## Recent Commits" >> "$REPORT_FILE"
echo "" >> "$REPORT_FILE"
echo '```' >> "$REPORT_FILE"
git log --oneline -20 2>/dev/null >> "$REPORT_FILE" || echo "No git history" >> "$REPORT_FILE"
echo '```' >> "$REPORT_FILE"
echo ""
echo "Report saved to $REPORT_FILE"
}
# ============================================================================
# CLEANUP ON EXIT
# ============================================================================
cleanup() {
local exit_reason="$1"
local exit_code="${2:-0}"
echo ""
echo "============================================"
if [ "$MODE" = "build" ]; then
generate_report "$exit_reason" "$exit_code"
fi
# Clean up stuck tracker
rm -f "$STUCK_FILE"
echo "============================================"
}
trap 'cleanup "interrupted"; exit 130' INT
trap 'cleanup "error" "$?"; exit $?' ERR
# ============================================================================
# MAIN LOOP
# ============================================================================
# Select prompt file based on mode
if [ "$MODE" = "plan" ]; then
PROMPT_FILE="PROMPT_plan.md"
echo "Ralph Planning Mode"
else
PROMPT_FILE="PROMPT_build.md"
echo "Ralph Building Mode"
# Verify plan file exists before starting build mode
if [ ! -f "$PLAN_FILE" ]; then
echo ""
echo "Error: $PLAN_FILE not found"
echo "Run './loop.sh plan' first to generate the implementation plan."
exit 1
fi
init_stuck_tracker
fi
# Check prompt file exists
if [ ! -f "$PROMPT_FILE" ]; then
echo "Error: $PROMPT_FILE not found"
echo "Run setup to create prompt files"
exit 1
fi
# Build Claude CLI command as array (security: avoids eval injection)
CLAUDE_ARGS=("--model" "$MODEL" "-p" "--dangerously-skip-permissions" "--output-format" "text")
if [ "$VERBOSE" = "true" ]; then
CLAUDE_ARGS+=("--verbose")
fi
# Display configuration
echo "Model: $MODEL"
echo "Claude args: ${CLAUDE_ARGS[*]}"
echo "Prompt: $PROMPT_FILE"
if [ -n "$LIMIT" ]; then
echo "Limit: $LIMIT iterations"
else
echo "Limit: until complete (Ctrl+C to stop)"
fi
echo "Stuck threshold: $MAX_STUCK failures"
echo "Log file: $LOG_FILE (tail -f to watch)"
echo ""
# Setup remote backup (creates private GitHub repo if needed)
setup_remote_backup
echo ""
echo "Starting loop..."
echo "---"
echo ""
# Initialize log file
echo "=== Ralph Session Started $(date '+%Y-%m-%d %H:%M:%S') ===" > "$LOG_FILE"
echo "Mode: $MODE | Model: $MODEL" >> "$LOG_FILE"
echo "" >> "$LOG_FILE"
# Run the loop
ITERATION=0
while true; do
ITERATION=$((ITERATION + 1))
ITERATION_START=$(date +%s)
echo "📍 Iteration $ITERATION - $(date '+%Y-%m-%d %H:%M:%S')"
# BUILD MODE: Check completion before each iteration
if [ "$MODE" = "build" ]; then
if check_all_tasks_complete; then
echo ""
echo "ALL TASKS COMPLETE"
cleanup "complete"
exit 0
fi
# Get current task for stuck detection
current_task=$(get_current_task)
update_stuck_tracker "$current_task"
# Check if stuck
if is_stuck; then
skip_stuck_task "$current_task"
continue # Try next iteration with new task
fi
echo "Current task: $current_task"
fi
# Check iteration limit
if [ -n "$LIMIT" ] && [ "$ITERATION" -gt "$LIMIT" ]; then
echo ""
echo "Reached iteration limit ($LIMIT)"
cleanup "limit"
exit 0
fi
# Run Claude with prompt (tee to log file for observability)
# Watch progress: tail -f ralph.log
if cat "$PROMPT_FILE" | claude "${CLAUDE_ARGS[@]}" 2>&1 | tee -a "$LOG_FILE"; then
# Print iteration summary in build mode
if [ "$MODE" = "build" ]; then
print_iteration_summary "$ITERATION_START"
# Push to remote backup after each successful iteration
push_to_backup
else
echo "✓ Iteration $ITERATION complete"
fi
else
EXIT_CODE=$?
echo ""
echo "❌ Claude exited with code $EXIT_CODE"
cleanup "error" "$EXIT_CODE"
exit $EXIT_CODE
fi
echo ""
sleep 1
done
Building Mode
You are Ralph, an autonomous coding agent in building mode.
CRITICAL SAFETY RULES
NEVER delete:
- Project root directory (
.,.., or absolute path to project) .git/directorysrc/,specs/,.planning/directories- Home directory (
~,$HOME) - Any path stored in a variable without first verifying it
Safe deletion requires:
- Explicit, hardcoded paths (not unverified variables)
- Paths you created this iteration
- Temp directories created with
mktemp -d - Build artifacts only (
dist/,node_modules/,.cache/)
Before any `rm -rf`: 1. Echo the path first to verify: echo "Will delete: $path" 2. Confirm it's not a critical directory 3. Prefer /tmp/... paths over ./... paths
When running tests:
- Tests MUST operate in isolated temp directories
- Use
mktemp -dfor test working directories - NEVER run test cleanup in the main project directory
- If a test clones the project, verify paths before any delete
Objective
Select the most important task from the implementation plan, implement it correctly, validate it works, and commit.
Process
0a. Study specs/ (use up to 500 parallel Sonnet subagents) 0b. Study @IMPLEMENTATION_PLAN.md 0c. Study @AGENTS.md (if exists) 0d. Reference: src/ (use parallel Sonnet subagents for code reading)
1. Select Task
- Pick the most important uncompleted task from IMPLEMENTATION_PLAN.md
- Most important = most foundational or highest priority
- Only ONE task per iteration
2. Investigate Before Implementing
- Search codebase first (don't assume missing)
- Understand existing patterns and conventions
- Use up to 500 Sonnet subagents for reading/searching
- Study similar existing implementations
- Identify exactly what needs to change
3. Implement
- Follow patterns from existing code
- Reference specs for requirements
- Write clean, maintainable code
- Match existing code style and conventions
- Add tests if they don't exist for new functionality
4. Validate
- Run: {{VALIDATION_COMMANDS}}
- Use only 1 Sonnet subagent for build/tests (creates backpressure)
- If validation fails, investigate and fix
- Do not commit until all validation passes
- If repeatedly failing, note in plan and move to next task
5. Update Plan
- Mark completed task with [x] in IMPLEMENTATION_PLAN.md
- Add any new tasks discovered during implementation
- Note any blockers or issues found
- Update task descriptions if understanding changed
6. Commit
- Write descriptive commit message
- Format: "[component] brief description of what changed"
- Include Co-Authored-By line:
Co-Authored-By: Ralph Wiggum <ralph@autonomous.ai>
- Push changes if remote configured
7. Exit
- End this loop iteration
- Next iteration will have fresh context
Success Criteria
- Exactly one task completed per iteration
- All validation passes before commit
- Changes committed with clear message
- Plan updated to reflect progress
- Any new discoveries added to plan
Planning Mode
You are Ralph, an autonomous coding agent in planning mode.
Objective
Study specifications and existing code, then generate a prioritized implementation plan. DO NOT implement anything.
Process
0a. Study specs/ (use up to 250 parallel Sonnet subagents) 0b. Study @IMPLEMENTATION_PLAN.md (if exists) 0c. Study src/lib/ (shared utilities to understand patterns) 0d. Reference: src/* (as needed for gap analysis)
1. Gap Analysis
- Compare each spec against existing code
- Identify what's missing, incomplete, or incorrect
- IMPORTANT: Don't assume not implemented; confirm with code search first
- Consider TODO comments, placeholders, and partial implementations
- Think deeply about dependencies and ordering
2. Generate/Update IMPLEMENTATION_PLAN.md
- Prioritized list of tasks
- Most important/foundational work first
- Each task should be completable in one loop iteration
- Include brief context for why each task matters
- Format:
## Priority 1: [Category]
- [ ] Task description (why: context)
## Priority 2: [Category]
- [ ] Task description (why: context)3. Exit
- Do NOT implement anything
- Do NOT commit anything
- Just generate the plan and exit
Success Criteria
- IMPLEMENTATION_PLAN.md exists and is prioritized
- Each task is specific and actionable
- Plan reflects actual gaps (confirmed via code search)
- Tasks are ordered by dependency and importance
- No code changes made
Workflow: Customize Ralph Loop
<required_reading> Read these reference files NOW: 1. references/prompt-design.md 2. references/validation-strategy.md 3. references/operational-learnings.md </required_reading>
<process>
Step 1: Identify Customization Goal
Ask the user using AskUserQuestion: "What would you like to customize?"
Options: 1. Prompts - Modify PROMPT_plan.md or PROMPT_build.md 2. Validation - Change test/lint/build commands 3. Loop behavior - Model, limits, stuck detection, backup 4. AGENTS.md - Add project-specific learnings
Step 2: Handle Based on Selection
If "Prompts":
Ask: "Which prompt do you want to modify?"
- Planning prompt - PROMPT_plan.md
- Building prompt - PROMPT_build.md
- Both - I'll guide you through each
For each selected prompt:
1. Read the current prompt file 2. Ask: "What behavior do you want to change?"
- Ralph keeps missing something → Add specific instruction
- Ralph does too much per iteration → Add clearer exit criteria
- Ralph uses wrong patterns → Add pattern guidance
- Subagent counts need adjustment → Update parallelism numbers
- Other (describe)
3. Apply the principle: Start minimal, evolve through observation
- Don't add rules you haven't seen need for
- Add ONE change at a time
- Test the change with a few iterations
- If it helps, keep it; if not, remove it
4. Make the edit and explain:
Added to [prompt file]:
[The change]
Why: [Observation that led to this]
Watch for: [How to know if it's working]If "Validation":
1. Read current PROMPT_build.md to find validation section 2. Ask: "What validation changes do you need?"
- Add tests - Run additional test command
- Add type checking - Add tsc/mypy/etc
- Add linting - Add eslint/ruff/etc
- Add build - Add build verification
- Remove validation - Validation is too slow
- Custom command - I'll specify
3. For additions, update the validation section in PROMPT_build.md:
4. Validate
- Run: [commands]
- If validation fails, investigate and fix
- Do not commit until all validation passes4. Warn about removing validation:
Removing validation reduces backpressure. Ralph may:
- Produce code that doesn't work
- Accumulate errors across iterations
- Go off track without feedback
Only remove validation if you're certain it's not needed.If "Loop behavior":
Ask: "What loop setting do you want to change?"
- Model - Switch between opus/sonnet/haiku
- Iteration limit - Set max iterations
- Stuck detection - Change failure threshold
- Remote backup - Enable/disable GitHub push
- Verbosity - More/less output
For each:
Model:
# In loop.sh or via command line
./loop.sh --model sonnet # Faster, cheaper
./loop.sh --model opus # More capable (default)
# Or set default in environment
export RALPH_MODEL=sonnetGuidance:
- opus: Best for complex reasoning, architecture decisions
- sonnet: Good for straightforward implementation tasks
- haiku: Fast for simple tasks (not recommended for Ralph)
Iteration limit:
./loop.sh 20 # Build mode, max 20 tasks
./loop.sh plan 5 # Plan mode, max 5 iterationsDefault is unlimited (runs until complete or Ctrl+C).
Stuck detection:
export RALPH_MAX_STUCK=5 # Fail 5 times before skipping (default: 3)Note: Stuck detection auto-skips tasks. If you prefer manual intervention, set high value or watch the loop.
Remote backup:
export RALPH_BACKUP=false # Disable auto-push to GitHub
export RALPH_BACKUP=true # Enable (default)Verbosity:
./loop.sh --verbose # More detailed Claude outputIf "AGENTS.md":
1. Read current AGENTS.md 2. Ask: "What pattern or learning do you want to add?"
- Build/test command - How to run validation
- Code pattern - Where things go, how they're structured
- Constraint - What NOT to do
- Gotcha - Non-obvious behavior to remember
3. Apply the entry following the format:
## [Section]
### [Topic]
[Concise guidance - 1-3 lines]4. Remind the user:
AGENTS.md best practices:
- Keep entries concise (1-3 lines)
- Add only after observing repeated issues
- Remove entries that become stale
- Don't duplicate what's in specsStep 3: Verify and Test
After making changes:
1. Summarize what was changed 2. Suggest testing:
To test this change:
1. Run: ./loop.sh [plan|build] 1 # Single iteration
2. Watch the behavior
3. If good, continue; if not, revert with:
git checkout [file]Step 4: Offer Follow-up
Ask: "Would you like to:" 1. Make another customization - Return to Step 1 2. Run the loop to test - Exit and let user run 3. Return to main menu - Done customizing </process>
<success_criteria> This workflow is complete when:
- [ ] User identified what to customize
- [ ] Appropriate changes made or guidance provided
- [ ] User understands how to test the changes
- [ ] User knows how to revert if needed
</success_criteria>
Workflow: Set Up New Ralph Loop
<required_reading> Read these reference files NOW: 1. references/ralph-fundamentals.md 2. references/project-structure.md 3. references/prompt-design.md </required_reading>
<process>
Step 1: Confirm Directory
Ask the user: "Which directory should I set up Ralph in? (provide absolute path, or I'll use current working directory)"
Wait for response. If no path provided, use current working directory from environment.
Step 2: Verify Directory Safety
Check if directory already has Ralph setup:
- Look for
loop.sh,PROMPT_plan.md,PROMPT_build.md, orIMPLEMENTATION_PLAN.md - If found, ask: "This directory appears to have Ralph files already. Overwrite? (yes/no)"
- If no, exit workflow
Step 3: Security Warning
Display to user before proceeding:
⚠️ SECURITY NOTICE
Ralph runs with --dangerously-skip-permissions, meaning it executes
commands without confirmation. This is powerful but risky.
RECOMMENDED: Run Ralph in Docker for isolation.
- Limits filesystem access to project directory
- Prevents accidental system modifications
- Sandboxes network and process execution
NON-DOCKER: Run at your own risk.
- Full access to your system as your user
- Can modify any files you can modify
- Only use in trusted, isolated environmentsStep 4: Gather Project Context
Ask the user 2-4 questions using AskUserQuestion:
Question 1 (Required): "What programming language/framework is this project using?"
- Options based on common stacks (Node.js/TypeScript, Python, Go, Rust, etc.)
- This determines test commands and backpressure mechanisms
Question 2 (Required): "What kind of backpressure should Ralph use?"
- Option 1: Tests only - Unit/integration tests must pass
- Option 2: Tests + type checking - Tests and type checker (TypeScript, mypy, etc.)
- Option 3: Full validation - Tests, type checking, linting, builds
- Option 4: Custom commands - I'll specify validation commands
Question 3 (Conditional): If custom commands selected: "What validation commands should Ralph run?"
- Free text input for custom commands
Question 4 (Optional): "Do you already have specification files?"
- Yes, in specs/ directory
- Yes, but elsewhere (I'll specify)
- No, I'll create them as I go
- No, help me create initial specs
Question 5 (Required): "Run Ralph in Docker for isolation?"
- Option 1: Yes, Docker mode (Recommended) - Isolated container, safer execution, requires OAuth token setup
- Option 2: No, run directly - Faster but runs with full host access. Use at your own risk.
If Docker mode selected, check for OAuth token: 1. Check $CLAUDE_CODE_OAUTH_TOKEN env var 2. Check ~/.claude-oauth-token file 3. If neither found, instruct user: "Run claude setup-token and save to ~/.claude-oauth-token"
Step 5: Create Directory Structure
Create the following structure in target directory:
mkdir -p specs srcEssential files:
loop.sh- Main orchestration script (from templates/loop.sh)PROMPT_plan.md- Planning mode instructions (from templates/PROMPT_plan.md)PROMPT_build.md- Building mode instructions (from templates/PROMPT_build.md)AGENTS.md- Operational learnings (initially empty or minimal)IMPLEMENTATION_PLAN.md- Task list (initially empty, generated by planning mode)
Docker mode additional files (if selected):
Dockerfile- Container definition (from templates/Dockerfile)loop-docker.sh- Docker-wrapped loop script (from templates/loop-docker.sh)
Directories:
specs/- Requirement documents (one per topic of concern)src/- Application source code
Step 6: Generate Loop Script
Use templates/loop.sh and customize:
- Set Claude model (default:
opusfor reasoning, can usesonnetfor speed) - Configure CLI flags based on user preferences
- Add validation commands based on backpressure choice
Step 7: Generate Planning Prompt
Use templates/PROMPT_plan.md and customize:
- Adjust subagent counts based on project size
- Reference appropriate source directories
- Include project-specific context if provided
Step 8: Generate Building Prompt
Use templates/PROMPT_build.md and customize:
- Set validation commands based on backpressure choice
- Configure subagent limits
- Add project-specific build/test instructions
Step 9: Initialize AGENTS.md
Create minimal AGENTS.md:
# Operational Learnings
This file contains project-specific guidance that Ralph has learned through observation.
Start minimal. Add entries only when Ralph exhibits repeated failures or needs specific guidance.
## Build/Test Commands
[To be filled as needed]
## Known Patterns
[To be filled as needed]
## Constraints
[To be filled as needed]Step 10: Make Loop Executable
chmod +x loop.shDocker mode: Also make loop-docker.sh executable:
chmod +x loop-docker.shStep 11: Provide Usage Instructions
Display to user:
Ralph loop initialized in [directory]!
NEXT STEPS:
1. Create specification files in specs/:
- One file per topic of concern
- Use "one sentence without 'and'" test for scope
- Example: specs/authentication.md, specs/color-extraction.md
2. Start planning mode:
./loop.sh plan
This will:
- Study your specs
- Analyze existing code
- Generate IMPLEMENTATION_PLAN.md
- Exit when plan is complete
3. Start building mode:
./loop.sh
This will:
- Pick most important task from plan
- Implement it
- Run validation ([validation_commands])
- Commit changes
- Loop until stopped (Ctrl+C)
4. Limit iterations (optional):
./loop.sh 20 # Build mode, 20 tasks max
./loop.sh plan 5 # Plan mode, 5 iterations
IMPORTANT:
- Your role: Sit on the loop, not in it
- Watch for failure patterns
- Update AGENTS.md with learnings
- Regenerate plan if Ralph goes off track
- Use Ctrl+C to stop the loop anytime
SECURITY:
- Loop runs with --dangerously-skip-permissions
- Only run in trusted environments
- Use Docker mode for isolation: ./loop-docker.sh
- Minimum viable access to APIs and secrets
DOCKER MODE (if enabled):
- First run: ./loop-docker.sh --build-image
- Then: ./loop-docker.sh plan
- Then: ./loop-docker.sh
- Requires: ~/.claude-oauth-token or CLAUDE_CODE_OAUTH_TOKEN env var
- Get token: claude setup-token
FILES:
- loop.sh - Main orchestration script
- loop-docker.sh - Docker-wrapped loop (if Docker mode)
- Dockerfile - Container definition (if Docker mode)
- PROMPT_plan.md - Planning mode instructions
- PROMPT_build.md - Building mode instructions
- AGENTS.md - Operational learnings (update as needed)
- IMPLEMENTATION_PLAN.md - Generated task list
- specs/ - Your requirement documents
- src/ - Your application code
Need help? Check references/operational-learnings.md for guidance on:
- Writing effective specs
- Tuning prompts
- Adding backpressure
- Debugging loopsStep 12: Offer Spec Creation Help
Ask using AskUserQuestion: "Would you like help creating initial specification files?"
Options: 1. Yes, help me create specs - I'll guide you through defining requirements 2. No, I'll create them myself - I understand the spec structure 3. Show me an example spec - I want to see what a good spec looks like
If option 1 selected, route to workflow: create-initial-specs.md (create this workflow) If option 3 selected, display example from references/spec-examples.md (create this reference) </process>
<success_criteria> This workflow is complete when:
- [ ] Directory structure created with all required files
- [ ] loop.sh executable and customized for project
- [ ] PROMPT_plan.md generated with appropriate settings
- [ ] PROMPT_build.md generated with validation commands
- [ ] AGENTS.md initialized (empty or minimal)
- [ ] Usage instructions displayed to user
- [ ] User knows next steps (create specs, run loop)
- [ ] User offered help with spec creation
</success_criteria>
Workflow: Troubleshoot Ralph Loop
<required_reading> Read these reference files NOW: 1. references/ralph-fundamentals.md (escape hatches section) 2. references/validation-strategy.md (handling failures section) </required_reading>
<process>
Step 1: Identify the Problem
Ask the user using AskUserQuestion: "What issue are you experiencing?"
Options: 1. Ralph is stuck on a task - Same task failing repeatedly 2. Ralph went off track - Implementing wrong things 3. Validation keeps failing - Tests/builds won't pass 4. Loop won't start - Errors before first iteration 5. Performance issues - Too slow, using too many resources 6. Other - Describe the problem
Step 2: Diagnose and Fix
If "Ralph is stuck on a task":
Check: 1. Look at .ralph_stuck_tracker if it exists 2. Check ralph.log for recent output 3. Review IMPLEMENTATION_PLAN.md for the stuck task
Common causes and fixes:
Task is genuinely hard:
- Break it into smaller tasks in the plan
- Add more specific guidance to AGENTS.md
- Clarify the spec for that feature
Task description is ambiguous:
# Edit IMPLEMENTATION_PLAN.md to clarify the task
# Be specific: "Add login endpoint" → "Add POST /api/auth/login endpoint that validates credentials and returns JWT"Missing dependency:
- Check if another task should be done first
- Reorder priorities in the plan
Stuck detection triggered incorrectly:
# Reset the stuck tracker
rm .ralph_stuck_tracker
# Increase threshold if tasks legitimately need retries
export RALPH_MAX_STUCK=5
./loop.shIf "Ralph went off track":
The answer is usually: Regenerate the plan
# Stop the loop
Ctrl+C
# Review what Ralph did
git log --oneline -10
git diff HEAD~5..HEAD --stat
# If recent work is bad, revert
git reset --hard HEAD~[number]
# Regenerate plan from current state
rm IMPLEMENTATION_PLAN.md
./loop.sh planThen investigate WHY:
- Specs unclear? → Update specs
- Missing context? → Add to AGENTS.md
- Prompt too vague? → Add specific instructions
If "Validation keeps failing":
1. Read the error output:
# Check recent log
tail -100 ralph.log2. Common validation issues:
Test failures:
- Is the test correct? Sometimes specs changed but tests didn't
- Is Ralph implementing the wrong behavior?
- Add test-specific guidance to AGENTS.md
Type errors:
- Check if interfaces changed
- Ralph may be using outdated patterns
- Add type patterns to AGENTS.md
Lint errors:
- Often style issues Ralph can fix
- If lint is too strict, consider relaxing rules
- Or add lint-specific patterns to AGENTS.md
Build failures:
- Missing imports/dependencies
- Syntax errors
- Check if Ralph is generating valid code for your framework
3. If Ralph can't fix it:
# Stop loop
Ctrl+C
# Fix manually
[make the fix]
# Commit the fix
git add . && git commit -m "Manual fix: [description]"
# Add learning to prevent recurrence
# Edit AGENTS.md with what you learned
# Resume
./loop.shIf "Loop won't start":
Check prompt files exist:
ls -la PROMPT_plan.md PROMPT_build.mdIf missing, run setup again or create from templates.
Check Claude CLI:
claude --versionIf not found: npm install -g @anthropic-ai/claude-code
Check OAuth token (for headless mode):
# Verify token exists
cat ~/.claude-oauth-token
# If missing, run:
claude setup-token
# Save to ~/.claude-oauth-token
# Set permissions
chmod 600 ~/.claude-oauth-tokenCheck plan file for build mode:
ls IMPLEMENTATION_PLAN.mdIf missing, run ./loop.sh plan first.
Check permissions:
chmod +x loop.shIf "Performance issues":
Too slow per iteration:
- Switch to Sonnet:
./loop.sh --model sonnet - Reduce validation: Remove slow checks from PROMPT_build.md
- Smaller tasks: Break tasks into smaller units
Using too many resources:
- Reduce subagent counts in prompts (250 → 50)
- Use Docker mode for isolation with resource limits:
# In loop-docker.sh, docker run could add:
# --memory=4g --cpus=2Too many API calls:
- Run fewer iterations:
./loop.sh 10 - Increase sleep between iterations (edit loop.sh)
- Use batch backup (reduce push frequency)
If "Other":
Ask user to describe the specific issue, then:
1. Check ralph.log for error messages 2. Check IMPLEMENTATION_PLAN.md for state 3. Check git log for recent changes 4. Check AGENTS.md for relevant guidance
Step 3: Emergency Escape Hatches
If nothing else works:
Stop everything:
Ctrl+CRevert all uncommitted changes:
git reset --hard HEADRevert to known good state:
git log --oneline -20 # Find good commit
git reset --hard [commit-hash]Start fresh with new plan:
rm IMPLEMENTATION_PLAN.md
rm .ralph_stuck_tracker
./loop.sh planNuclear option - start completely over:
# Keep your source code, reset Ralph state
rm IMPLEMENTATION_PLAN.md
rm AGENTS.md
rm .ralph_stuck_tracker
rm ralph.log
rm REPORT.md
# Reinitialize
# Edit PROMPT_*.md if needed
./loop.sh planStep 4: Prevent Recurrence
After fixing the issue:
1. Add to AGENTS.md if relevant pattern discovered 2. Update specs if requirements were unclear 3. Update prompts if Claude needed different instructions 4. Consider Docker mode if safety is a concern
Ask: "Would you like to:" 1. Add a learning to AGENTS.md - Document what went wrong 2. Update prompts - Change Claude's instructions 3. Resume the loop - Continue with the fix applied 4. Return to main menu - Done troubleshooting </process>
<success_criteria> This workflow is complete when:
- [ ] User's issue identified
- [ ] Diagnosis steps followed
- [ ] Fix applied or guidance provided
- [ ] Prevention steps discussed
- [ ] User can resume work
</success_criteria>
Workflow: Understand Ralph
<required_reading> Read these reference files NOW: 1. references/ralph-fundamentals.md </required_reading>
<process>
Step 1: Identify Learning Goal
Ask the user using AskUserQuestion: "What aspect of Ralph would you like to understand better?"
Options: 1. The core concept - What Ralph is and why it works 2. The three phases - Planning, building, and observation 3. Backpressure - How tests and validation steer Ralph 4. AGENTS.md - How to capture and evolve learnings 5. When to use Ralph - Is it right for my project?
Step 2: Explain Based on Selection
If "The core concept":
Explain:
Ralph is Geoffrey Huntley's autonomous coding technique. In its purest form:
while :; do cat PROMPT.md | claude ; done
That's it. 16 characters of bash plus a prompt file.
WHY IT WORKS:
1. Fresh context every iteration
- Each loop starts with clean 200K context window
- No accumulated history, no stale assumptions
- Forces decisions to be grounded in files on disk
2. File I/O as state
- IMPLEMENTATION_PLAN.md is the only persistent state
- Claude reads it, updates it, commits it
- No sophisticated orchestration needed
3. Backpressure as steering
- Tests, type checks, lints provide feedback
- If code doesn't pass validation, loop continues
- Quality is enforced, not hoped for
4. The loop is inevitable
- Given enough iterations, progress happens
- Bad iterations get rejected by validation
- Good iterations accumulate as commits
The insight: "Deterministically bad in an undeterministic world"
- Traditional AI coding fights probabilistic nature of LLMs
- Ralph embraces chaos by resetting context each iteration
- Plan on disk provides deterministic shared stateIf "The three phases":
Explain:
Ralph has three distinct phases:
PHASE 1: PLANNING
- Objective: Gap analysis only
- Input: Specs and existing code
- Output: IMPLEMENTATION_PLAN.md (prioritized TODO list)
- Rule: No implementation, no commits
- Key instruction: "Don't assume not implemented; confirm with code search"
Run with: ./loop.sh plan
PHASE 2: BUILDING
- Objective: Implement from the plan
- Input: Plan, specs, existing code
- Output: Code changes + commits
- Rule: One task per loop iteration
Process each iteration:
1. Select most important task
2. Search existing code (don't assume)
3. Implement functionality
4. Run validation
5. Update plan
6. Commit changes
7. Exit (fresh context next iteration)
Run with: ./loop.sh
PHASE 3: OBSERVATION (Your Role)
- Objective: Sit on the loop, not in it
- Action: Engineer the environment
You DO:
- Watch for failure patterns
- Update AGENTS.md with learnings
- Tune prompts based on observed behavior
- Regenerate plan when trajectory fails
- Add backpressure mechanisms
You DON'T:
- Jump into the loop to fix things
- Manually implement features
- Edit code directly
- Interfere with the autonomous process
The shift: From implementer to environment engineerIf "Backpressure":
Load references/validation-strategy.md then explain:
Backpressure is automated validation that rejects invalid work.
THE FEEDBACK LOOP:
1. Ralph implements task
2. Validation runs (tests, type checks, lints)
3. If fails → Ralph investigates and fixes
4. Loop continues until validation passes
5. Only then can Ralph commit and proceed
WITHOUT BACKPRESSURE: Ralph generates code that may not work
WITH BACKPRESSURE: Ralph must produce working code to progress
TYPES OF BACKPRESSURE:
Tests (most important)
- Binary pass/fail
- Aligned with requirements
- Fast feedback each iteration
Type checking
- Catches type errors before runtime
- Enforces interface contracts
- TypeScript: tsc --noEmit
- Python: mypy
Linting
- Enforces code style
- Catches common mistakes
- Start minimal, add rules as patterns emerge
Builds
- Catches syntax errors
- Verifies dependencies
VALIDATION LEVELS:
- Level 1: Tests only (fastest)
- Level 2: Tests + type checking (recommended)
- Level 3: Full validation (tests + types + lint + build)
If you have no tests, Ralph should create them as part of implementation.If "AGENTS.md":
Load references/operational-learnings.md then explain:
AGENTS.md captures project-specific learnings that Ralph needs.
START MINIMAL:Operational Learnings
That's literally enough to start. Don't pre-populate.
WHEN TO ADD:
1. Repeated mistakes
Ralph keeps reimplementing auth? Add:
"Always use src/lib/auth.ts for authentication"
2. Project-specific commands
Tests need special setup? Add:
"Run: export NODE_ENV=test && npm test"
3. Discovered constraints
Ralph keeps using wrong library? Add:
"Do NOT use lodash (not installed)"
4. Architectural decisions
Code in wrong places? Add:
"UI components: src/components/"
WHEN NOT TO ADD:
- One-off mistakes (wait for pattern)
- General best practices (Claude knows these)
- Things already in specs (don't duplicate)
- Temporary workarounds (fix root cause)
EVOLUTION:
- Days 1-3: Mostly empty, watching for patterns
- Week 1: First entries, build commands, constraints
- Weeks 2-4: Known patterns documented
- Month 2+: Stable, changes infrequentlyIf "When to use Ralph":
Explain:
RALPH WORKS BEST WHEN:
✓ You have clear specifications
- Written requirements Ralph can study
- Acceptance criteria defined
- One topic per spec file
✓ Your project has test coverage
- Tests create backpressure
- Ralph can validate its own work
- No tests = no feedback loop
✓ You can observe initially
- First 30+ minutes need watching
- Prompts evolve through observation
- Early failures inform AGENTS.md
✓ You want autonomous operation
- Overnight coding sessions
- Hands-off implementation
- Batch processing of tasks
RALPH IS NOT FOR:
✗ Exploratory coding
- No clear specs to implement
- "Figure out what we need" situations
- Creative/design-heavy work
✗ Projects without tests
- No validation = no steering
- Ralph may accumulate errors
- Add tests first, then use Ralph
✗ Quick one-off changes
- Loop overhead not worth it
- Just make the change directly
✗ Highly interactive work
- Constant human decisions needed
- Approval gates every step
- Design reviews mid-implementation
THE QUESTION TO ASK:
"Can I write specs clear enough that passing tests proves completion?"
If yes → Ralph can help
If no → Consider manual implementation or clarify specs firstStep 3: Offer Follow-up
Ask: "Would you like to:" 1. Learn about another concept - Continue exploring Ralph 2. Set up a Ralph loop - Route to setup-new-loop.md 3. Return to main menu - Done learning for now
If option 1, return to Step 1. If option 2, route to workflows/setup-new-loop.md. </process>
<success_criteria> This workflow is complete when:
- [ ] User selected a learning topic
- [ ] Relevant explanation provided with examples
- [ ] User offered follow-up options
- [ ] User understands enough to proceed or continue learning
</success_criteria>