Iterative work/review loop for Claude Code
Project description
ralphkit
A step-based pipeline for Claude Code. Define setup, loop, and cleanup phases in a YAML config. The loop iterates until the reviewer says SHIP or max iterations are reached.
Inspired by the ralph loop.
Install
pip install ralphkit
With uv:
uv tool install ralphkit
Or run directly without installing:
uvx ralphkit ralph-loop "your task here" --config ralph.yaml
Quick Start
# Run with built-in defaults (no config needed)
ralph-loop "Create a Python function in prime.py that checks if a number is prime. Include unit tests."
# Or with a custom config
ralph-loop "Create a Python function in prime.py that checks if a number is prime. Include unit tests." --config configs/example.yaml
Usage
ralph-loop TASK [OPTIONS]
Arguments:
| Argument | Description | Default |
|---|---|---|
TASK |
Task description (string or path to .md file) |
required |
--config PATH |
Path to YAML config file | built-in defaults |
--max-iterations N |
Override max iterations from config | 10 |
-f / --force |
Skip confirmation prompt | off |
Examples:
# No config — uses built-in worker/reviewer loop
ralph-loop "Build a REST API"
# With a custom config
ralph-loop "Build a REST API" --config ralph.yaml
# Task from a markdown file
ralph-loop task.md --config ralph.yaml
# Override max iterations
ralph-loop "Build a REST API" --max-iterations 5
# Skip confirmation
ralph-loop "Build a REST API" -f
Config file
The config file is optional. Without one, ralphkit uses a built-in default loop with a worker (opus) and reviewer (sonnet) step. When a config is provided, all sections are optional — any section not specified uses defaults.
# All top-level keys are optional
max_iterations: 10 # default: 10
default_model: sonnet # default: sonnet
# Optional: runs once before the loop
setup:
- step_name: init
task_prompt: "Initialize the project."
system_prompt: "You are a setup agent."
# Optional: overrides the built-in worker/reviewer loop
loop:
- step_name: worker
task_prompt: "Read .ralphkit/task.md and begin working. This is iteration {iteration}."
system_prompt: "You are a worker in a RALPH LOOP..."
model: opus
- step_name: reviewer
task_prompt: "Review the work done for the task in .ralphkit/task.md."
system_prompt: "You are a code reviewer..."
model: sonnet
# Optional: runs once after the loop (always, even on failure)
cleanup:
- step_name: finalize
task_prompt: "Clean up temporary files."
system_prompt: "You are a cleanup agent."
Each step requires step_name, task_prompt, and system_prompt. The optional model field overrides default_model for that step.
Template variables
Both task_prompt and system_prompt support template variables via {variable_name}. Unrecognized variables are left as-is.
All phases:
| Variable | Description |
|---|---|
{step_name} |
Current step's name |
{max_iterations} |
Configured max iterations |
{default_model} |
Pipeline's default model |
{model} |
Resolved model for this step |
{state_dir} |
State directory path (.ralphkit) |
Loop phase only:
| Variable | Description |
|---|---|
{iteration} |
Current iteration number (1-based) |
See configs/example.yaml for a complete working config.
How It Works
Setup (once) Loop (iterate) Cleanup (once, always)
┌──────────┐ ┌───────────────────────┐ ┌──────────────┐
│ step 1 │ │ step 1 (e.g. worker) │ │ step 1 │
│ step 2 │ │ step 2 (e.g. reviewer)│ │ ... │
│ ... │ │ ... │ └──────────────┘
└──────────┘ │ SHIP? → done │
│ REVISE? → loop again │
└───────────────────────┘
Each loop iteration runs all loop steps in order, then checks the review result:
- Loop steps — each step runs
claudewith its configured prompts and model. - After all steps, the verdict is read from
.ralphkit/review-result.md. - SHIP → exit successfully. REVISE → feedback is preserved for the next iteration.
The cleanup phase always runs (even if the loop exits with an error), similar to a finally block.
State Files
State is persisted in .ralphkit/ in the current working directory so each stateless claude -p invocation can pick up where the last left off.
| File | Purpose |
|---|---|
task.md |
The task description |
iteration.md |
Current iteration number |
work-summary.md |
What the worker did this iteration |
work-complete.md |
Created when the worker thinks it's done |
review-result.md |
SHIP or REVISE |
review-feedback.md |
Specific feedback from the reviewer |
RALPH-BLOCKED.md |
Created by a step if it cannot proceed |
Requirements
- Claude Code CLI (
claudemust be on your PATH) - Python 3.10+
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ralphkit-0.1.1rc5.tar.gz.
File metadata
- Download URL: ralphkit-0.1.1rc5.tar.gz
- Upload date:
- Size: 2.2 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
58ef641d694262e6297641bf4dce399532fdb4d1e524bb646fab60c526e15d82
|
|
| MD5 |
ca2c7a49d0e539f4f81fed456549245c
|
|
| BLAKE2b-256 |
8a8bc3cc19029ef359b51a5e2363cce7f8fe21a0f1047cb086e0bb4accc7909a
|
File details
Details for the file ralphkit-0.1.1rc5-py3-none-any.whl.
File metadata
- Download URL: ralphkit-0.1.1rc5-py3-none-any.whl
- Upload date:
- Size: 14.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ffb6600e0c71d0f547ddea38906ddaeadbcf8585b832cd90d855cc66d0ab8905
|
|
| MD5 |
d3488efb1d230fa62c51df494f1dcaef
|
|
| BLAKE2b-256 |
75107617fab8792f0f36af00d61547a9dca925d3e3acc5543204124379dcfd0f
|