Self-hosted service
snarktank/ralph avatar
snarktank/ralph

Ralph, prd.json and a ten-iteration ceiling: what the agent loop actually checks

Project brief: Ralph is an autonomous AI agent loop that runs repeatedly until all PRD items are complete.

22,229 stars2,115 forksTypeScriptMIT

At a glance

What is it?
Ralph is a bash loop that spawns a fresh Amp or Claude Code instance per story and stops when every entry in prd.json reads passes true. It judges nothing itself, so the loop is only as trustworthy as the checks and acceptance criteria you wrote.
Who is it for?
Adopt Ralph if your repository already has a typecheck and test suite that fails when behaviour is wrong, a PRD you can split into one-context-window stories, and an acceptance criteria habit you trust. Do not adopt it as a way to bootstrap either of those, because the loop reads your checks rather than improving them, and the story that gets marked passing is never revisited.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Activity is slowing. The repository last received commits 9 months ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • snarktank/ralph22,229 ★ · +852
Star history
Repository2026-08-042026-11-14
snarktank/ralph21.4k22.2k

852 Stars in the last 102 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

Every iteration starts with an empty context window

Ralph spawns a new instance of Amp or Claude Code for every pass, and each instance starts with clean context. Nothing carries over except three things: the commits from earlier iterations, progress.txt, and prd.json. That is the entire memory of a run.

So each PRD item has to be small enough to finish inside one context window. The README is blunt about this: if a task is too big, the LLM runs out of context before finishing and produces poor code. Adding a database column and migration is right-sized. Building the entire dashboard is not, and neither is adding authentication or refactoring the API.

One file sits outside that list: AGENTS.md. After each iteration Ralph updates the relevant AGENTS.md files, and the AI coding tools read those files automatically, so a pattern or gotcha found in iteration one is available in iteration ten. Block that write and future iterations lose those learnings.

A story counts as passing when typecheck and tests go green

One iteration does eight things in a fixed order. It creates a feature branch from the branchName in the PRD, picks the highest priority story where passes is false, implements that one story, runs quality checks described as typecheck and tests, commits only if those checks pass, flips passes to true in prd.json, appends learnings to progress.txt, and starts again.

The fifth step decides everything about quality. The commit gate is the quality checks: it commits when typecheck and tests pass. A project with a thin test suite therefore gets a loop that will mark unimplemented behaviour as done, one story at a time, with a green commit for each one.

The README states the precondition directly: Ralph only works if there are feedback loops, CI must stay green, and broken code compounds across iterations. That is a demand on your repository, not something the loop produces.

The stop condition is a flag the agent writes itself

When every story in prd.json has passes set to true, Ralph outputs <promise>COMPLETE</promise> and the loop exits. Nothing else ends a run early.

The consequence is worth sitting with. The same agent that wrote the code writes the verdict that the code is finished. The eight steps the README lists include no reviewer pass and no human checkpoint. A story marked passing by mistake stays marked, the next iteration moves on to a different story, and the run finishes reporting completion.

State lives in three places, so checking a run after the fact means reading all three:

bash
# See which stories are done
cat prd.json | jq '.userStories[] | {id, title, passes}'

# See learnings from previous iterations
cat progress.txt

# Check git history
git log --oneline -10

Read the commits on the feature branch before trusting a completed run. The flag records what the agent believed, not what shipped.

Ten iterations is a ceiling, not a budget

Ralph takes one positional argument, the iteration count, and defaults to 10:

bash
# Using Amp (default)
./scripts/ralph/ralph.sh [max_iterations]

# Using Claude Code
./scripts/ralph/ralph.sh --tool claude [max_iterations]

Ten is a ceiling rather than a budget the script paces. Every iteration is a full agent run that reads the repository, writes code and runs your checks, so a PRD of twenty stories stops partway with the rest untouched. Passing ./scripts/ralph/ralph.sh 50 raises the ceiling, and because each run takes the highest priority story with passes false, a second run continues where the first one stopped instead of starting over.

The Run Ralph section of the README lists only --tool and the iteration count as options.

Auto-handoff is an Amp-only experimental key

Amp users can hand context to a fresh instance when the window fills, which the README points at for work that runs past a single context window. The setting goes in your Amp settings file:

json
{
  "amp.experimental.autoHandoff": { "context": 90 }
}

Two details matter. The key sits under amp.experimental, so Amp itself flags it as experimental, and the file is ~/.config/amp/settings.json, which makes it an Amp-only setting. No equivalent is given for Claude Code, where installation runs through the skills copy or the plugin marketplace. On that path, keeping a story inside one context window is left entirely to you.

The README also holds two positions at once. The handoff section says this setting lets Ralph handle large stories that exceed a single context window, while Critical Concepts still says each PRD item should be small enough to complete in one context window. Splitting stories by hand remains the advice the same file gives elsewhere.

A browser check only runs if you write it into the criteria

For frontend stories the README asks for one specific line in the acceptance criteria: "Verify in browser using dev-browser skill". With that line present, Ralph uses the dev-browser skill to navigate to the page, interact with the UI and confirm the change works.

Without it, nothing in the loop looks at the rendered page. Typecheck and tests pass on a component that compiles, imports cleanly and never mounts, so a broken layout commits as a passing story and the iteration after it builds on that layout.

The setup steps copy ralph.sh, prompt.md or CLAUDE.md, and the prd and ralph skills; the dev-browser skill is not among them, so check that your tool installation provides it before relying on browser verification.

Three install paths, no package, nothing to pin

There is no package to install for the loop itself. Ralph is a bash script, two prompt templates and a pair of skills that you copy into place. The first route puts the script and one prompt template inside your repository:

bash
# From your project root
mkdir -p scripts/ralph
cp /path/to/ralph/ralph.sh scripts/ralph/

# Copy the prompt template for your AI tool of choice:
cp /path/to/ralph/prompt.md scripts/ralph/prompt.md    # For Amp
# OR
cp /path/to/ralph/CLAUDE.md scripts/ralph/CLAUDE.md    # For Claude Code

chmod +x scripts/ralph/ralph.sh

The second route copies the skills where every project can reach them, with cp -r skills/prd ~/.config/amp/skills/ for Amp or cp -r skills/prd ~/.claude/skills/ for Claude Code. The third is the Claude Code marketplace: add snarktank/ralph, then install ralph-skills@ralph-marketplace. Either way you also need jq, where the only install command given is brew install jq on macOS, and a git repository for your project.

Copying carries its own upkeep. The repository has no GitHub releases and the last push was on 2026-02-02, so there is no version to pin. You re-copy files by hand when you want changes, and those same files are the ones you are told to edit, since prompt.md or CLAUDE.md is where your own quality check commands and codebase conventions belong.

The loop layers a feature branch and prd.json on Huntley's pattern

The credit line points at Geoffrey Huntley's Ralph pattern, so it is fair to ask what this repository adds on top. The file layout answers it: ralph.sh is the bash loop that spawns fresh AI instances and supports --tool amp or --tool claude, skills/prd writes the requirements document, skills/ralph converts it into prd.json, and .claude-plugin holds the manifest behind the marketplace entry. The requirements document itself is written first, saved to tasks/prd-[feature-name].md, and only then converted.

The difference from driving the agent by hand is bookkeeping. A human session carries its own context and its own memory of what is finished. This loop carries neither and substitutes three files plus a feature branch, which is what makes a run auditable afterwards and equally what makes a wrong passes flag permanent.

One oddity for anyone auditing the repository: the top level has no package.json, and the one npm project it documents is flowchart/, the interactive visualisation published at snarktank.github.io/ralph. You run it with cd flowchart, npm install and npm run dev. Nothing in the loop depends on it.

Editorial conclusion

Adopt Ralph if your repository already has a typecheck and test suite that fails when behaviour is wrong, a PRD you can split into one-context-window stories, and an acceptance criteria habit you trust. Do not adopt it as a way to bootstrap either of those, because the loop reads your checks rather than improving them, and the story that gets marked passing is never revisited. Verify first with cat prd.json | jq '.userStories[] | {id, title, passes}' and git log --oneline -10 on the feature branch it leaves behind.

Frequently asked questions

What is the ralph loop?

Ralph runs an AI coding tool, Amp or Claude Code, repeatedly until every PRD item is complete. Each iteration is a fresh instance with clean context, and memory persists through git history, progress.txt and prd.json.

How do I install ralph?

It is copied rather than installed from a package. ralph.sh plus prompt.md for Amp or CLAUDE.md for Claude Code go into scripts/ralph/ in your project, or the skills go into ~/.config/amp/skills/ or ~/.claude/skills/ for use across projects.

How do I install ralph in Claude Code?

Install the CLI with npm install -g @anthropic-ai/claude-code, then either copy skills/prd and skills/ralph into ~/.claude/skills/ or add the marketplace with /plugin marketplace add snarktank/ralph followed by /plugin install ralph-skills@ralph-marketplace. Both routes hand you the /prd and /ralph skills.

How do I install the ralph loop plugin?

The Claude Code route is two commands: /plugin marketplace add snarktank/ralph, then /plugin install ralph-skills@ralph-marketplace. What you get is /prd for generating requirements documents and /ralph for converting them into prd.json.

How do I use the ralph loop once it is installed?

Run ./scripts/ralph/ralph.sh from your project and pass the iteration count as a positional argument, adding --tool claude for Claude Code. The default is 10 iterations, and each one takes the highest priority story whose passes value is false.

Official sources

  1. Official documentation
  2. Official README
  3. Project repository
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/snarktank-ralph.svg)](https://hysenlabs.com/projects/snarktank-ralph)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/snarktank-ralph.svg)](https://hysenlabs.com/projects/snarktank-ralph)

Was this useful?