Getting Started¶
What you're about to do is loop engineering: you write a loop in the open ralph loops format, and ralphify — the runtime — runs it. This tutorial walks you through writing a ralph, feeding it live data, running the loop, steering it while it runs, and sharing it. By the end you'll have a self-healing loop that validates its own work.
Step 1: Install ralphify¶
This gives you the ralph command.
Step 2: Create a ralph¶
The fastest way to scaffold a ralph is ralph scaffold:
This creates my-ralph/RALPH.md with a ready-to-customize template including an example command, arg, and prompt. Edit the task section, test it, then follow Step 4 to add a test command — test feedback is what makes the loop self-healing.
Or create the file manually as shown below.
Manual setup¶
A ralph is a directory — not a single file. It contains a RALPH.md (the loop definition) plus any scripts or files the loop needs. RALPH.md is the only requirement; its shape is defined by the open ralph loops format:
Create the directory and a RALPH.md with the agent field — this is the only required frontmatter:
---
agent: claude -p --dangerously-skip-permissions
---
You are an autonomous coding agent running in a loop. Each iteration
starts with a fresh context. Your progress lives in the code and git.
Read TODO.md for the current task list. Pick the top uncompleted task,
implement it fully, then mark it done.
## Rules
- One task per iteration
- No placeholder code — full, working implementations only
- Run `uv run pytest -x` before committing
- Commit with a descriptive message like `feat: add X` or `fix: resolve Y`
- Mark the completed task in TODO.md
Parameterize with args¶
To make one ralph reusable with different inputs, declare args in the frontmatter. Each name becomes a {{ args.<name> }} placeholder in the prompt body, filled from the CLI at run time:
---
agent: claude -p --dangerously-skip-permissions
args:
- focus
---
Refactor the code under {{ args.focus }}. One module per iteration.
Pass the value with a matching flag:
The same ralph now runs against any path you give it. See the CLI reference for named vs. positional args.
Step 3: Do a test run¶
Run a single iteration to verify your setup works:
This runs a single iteration and saves the output to ralph_logs/. Review the log to see what the agent did:
Log files are useful for debugging but shouldn't be committed — add echo "ralph_logs/" >> .gitignore.
If the agent produced useful work, you're ready to add test feedback. If it errored or didn't do anything useful, check Troubleshooting.
Step 4: Add a test command¶
Commands run each iteration and their output is injected into the prompt via {{ commands.<name> }} placeholders. Add a test command and its placeholder:
---
agent: claude -p --dangerously-skip-permissions
commands:
- name: tests
run: uv run pytest -x
---
# Prompt
## Test results
{{ commands.tests }}
You are an autonomous coding agent running in a loop. Each iteration
starts with a fresh context. Your progress lives in the code and git.
Read TODO.md for the current task list. Pick the top uncompleted task,
implement it fully, then mark it done.
If tests are failing, fix them before starting new work.
## Rules
- One task per iteration
- No placeholder code — full, working implementations only
- Commit with a descriptive message like `feat: add X` or `fix: resolve Y`
- Mark the completed task in TODO.md
The tests command runs uv run pytest -x each iteration. Its output replaces {{ commands.tests }} in the prompt, so the agent always sees the current test results. If tests fail, the agent fixes them — that's the self-healing loop.
Step 5: Add more commands¶
Add a lint command and a git log for context:
---
agent: claude -p --dangerously-skip-permissions
commands:
- name: tests
run: uv run pytest -x
- name: lint
run: uv run ruff check .
- name: git-log
run: git log --oneline -10
---
# Prompt
## Recent commits
{{ commands.git-log }}
## Test results
{{ commands.tests }}
## Lint results
{{ commands.lint }}
You are an autonomous coding agent running in a loop. Each iteration
starts with a fresh context. Your progress lives in the code and git.
Read TODO.md for the current task list. Pick the top uncompleted task,
implement it fully, then mark it done.
If tests or lint are failing, fix them before starting new work.
## Rules
- One task per iteration
- No placeholder code — full, working implementations only
- Commit with a descriptive message like `feat: add X` or `fix: resolve Y`
- Mark the completed task in TODO.md
Step 6: Run the loop¶
Start with a few iterations to verify everything works:
Add --stop-on-error to stop the loop if the agent exits non-zero or times out — useful when you're still tuning the prompt and don't want to waste iterations:
Watch the output. Each iteration runs the commands, assembles the prompt with the command output, and pipes it to the agent:
▶ Running: my-ralph
3 commands · max 3 iterations
── Iteration 1 ──
Commands: 3 ran
✓ Iteration 1 completed (45.2s)
→ ralph_logs/001_20250115-142301.log
── Iteration 2 ──
Commands: 3 ran
✗ Iteration 2 failed with exit code 1 (23.1s)
→ ralph_logs/002_20250115-142512.log
── Iteration 3 ──
Commands: 3 ran
✓ Iteration 3 completed (38.5s)
→ ralph_logs/003_20250115-142812.log
──────────────────────
Done: 3 iterations — 2 succeeded, 1 failed
The agent's output streams live to your terminal between the iteration markers — you can watch it work in real time. Press p to silence the stream if you prefer a quieter loop, and p again to resume.
If the agent breaks a test, the next iteration sees the failure output via {{ commands.tests }} and fixes it automatically.
Once you're confident the loop works, drop the -n 3 to let it run indefinitely. Press Ctrl+C to stop.
Step 7: Steer while it runs¶
The prompt body is re-read from disk every iteration. You can edit RALPH.md while the loop is running and the agent follows your changes on the next cycle.
When the agent does something you don't want, add a rule:
When you want to shift focus, change the task:
This is the most powerful part of ralph loops — you're steering a running agent with a text file.
Note that only the prompt body is re-read each iteration. Frontmatter fields (agent, commands, args) are parsed once at startup, so if you add a command or change the agent, stop the loop with Ctrl+C and restart it.
Next steps¶
- Reference — the CLI, RALPH.md format, how the loop works, agents, troubleshooting, and the Python API
- How the loop works — what happens inside each iteration
- Examples — copy-pasteable ralph loops for coding, docs, research, and more