Skip to main content

Minimal CLI for orchestrating Ralph loops across coding agents

Project description

ralph-py

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

Quick start

# 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>

How it works

┌──────────────────────────────────────────────────────────────┐
│                                                              │
│   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:

  1. Ralph reads your task prompt and the accumulated memory.md
  2. Builds a composite prompt (your task + memory + iteration context + instructions)
  3. Invokes the agent CLI as a blocking subprocess with fresh context
  4. The agent works, updates memory.md, and exits
  5. Ralph checks for RALPH_COMPLETE in stdout, updates state, repeats

You only write the task. Memory management, iteration tracking, and completion detection are automatic.

Supported agents

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-20250514

Commands

ralph run

Start 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.

Daemon mode

ralph run "implement auth" --daemon

The --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.

ralph schedule

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).

ralph list

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   │
└──────────────────┴───────────────────┴───────────┴──────┴──────────────┴──────────┘

ralph show <loop-id>

Full details: config, memory contents, and latest log tail.

ralph logs <loop-id>

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 lines

ralph stop <loop-id>

Stop 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.

ralph remove <loop-id>

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 files

ralph once <loop-id>

Run a single iteration. This is what cron calls — you can also use it manually.

Memory

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 endpoint

Memory 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.

Completion

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.

Data layout

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.

Foreground vs. daemon vs. scheduled

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

Installation

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 .

Dependencies

One runtime dependency: typer. Cron management uses the system crontab command directly — no extra libraries.

What ralph doesn't do

Ralph is deliberately minimal. It does not:

  • Track costs — delegate to the agent CLI (--max-budget-usd on Claude Code)
  • Manage git — the agent handles commits, branches, etc.
  • Provide a TUI/dashboard — use ralph list and ralph 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

Background

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; done

ralph-py wraps this pattern with scheduling, memory management, iteration tracking, and multi-agent support — while staying true to the philosophy of simplicity.

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ralph_py-0.4.0.tar.gz (46.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ralph_py-0.4.0-py3-none-any.whl (21.4 kB view details)

Uploaded Python 3

File details

Details for the file ralph_py-0.4.0.tar.gz.

File metadata

  • Download URL: ralph_py-0.4.0.tar.gz
  • Upload date:
  • Size: 46.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for ralph_py-0.4.0.tar.gz
Algorithm Hash digest
SHA256 3608f74e9b04225f43048b392f0b456fa48589302558158adab500d2f1ca2d5f
MD5 7db30634660fc27e287119b4c99da41b
BLAKE2b-256 c4a1589ef0e5d7ac79b1ce4969398ffdfd1b4d70552cba4381fa59e600c049ee

See more details on using hashes here.

File details

Details for the file ralph_py-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: ralph_py-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 21.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.7

File hashes

Hashes for ralph_py-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 66881c86b7a929c955c4c62f27d1c78f38982d47107b17c106a73984efb846e3
MD5 29e22ffca4cb2b11bda6cbe19a44c7f3
BLAKE2b-256 79812742a42d3c371e40b2a35280535999989265c13719d8ca2de0bccb7a2d1f

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page