Minimal CLI for orchestrating Ralph loops across coding agents.
Ralph loops solve context rot — the degradation LLMs suffer in long sessions as conversation history fills with noise. Instead of one long session, ralph runs your agent repeatedly with fresh context, using a simple markdown file as memory between iterations.
pip install ralph-py
# Run a loop in the foreground (Ctrl+C to stop)
ralph run "implement user authentication with JWT tokens"
# Schedule a loop via system cron (survives reboots)
ralph schedule "run tests and fix failures" --cron "0 */2 * * *"
# Check on your loops
ralph list
ralph show <loop-id>
ralph logs <loop-id>
# Clean up
ralph remove <loop-id>┌──────────────────────────────────────────────────────────────┐
│ │
│ ralph run "implement auth" │
│ │ │
│ ├── iteration 1 ─── agent runs ─── updates memory.md │
│ │ ↓ │
│ │ sleep 5s │
│ │ ↓ │
│ ├── iteration 2 ─── agent runs ─── updates memory.md │
│ │ ↓ │
│ │ sleep 5s │
│ │ ↓ │
│ ├── iteration 3 ─── agent runs ─── prints │
│ │ RALPH_COMPLETE │
│ │ │
│ └── done. │
│ │
└──────────────────────────────────────────────────────────────┘
Each iteration:
- Ralph reads your task prompt and the accumulated
memory.md - Builds a composite prompt (your task + memory + iteration context + instructions)
- Invokes the agent CLI as a blocking subprocess with fresh context
- The agent works, updates
memory.md, and exits - Ralph checks for
RALPH_COMPLETEin stdout, updates state, repeats
You only write the task. Memory management, iteration tracking, and completion detection are automatic.
| Agent | Provider flag | Non-interactive mode |
|---|---|---|
| Claude Code | --provider claude (default) |
claude -p "prompt" |
| Codex CLI | --provider codex |
codex exec "prompt" |
| Aider | --provider aider |
aider --message "prompt" |
| OpenCode | --provider opencode |
opencode run "prompt" |
ralph run "refactor the database layer" --provider codex --model gpt-4.1
ralph run "add test coverage" --provider aider --model claude-sonnet-4-20250514Start a loop. Runs in the foreground by default, or as a background daemon with --daemon.
ralph run "implement auth feature" [options]| Option | Short | Default | Description |
|---|---|---|---|
--provider |
-p |
claude |
Agent CLI to use |
--model |
-m |
(provider default) | Model name |
--max-iter |
-n |
50 |
Stop after N iterations |
--delay |
-d |
5 |
Seconds between iterations |
--prompt-file |
-f |
Read prompt from a file | |
--name |
(auto) | Human-readable loop name | |
--workdir |
-w |
. |
Working directory for the agent |
--daemon |
false |
Run in background (survives SSH disconnect) |
Ctrl+C gracefully stops foreground loops — the current iteration finishes, state is saved.
ralph run "implement auth" --daemonThe --daemon flag spawns a detached background process that survives SSH disconnects and terminal closes. Use ralph show <loop-id> to check progress and ralph stop <loop-id> to stop it.
Install a system cron job. Each tick runs one iteration. Survives reboots.
ralph schedule "run tests and fix failures" --cron "0 */2 * * *"
ralph schedule --prompt-file ./nightly-task.md --cron "0 3 * * *" --name "nightly fixes"| Option | Short | Default | Description |
|---|---|---|---|
--cron |
-c |
(required) | Cron expression |
All options from ralph run also apply (except --delay).
Show all loops.
$ ralph list
┌──────────────────┬───────────────────┬───────────┬──────┬──────────────┬──────────┐
│ ID │ NAME │ STATUS │ ITER │ SCHEDULE │ LAST RUN │
├──────────────────┼───────────────────┼───────────┼──────┼──────────────┼──────────┤
│ implement-auth… │ implement auth │ running │ 7/50 │ (foreground) │ 2m ago │
│ nightly-fixes… │ nightly fixes │ running │ 12/50│ 0 3 * * * │ 8h ago │
│ refactor-db… │ refactor db layer │ completed │ 15/50│ (foreground) │ 1d ago │
└──────────────────┴───────────────────┴───────────┴──────┴──────────────┴──────────┘
Full details: config, memory contents, and latest log tail.
View the output log for an iteration.
ralph logs <loop-id> # latest iteration
ralph logs <loop-id> --iter 3 # specific iteration
ralph logs <loop-id> --tail 20 # last 20 linesStop a running loop without deleting any files. Works for foreground, daemon, and cron loops.
ralph stop <loop-id>This kills the process (if running), removes any cron entry, and sets the status to stopped. All files (logs, memory, state) are preserved for inspection.
Stop a loop and delete its files. Use --keep-files to preserve logs and memory.
ralph remove <loop-id> # remove everything
ralph remove <loop-id> --keep-files # stop cron, keep filesRun a single iteration. This is what cron calls — you can also use it manually.
Memory is a plain markdown file (~/.ralph/loops/<id>/memory.md) that persists across iterations. Ralph injects it into the prompt automatically. The agent is instructed to update it after each iteration.
## Iteration 3
- Implemented JWT token generation and validation
- All auth tests passing (12/12)
- TODO: refresh token endpoint, rate limiting
## Iteration 2
- Created login endpoint, password hashing with bcrypt
- Added test fixtures for auth module
## Iteration 1
- Set up project structure and database models
- Created user registration endpointMemory lives outside your project directory (~/.ralph/loops/<id>/), so multiple loops can target the same repo without conflicting, and nothing ralph-related ends up in your git history.
The loop stops when any of these happen:
| Condition | Result status |
|---|---|
Agent prints RALPH_COMPLETE on its own line |
completed |
Iteration count reaches --max-iter |
stopped |
ralph remove <id> |
stopped |
Ctrl+C during ralph run |
stopped |
The agent is automatically instructed to print RALPH_COMPLETE when the task is done — you don't need to include this in your prompt.
All state lives under ~/.ralph/:
~/.ralph/
└── loops/
└── implement-auth-a1b2/
├── prompt.md # Your original task (immutable)
├── memory.md # Agent-maintained memory
├── state.json # Iteration count, status, config
└── logs/
├── 001.log # stdout from iteration 1
├── 002.log
└── 003.log
No databases. No daemon. Just files.
ralph run |
ralph run --daemon |
ralph schedule |
|
|---|---|---|---|
| Process | Foreground, needs a terminal | Background, detached | No process — cron manages it |
| Survives terminal close | No | Yes | Yes |
| Survives reboot | No | No | Yes |
| Timing | Fixed delay between iterations | Fixed delay between iterations | Cron expression |
| Output | Streamed to terminal | Written to log files | Written to log files |
| Best for | Active development | Long tasks over SSH | Overnight/periodic tasks |
Requires Python 3.11+.
# pip
pip install ralph-py
# uv
uv tool install ralph-py
# pipx
pipx install ralph-py
# From source
git clone https://github.com/SiluPanda/ralph-py.git
cd ralph-py
pip install -e .One runtime dependency: typer. Cron management uses the system crontab command directly — no extra libraries.
Ralph is deliberately minimal. It does not:
- Track costs — delegate to the agent CLI (
--max-budget-usdon Claude Code) - Manage git — the agent handles commits, branches, etc.
- Provide a TUI/dashboard — use
ralph listandralph logs - Rotate agents — one provider per loop
- Retry with backoff — fresh context is the retry mechanism
- Run a daemon — scheduling is the OS's job
The Ralph loop (named by Geoffrey Huntley, mid-2025) is a technique for running coding agents autonomously on long tasks. The insight: LLMs degrade as context fills — past 60-70% capacity, performance collapses. Ralph fixes this by restarting the agent with fresh context each iteration, using files and git as the memory layer instead of conversation history.
# The original Ralph loop is one line of bash:
while :; do cat PROMPT.md | claude -p; doneralph-py wraps this pattern with scheduling, memory management, iteration tracking, and multi-agent support — while staying true to the philosophy of simplicity.
MIT