Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ Ralph loops give you:
| **grow-coverage** | Write tests for untested modules, one per iteration, until coverage hits the target |
| **security-audit** | Hunt for vulnerabilities — scan, find, fix, verify, repeat |
| **clear-backlog** | Work through a TODO list or issue tracker, one task per loop |
| **promise-completion** | Work until a target is done, then emit a promise tag so the loop stops early |
| **write-docs** | Generate documentation for undocumented modules, one at a time |
| **improve-codebase** | Find and fix code smells, refactor patterns, modernize APIs |
| **migrate** | Incrementally migrate files from one framework or pattern to another |
Expand Down Expand Up @@ -95,11 +96,17 @@ Scaffold a ralph and start experimenting:
ralph scaffold my-ralph
```

The scaffolded `RALPH.md` includes the normal command/arg template plus a commented promise-completion path you can enable if the agent should stop early by emitting a matching `<promise>...</promise>` tag.

For a committed example, see [`examples/promise-completion/RALPH.md`](examples/promise-completion/RALPH.md) — it shows a loop that exits early once the requested target is complete.

Edit `my-ralph/RALPH.md`, then run it:

```bash
ralph run my-ralph # loops until Ctrl+C
ralph run my-ralph -n 5 # run 5 iterations then stop
# from a repo checkout:
ralph run examples/promise-completion -n 10 --target "stabilize the failing auth tests"
```

### What `ralph run` does
Expand Down
29 changes: 27 additions & 2 deletions docs/agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,34 @@ Your agent must:

1. **Read a prompt from stdin** — the full assembled prompt is piped in
2. **Do work in the current directory** — edit files, run commands, make commits
3. **Exit when done** — exit code 0 means success, non-zero means failure
3. **Exit cleanly** — exit code `0` means the agent process succeeded; non-zero means failure
4. **Optionally emit a completion signal** — set `completion_signal` in frontmatter (default inner text: `RALPH_PROMISE_COMPLETE`) if you want the agent to print an explicit `<promise>...</promise>` marker

That's it. No special protocol, no API — just stdin in, work done, process exits.
Normal exit codes still indicate process success or failure. They do **not** trigger promise completion by themselves.

Ralphify only stops early on promise completion when both of these are true:

- `stop_on_completion_signal: true`
- the matching `<promise>...</promise>` tag is detected in agent output or captured result text

`completion_signal` is the inner promise text. For example, `completion_signal: COMPLETE` means the agent must output `<promise>COMPLETE</promise>`.

Ralphify still keeps its own command/prompt loop architecture. Only the promise tag format and matching align with Ralph-Wiggum.

Minimal example:

```markdown
---
agent: claude -p --dangerously-skip-permissions
completion_signal: COMPLETE
stop_on_completion_signal: true
---

Implement the next todo. When the work is fully complete, print
<promise>COMPLETE</promise> and exit.
```

That's it. No API required — just stdin in, output out, process exits.

## Claude Code

Expand Down
7 changes: 6 additions & 1 deletion docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ The loop also stops automatically when:

- All `-n` iterations have completed
- `--stop-on-error` is set and the agent exits non-zero or times out
- `stop_on_completion_signal: true` is set in frontmatter and the matching `<promise>...</promise>` tag is detected in agent output or captured result text

### Peeking at live agent output

Expand Down Expand Up @@ -152,7 +153,7 @@ ralph scaffold # Creates RALPH.md in the current directory
|---|---|---|
| `[NAME]` | none | Directory name. If omitted, creates RALPH.md in the current directory |

The generated template includes an example command (`git-log`), an example arg (`focus`), and a prompt body with placeholders for both. Edit it, then run [`ralph run`](#ralph-run). See [Getting Started](getting-started.md) for a full walkthrough.
The generated template includes an example command (`git-log`), an example arg (`focus`), a prompt body with placeholders for both, and commented `completion_signal` / `stop_on_completion_signal` lines showing the promise-completion path. Uncomment them if you want the agent to stop early by emitting a matching `<promise>...</promise>` tag. Then run [`ralph run`](#ralph-run). See [Getting Started](getting-started.md) for a full walkthrough.

Errors if `RALPH.md` already exists at the target location.

Expand Down Expand Up @@ -190,6 +191,10 @@ Your instructions here. Reference args with {{ args.dir }}.
| `commands` | list | no | Commands to run each iteration (each has `name` and `run`) |
| `args` | list of strings | no | Declared argument names for user arguments. Letters, digits, hyphens, and underscores only. |
| `credit` | bool | no | Append co-author trailer instruction to prompt (default: `true`) |
| `completion_signal` | string | no | Inner text for the completion promise tag. `COMPLETE` means the agent must emit `<promise>COMPLETE</promise>` (default inner text: `RALPH_PROMISE_COMPLETE`) |
| `stop_on_completion_signal` | bool | no | Stop the loop early when the matching `<promise>...</promise>` tag is detected (default: `false`) |

Exit code `0` still only means the agent process succeeded. Ralphify keeps its own loop architecture; only the promise tag format and matching align with Ralph-Wiggum.

### Commands

Expand Down
40 changes: 37 additions & 3 deletions docs/cookbook.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
---
title: Ralph Loop Recipes
description: Copy-pasteable ralph loop setups for autonomous ML research, test coverage, code migration, security scanning, deep research, documentation, bug fixing, and codebase improvement.
keywords: ralphify cookbook, autonomous coding recipes, RALPH.md examples, documentation loop, bug fixing loop, codebase improvement, deep research agent, code migration loop, security scanning agent, test coverage automation, autoresearch, autonomous ML research
description: Copy-pasteable ralph loop setups for autonomous ML research, promise-based early exit, test coverage, code migration, security scanning, deep research, documentation, bug fixing, and codebase improvement.
keywords: ralphify cookbook, autonomous coding recipes, RALPH.md examples, promise completion, early exit agent loop, documentation loop, bug fixing loop, codebase improvement, deep research agent, code migration loop, security scanning agent, test coverage automation, autoresearch, autonomous ML research
---

# Cookbook

!!! tldr "TL;DR"
8 copy-pasteable ralph loops: [autoresearch](#autoresearch), [codebase improvement](#codebase-improvement), [documentation](#documentation-loop), [bug hunting](#bug-hunter), [deep research](#deep-research), [code migration](#code-migration), [security scanning](#security-scan), and [test coverage](#test-coverage). Each is a real, runnable example from the `examples/` directory.
9 copy-pasteable ralph loops: [autoresearch](#autoresearch), [codebase improvement](#codebase-improvement), [documentation](#documentation-loop), [bug hunting](#bug-hunter), [deep research](#deep-research), [code migration](#code-migration), [security scanning](#security-scan), [test coverage](#test-coverage), and [promise completion](#promise-completion). Each is a real, runnable example from the `examples/` directory.

Copy-pasteable setups for common autonomous workflows. Each recipe is a real, runnable ralph from the [`examples/`](https://github.com/computerlovetech/ralphify/tree/main/examples) directory.

Expand Down Expand Up @@ -269,6 +269,40 @@ The coverage report gives the agent a clear metric to improve and shows exactly

---

## Stop the loop when the task is complete {: #promise-completion }

A loop that uses ralphify's promise-completion path to stop before the iteration budget. The agent keeps working until the requested target is done, then emits `<promise>COMPLETE</promise>` so the run ends immediately instead of burning the remaining iterations.

**`promise-completion/RALPH.md`**

```markdown
--8<-- "examples/promise-completion/RALPH.md"
```

```bash
ralph run promise-completion -n 10 --target "stabilize the failing auth tests"
```

```text
▶ Running: promise-completion
3 commands · max 10 iterations

── Iteration 1 ──
Commands: 3 ran
✓ Iteration 1 completed (51.4s)

── Iteration 2 ──
Commands: 3 ran
✓ Iteration 2 completed via promise tag <promise>COMPLETE</promise> (43.2s)

──────────────────────
Done: 2 iterations — 2 succeeded
```

Set `completion_signal` to the inner promise text and `stop_on_completion_signal: true` to enable early exit. The agent must emit the matching `<promise>...</promise>` tag — bare text does not count.

---

## Next steps

- [CLI Reference](cli.md) — all `ralph run` options (`--timeout`, `--stop-on-error`, `--delay`, user args)
Expand Down
15 changes: 13 additions & 2 deletions docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,10 @@ ralph scaffold my-ralph
```text
Created my-ralph/RALPH.md
Edit the file, then run: ralph run my-ralph
Optional early exit: uncomment completion_signal + stop_on_completion_signal and emit <promise>COMPLETE</promise>.
```

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](#step-3-do-a-test-run), then follow [Step 4](#step-4-add-a-test-command) to add a test command — test feedback is what makes the loop self-healing.
This creates `my-ralph/RALPH.md` with a ready-to-customize template including an example command, arg, prompt, and a commented promise-completion example. If you want the loop to stop before its iteration budget, uncomment `completion_signal` and `stop_on_completion_signal`, then tell the agent to emit the matching `<promise>...</promise>` tag when it is done. Edit the task section, [test it](#step-3-do-a-test-run), then follow [Step 4](#step-4-add-a-test-command) to add a test command — test feedback is what makes the loop self-healing.

Or create the file manually as shown below.

Expand Down Expand Up @@ -251,6 +252,16 @@ The agent's output streams live to your terminal between the iteration markers

If the agent breaks a test, the next iteration sees the failure output via `{{ commands.tests }}` and fixes it automatically.

!!! tip "Optional: stop when the task is fully complete"
Add these frontmatter fields if you want the loop to stop on an explicit completion marker:

```yaml
completion_signal: COMPLETE
stop_on_completion_signal: true
```

`completion_signal` is the inner promise text. With `completion_signal: COMPLETE`, the agent must emit `<promise>COMPLETE</promise>`. If you omit it, the default promise tag is `<promise>RALPH_PROMISE_COMPLETE</promise>`. The loop only exits early when `stop_on_completion_signal` is enabled and that tag is detected in agent output or captured result text. Exit code `0` still only means the agent process succeeded.

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
Expand All @@ -274,7 +285,7 @@ Read TODO.md and focus only on the API module.
This is the most powerful part of ralph loops — you're steering a running agent with a text file.

!!! warning "Frontmatter changes need a restart"
Only the **prompt body** is re-read each iteration. Frontmatter fields (`agent`, `commands`, `args`) are parsed once at startup. If you add a new command or change the agent, stop the loop with `Ctrl+C` and restart it.
Only the **prompt body** is re-read each iteration. Frontmatter is parsed once at startup. If you add a new command, change the agent, or change completion settings, stop the loop with `Ctrl+C` and restart it.

## Next steps

Expand Down
7 changes: 5 additions & 2 deletions docs/how-it-works.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Every iteration follows the same sequence. Here's what happens at each step.

The prompt body (everything below the frontmatter) is read from disk **every iteration**. This means you can edit the prompt text — add rules, change the task, adjust constraints — while the loop is running. Changes take effect on the next cycle.

Frontmatter fields (`agent`, `commands`, `args`) are parsed once at startup. To change those, restart the loop.
Frontmatter settings are parsed once at startup. To change them, restart the loop.

### 2. Run commands and capture output

Expand Down Expand Up @@ -70,6 +70,8 @@ echo "<assembled prompt>" | claude -p --dangerously-skip-permissions

The agent reads the prompt, does work in the current directory (edits files, runs commands, makes commits), and exits. Ralphify waits for the agent process to finish.

Exit codes still mean process success or failure. Promise completion is separate: `completion_signal` is the inner promise text (default: `RALPH_PROMISE_COMPLETE`), so ralphify only stops early when `stop_on_completion_signal` is `true` and the agent emits the matching `<promise>...</promise>` tag in output or captured result text. This aligns the promise format with Ralph-Wiggum, but ralphify still uses its own command/prompt loop architecture.

When the agent command starts with `claude`, ralphify automatically adds `--output-format stream-json --verbose` to enable structured streaming. This lets ralphify track agent activity in real time — you don't need to configure this yourself.

### 6. Loop back with fresh context
Expand All @@ -82,7 +84,7 @@ The loop starts the next iteration from step 1. The RALPH.md is re-read, command
|---|---|---|
| Prompt body | Every iteration | Edit the prompt while the loop runs — the next iteration follows your new instructions |
| Command output | Every iteration | The agent always sees fresh data (latest git log, current test status, etc.) |
| Frontmatter (`agent`, `commands`, `args`) | Once at startup | Parsed when the loop starts. Restart to pick up changes. |
| Frontmatter settings | Once at startup | Parsed when the loop starts. Restart to pick up changes. |
| User arguments | Once at startup | Passed via CLI flags, constant for the run |

## How broken code gets fixed automatically
Expand Down Expand Up @@ -179,6 +181,7 @@ The loop continues until one of these happens:
| `Ctrl+C` (first) | Gracefully finishes the current iteration, then stops the loop. The agent completes its work and the iteration result is recorded. |
| `Ctrl+C` (second) | Force-stops immediately — kills the agent process and exits. Use when you don't want to wait for the current iteration to finish. |
| `-n` limit reached | Loop stops after completing the specified number of iterations |
| `stop_on_completion_signal: true` and matching `<promise>...</promise>` tag detected | Loop stops after the current iteration |
| `--stop-on-error` and agent exits non-zero or times out | Loop stops after the current iteration |
| `--timeout` exceeded | Agent process is killed, iteration is marked as timed out, loop continues (unless `--stop-on-error`) |

Expand Down
6 changes: 3 additions & 3 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ hide:

A **ralph** is a directory with a `RALPH.md` file — a skill-like format that bundles a prompt, the commands to run between iterations, and any files the agent needs. **Ralphify** is the CLI runtime that executes them.

See [The Ralph Format](blog/posts/the-ralph-format.md) for the full spec.
See [The Ralph Format](blog/posts/the-ralph-standard.md) for the full spec.

```
grow-coverage/
Expand Down Expand Up @@ -52,7 +52,7 @@ One directory. One command. Each iteration starts with fresh context and current
*Works with any agent CLI. Swap `claude -p` for Codex, Aider, or your own — just change the `agent` field.*

[Get Started](getting-started.md){ .md-button .md-button--primary }
[Read the Format Spec](blog/posts/the-ralph-format.md){ .md-button }
[Read the Format Spec](blog/posts/the-ralph-standard.md){ .md-button }

---

Expand Down Expand Up @@ -149,7 +149,7 @@ Ralphs are to the outer loop what [skills](https://agentskills.io/) are to the i

## Next steps

- **[The Ralph Format](blog/posts/the-ralph-format.md)** — the full spec
- **[The Ralph Format](blog/posts/the-ralph-standard.md)** — the full spec
- **[Getting Started](getting-started.md)** — from install to a running loop in 10 minutes
- **[How it Works](how-it-works.md)** — what happens inside each iteration
- **[Cookbook](cookbook.md)** — copy-pasteable ralphs for coding, docs, research, and more
Expand Down
3 changes: 3 additions & 0 deletions docs/quick-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ Your instructions here. Use {{ args.dir }} for user arguments. <!-- (6) -->
| `commands` | list | no | Commands to run each iteration |
| `args` | list | no | User argument names. Letters, digits, hyphens, and underscores only. |
| `credit` | bool | no | Append co-author trailer instruction to prompt (default: `true`) |
| `completion_signal` | string | no | Inner text for the completion promise tag. `COMPLETE` means the agent must emit `<promise>COMPLETE</promise>` (default inner text: `RALPH_PROMISE_COMPLETE`) |
| `stop_on_completion_signal` | bool | no | Stop the loop early when the matching `<promise>...</promise>` tag is detected (default: `false`) |

### Command fields

Expand Down Expand Up @@ -160,6 +162,7 @@ Each iteration:
| `P` (shift+p) | Open full-screen peek — scroll the entire activity buffer. `j/k` line, `space/b` page, `g/G` top/bottom, `q` or `P` exits |
| `-n` limit reached | Stops after the specified number of iterations |
| `--stop-on-error` | Stops if agent exits non-zero or times out |
| matching `<promise>...</promise>` tag detected | Stops early only when `stop_on_completion_signal: true` and the configured promise tag is found in agent output/result |

## Live editing

Expand Down
2 changes: 1 addition & 1 deletion docs/troubleshooting.md
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,7 @@ For programmatic control over concurrent runs, use the [Python API's `RunManager

### Can I edit RALPH.md while the loop runs?

Yes. The prompt body (everything below the frontmatter) is re-read every iteration — edit the prompt text and changes take effect on the next cycle. Frontmatter fields (`agent`, `commands`, `args`) are parsed once at startup, so changing those requires restarting the loop.
Yes. The prompt body (everything below the frontmatter) is re-read every iteration — edit the prompt text and changes take effect on the next cycle. Frontmatter settings are parsed once at startup, so changing them requires restarting the loop.

### How do I disable the co-author credit in commits?

Expand Down
49 changes: 49 additions & 0 deletions examples/promise-completion/RALPH.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
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
args:
- target
completion_signal: COMPLETE
stop_on_completion_signal: true
---

# Stop Early with a Promise Tag

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.

## Recent commits

{{ commands.git-log }}

## Test results

{{ commands.tests }}

## Lint

{{ commands.lint }}

Fix any failing tests or lint violations above before doing anything else.

## Task

Get the requested target to a clean, shippable state.
{{ args.target }}

When the task is complete and no more changes are needed, print
<promise>COMPLETE</promise> and exit so the loop stops early.

## Rules

- One fix or improvement per iteration
- Keep the target scoped — do not drift into unrelated cleanup
- If tests or lint are failing, fix them before new work
- Only emit <promise>COMPLETE</promise> when the target is truly done
- Commit with a descriptive message and push
Loading