Agentic coding loop runner for Claude CLI. Runs Claude in a loop with formatted streaming output, automatic git pushes, and spec file injection.
git clone https://github.com/wesburch/ralph-cli ~/.ralph
~/.ralph/install.sh# In your Dockerfile
RUN git clone https://github.com/wesburch/ralph-cli /opt/ralph \
&& /opt/ralph/install.shOr mount as a volume:
# docker-compose.yml
volumes:
- ~/.ralph:/opt/ralph:ro
- /opt/ralph/bin/ralph:/usr/local/bin/ralph:ro
- /opt/ralph/bin/stream-format:/usr/local/bin/stream-format:rocd ~/.ralph && git pull- Node.js - For the stream formatter
- Claude CLI - The
claudecommand must be available and authenticated
# 1. Install ralph
git clone https://github.com/wesburch/ralph-cli ~/.ralph && ~/.ralph/install.sh
# 2. Navigate to your project
cd your-project
# 3. Set up prompt files (in Claude Code)
/ralph-init
# 4. Create a spec for your feature
# (or use /spec if you have that skill installed)
# 5. Run the loop
ralph specs/my-feature.mdThe installer adds a Claude Code skill that generates customized prompt files for your project.
In Claude Code, run:
/ralph-init
/ralph-init my-project-name
- Analyzes your codebase - Detects tech stack, testing framework, patterns
- Interviews you - Asks about conventions, commands, guardrails
- Generates prompt files - Creates
PROMPT_plan.mdandPROMPT_build.md
| Stack | Frameworks | Testing |
|---|---|---|
| Ruby | Rails, Sinatra, Hanami | Minitest, RSpec |
| JavaScript/TypeScript | Next.js, Express, Nest, Remix | Jest, Vitest, Mocha |
| Python | Django, FastAPI, Flask | pytest, unittest |
| Go | Gin, Echo, Fiber | go test |
| Rust | Actix, Axum, Rocket | cargo test |
| Elixir | Phoenix | ExUnit |
| PHP | Laravel, Symfony | PHPUnit |
- Default - Full interview with codebase detection
- Quick (
/ralph-init quick) - Use detected defaults, skip interview - Minimal (
/ralph-init minimal) - Bare-bones prompts
# Basic usage - runs PROMPT_build.md in a loop
ralph
# With a specific spec file (replaces {spec-name} in prompt)
ralph my-feature.md
# Plan mode - uses PROMPT_plan.md
ralph -p
ralph -p my-feature.md
# Limit iterations
ralph -n 5 # Max 5 iterations
ralph -1 # Single iteration (same as -n 1)
# Different model
ralph -m sonnet my-feature.md
# Skip git push
ralph --no-push my-feature.md
# Combine options
ralph -p -n 3 -m sonnet --no-push my-feature.mdRalph expects this structure in your project:
your-project/
├── PROMPT_build.md # Build/implementation prompt (generated by /ralph-init)
├── PROMPT_plan.md # Planning prompt (generated by /ralph-init)
├── specs/ # Spec files
│ └── my-feature.md
└── *-implementation.md # Generated plans (created during planning)
The {spec-name} placeholder in your prompts gets replaced with the spec file path:
# PROMPT_build.md
1. Read the spec at `{spec-name}` to understand the task.
2. Implement the next incomplete item.
3. Run tests and commit.
4. Exit cleanly.Plan Mode (ralph -p):
- Analyzes spec requirements vs existing code
- Creates/updates
{spec-name}-implementation.mdwith tasks - Does NOT write implementation code
Build Mode (ralph):
- Reads the implementation plan
- Implements one task per iteration
- Runs tests and commits
- Updates the plan with progress
Ralph pipes Claude's JSON stream through stream-format for readable output:
📖 Read: src/components/Button.tsx
└─ export function Button({ children, onClick }...
✏️ Edit: src/components/Button.tsx
💻 Bash: npm test
└─ PASS src/components/Button.test.tsx
🤖 Task: Search for similar patterns
✅ Complete
- Reads
PROMPT_build.md(orPROMPT_plan.mdwith-p) - Replaces
{spec-name}with the provided spec file - Pipes the prompt to Claude CLI with streaming JSON output
- Formats the stream for readability
- Pushes to git after each iteration (unless
--no-push) - Repeats until max iterations reached or manually stopped
After running /ralph-init, you can customize the generated prompts:
- Add project-specific guardrails
- Adjust validation commands
- Modify the task format
- Add custom study steps
Specs define what you want to build. A simple spec might look like:
# User Authentication Spec
## Problem
Users can't log in to the application.
## Goals
1. Add login/logout functionality
2. Protect routes that require authentication
## User Stories
- As a user, I want to log in with email/password
- As a user, I want to stay logged in across sessions
## Technical Approach
- Use [your auth solution]
- Store sessions in [your session store]MIT