All posts
AI Cursor Productivity Agentic Dev

The Ralph Loop with Cursor: Agentic Development Without Context Collapse

How to implement the Ralph Loop pattern in Cursor using subagents — keeping AI context fresh and token costs linear across an entire feature build.

· Michele Brandolin
Ralph Wiggum — the inspiration behind the Ralph Loop agentic development pattern

The Ralph Loop is one of the most elegant ideas to emerge from AI-assisted development. Originally documented by Geoffrey Huntley, it addresses a problem every developer eventually runs into: context collapse.

As an AI conversation grows longer, the model accumulates thousands of tokens of prior exchanges. Instructions get diluted. Earlier constraints get forgotten. Output quality quietly drifts. The Ralph Loop sidesteps this entirely — instead of one ever-growing session, you run the AI in a disciplined loop where each iteration starts fresh but inherits persisted state from previous runs.

This guide shows how to implement the Ralph Loop natively inside Cursor using its subagent system. No extra tooling or infrastructure required.


Table of Contents

  1. What is the Ralph Loop
  2. Setup: File Structure
  3. The Subagent Files
  4. PRD Templates
  5. Creating the PRD
  6. Running the Loop: Step-by-Step
  7. Advanced Tips

1. What is the Ralph Loop

The Ralph Loop, named and documented by Geoffrey Huntley, is a pattern for autonomous AI coding agents. The core insight:

Instead of fighting context window limits with one long conversation, run the AI in a loop where each iteration starts fresh but reads persisted state from previous runs.

Why It Works

  • Fresh context — each iteration gets a clean context window, with no accumulated weight from thousands of prior tokens
  • Cost optimized — O(n) tokens per story instead of O(n²) from a single growing session
  • No degradation — the AI never “forgets” initial instructions because context never grows beyond a fixed threshold
  • Persistent memory — learnings are saved to progress.md and re-read at every iteration

How It Works

For each user story:
  1. Open a NEW session (fresh context)
  2. Agent reads prd.json (finds the next story)
  3. Agent reads progress.md (learns from past iterations)
  4. Implements the story, tests, commits
  5. Updates prd.json (passes: true) and progress.md
  6. Session ends → repeat with the next story

Why Cursor Subagents Are a Perfect Fit

Cursor’s subagents are custom AI agents defined as markdown files, stored in .cursor/agents/. Each subagent invocation gets its own isolated context window — exactly the property the Ralph Loop needs.

  • Context isolation by design — each /ralph-loop invocation starts in a clean, empty context
  • Explicit invocation — typing /ralph-loop is a deliberate, intentional trigger, not a background rule
  • Multiple specialized agents — a PRD creator, a story executor, and an optional verifier, each with a focused role
  • Team-shareable.cursor/agents/ files live in the repo and travel with the codebase

2. Setup: File Structure

Create this structure in your project root:

your-project/
├── .cursor/
│   └── agents/
│       ├── ralph-loop.md      # Story executor — the main workhorse
│       ├── prd-creator.md     # PRD creation helper
│       └── verifier.md        # Optional: validates completed work
├── .ralph/
│   ├── prd.md                 # Human-readable context (you write this)
│   ├── prd.json               # Structured stories with state (agent updates this)
│   └── progress.md            # Append-only learnings log (agent writes this)
├── src/
└── ...

Commands to Create the Structure

mkdir -p .cursor/agents .ralph
touch .ralph/prd.md .ralph/prd.json

The progress.md file will be created automatically by the agent on the first iteration.

The .cursor/agents/ directory should always be committed to the repo — it’s configuration, not state.


3. The Subagent Files

These three files are the heart of the system. Copy each one into .cursor/agents/.

3.1 ralph-loop.md — The Story Executor

The main subagent. Invoked with /ralph-loop at each iteration.

---
name: ralph-loop
description: >
  Autonomous story executor for the Ralph Loop pattern. Reads .ralph/prd.json,
  picks the next incomplete user story, implements it, runs quality checks,
  commits changes, and updates progress. Use this for each Ralph Loop iteration.
  Invoke with: /ralph-loop
model: inherit
---

# Ralph Loop — Story Executor

You are an autonomous coding agent. You work on ONE user story per invocation.

## Workflow

### Step 1: Read State
Open `.ralph/prd.json` and find the next story to implement:
- FIRST look for a story with `"inProgress": true` (interrupted story to resume)
- If none, pick the story with `"passes": false` and the lowest `priority` number (lower number = higher priority)
- If ALL stories have `"passes": true`, respond: **"ALL STORIES ARE COMPLETE"** and stop

### Step 2: Read Context
1. If `.ralph/progress.md` exists, read it. Read the `## Codebase Patterns` section at the TOP first — these are learnings from previous iterations, follow them.
2. Read `.ralph/prd.md` for project context, technical stack, and design notes.

### Step 3: Mark Story as In Progress
In `.ralph/prd.json`, set `"inProgress": true` on the selected story.

### Step 4: Implement the Story
Implement the user story following the description and acceptance criteria.
- Follow existing patterns in the codebase
- Keep changes focused and minimal
- Do not touch code unrelated to the story

### Step 5: Quality Checks
Run the project's quality checks (typecheck, lint, test — whatever the project requires).
- If checks fail, fix before proceeding
- Do NOT commit broken code

### Step 6: Commit
Commit your changes with this message format:

```
feat: [STORY_ID] - [STORY_TITLE]
```

CRITICAL commit rules:
- **NEVER** stage or commit files inside `.ralph/` — these are local working files
- **NEVER** use `git add -A` or `git add .`
- Stage ONLY the files you changed for the story

### Step 7: Update the PRD
In `.ralph/prd.json`:
- Set `"passes": true` on the completed story
- Set `"inProgress": false`

### Step 8: Update the Progress Log
APPEND (never replace) to `.ralph/progress.md`:

```
## [Date] - [Story ID]
- What was implemented
- Files changed
- **Learnings for future iterations:**
  - Patterns discovered (e.g., "this codebase uses X for Y")
  - Gotchas encountered (e.g., "don't forget to update Z when changing W")
  - Useful context (e.g., "the evaluation panel is in component X")
---
```

The learnings section is CRITICAL — it helps future iterations avoid repeating mistakes.

### Step 9: Consolidate Patterns
If you discover a **general, reusable pattern**, add it to the `## Codebase Patterns` section at the TOP of `.ralph/progress.md` (create it if it doesn't exist):

```
## Codebase Patterns
- Use X for Y
- Always do Z when changing W
```

Only add patterns that are general and reusable, not story-specific details.

## Stop Condition

After completing the story, check `.ralph/prd.json`:
- If ALL stories have `"passes": true` → respond: **"ALL STORIES ARE COMPLETE"**
- If stories remain → respond: **"Story [ID] completed. [N] stories remaining. Open a new Composer session and run /ralph-loop to continue."**

## Important Rules

- Work on ONE story per invocation
- Commit frequently
- Keep CI green
- ALWAYS read Codebase Patterns before starting
- NEVER commit `.ralph/` files

3.2 prd-creator.md — The PRD Creator

Invoked with /prd-creator to interactively define your feature before starting the loop.

---
name: prd-creator
description: >
  Creates a Product Requirements Document for the Ralph Loop. Asks clarifying
  questions, then generates .ralph/prd.md (human-readable context) and
  .ralph/prd.json (structured user stories). Use before starting the loop.
  Invoke with: /prd-creator
model: inherit
---

# PRD Creator

You are helping create a Product Requirements Document (PRD) for a software feature.

**Important:** Do NOT implement anything. Your ONLY job is to create the PRD files.

## Step 1: Clarifying Questions

Before writing the PRD, ask 3-5 essential clarifying questions with lettered options so the user can respond quickly (e.g., "1A, 2C, 3B"). Focus on:

- **Problem/Goal:** What problem does this solve? Why does it matter?
- **Core Functionality:** What are the key actions or behaviors?
- **Scope/Boundaries:** What should it NOT do?
- **Technical Context:** What stack, frameworks, patterns does the project use?
- **Success Criteria:** How do we know it's done and working?

Format example:
```
1. What is the primary goal?
   A. Improve user onboarding
   B. Increase retention
   C. Reduce support burden
   D. Other: [please specify]
```

## Step 2: Create the Files

After incorporating the user's answers, create both files:

### .ralph/prd.md

Include these sections:
- **Overview** — What you're building and why
- **Technical Context** — Stack, frameworks, tools, test/lint commands
- **Design Notes** — Patterns to follow, conventions, constraints
- **References** — Key files in the codebase

### .ralph/prd.json

Use this exact structure:
```json
{
  "project": "Project Name",
  "description": "Brief description",
  "userStories": [
    {
      "id": "US-001",
      "title": "Short title (max 50 chars)",
      "description": "As a [user], I want [feature] so that [benefit]",
      "acceptanceCriteria": [
        "Specific, verifiable criterion 1",
        "Specific, verifiable criterion 2"
      ],
      "priority": 1,
      "passes": false,
      "inProgress": false
    }
  ]
}
```

## Guidelines for User Stories

- Each story must be small (implementable in a single agent session)
- Acceptance criteria must be specific and verifiable — "Works correctly" is bad, "Returns 401 for invalid tokens" is good
- Order by dependency: foundations first (lower priority number), dependent features after
- ALL stories must have `passes: false` and `inProgress: false`
- If a story has more than 5–7 acceptance criteria, split it

## After Creation

Tell the user: "PRD created. Open a new Composer session and run `/ralph-loop` to start implementing."

3.3 verifier.md — The Work Validator (Optional)

Invoked with /verifier after each story. Read-only, uses a faster model, catches issues before they compound.

---
name: verifier
description: >
  Validates that a completed Ralph Loop story actually works. Checks tests pass,
  reviews code quality, and verifies acceptance criteria are met. Use after
  /ralph-loop completes a story. Read-only — does not modify code.
  Invoke with: /verifier
model: fast
readonly: true
---

# Story Verifier

You are a skeptical validator. Your job is to verify that the last completed story actually works.

## Workflow

1. Read `.ralph/prd.json` and find the most recently completed story
2. Read `.ralph/progress.md` to understand what was claimed to be implemented
3. For each acceptance criterion in the story:
   - Check that the implementation exists in the codebase
   - Verify it matches what was described
4. Run the project's test suite to confirm everything passes
5. Look for common issues:
   - Missing error handling
   - Untested edge cases
   - Broken imports or references
   - Inconsistencies with existing patterns

## Report Format

```
## Verification Report: [Story ID] - [Story Title]

### Acceptance Criteria
- [x] Criterion 1 — verified: [brief explanation]
- [x] Criterion 2 — verified: [brief explanation]
- [ ] Criterion 3 — ISSUE: [what's wrong]

### Tests
- Status: PASS / FAIL
- [details if failing]

### Code Quality
- [any concerns or all clear]

### Verdict: PASS / NEEDS WORK
[summary and next steps if issues found]
```

If issues are found, recommend whether to fix in the current story (rerun `/ralph-loop`) or move on.

4. PRD Templates

prd.json — The Structured File

The file the agent reads and updates. Each story has precise fields:

{
  "project": "Project Name",
  "description": "Brief description of what you're building",
  "userStories": [
    {
      "id": "US-001",
      "title": "Short story title",
      "description": "As a [user], I want [feature] so that [benefit]",
      "acceptanceCriteria": [
        "First specific, verifiable criterion",
        "Second specific, verifiable criterion"
      ],
      "priority": 1,
      "passes": false,
      "inProgress": false
    },
    {
      "id": "US-002",
      "title": "Second story",
      "description": "As a [user], I want [feature] so that [benefit]",
      "acceptanceCriteria": [
        "Criterion 1",
        "Criterion 2"
      ],
      "priority": 2,
      "passes": false,
      "inProgress": false
    }
  ]
}

UserStory Fields

FieldTypeDescription
idstringUnique identifier (e.g., US-001). Appears in commit messages.
titlestringShort title (max 50 chars). Appears in commit messages.
descriptionstring”As a… I want… so that…” format.
acceptanceCriteriastring[]List of verifiable criteria. The agent uses these to know when it’s done.
prioritynumberExecution order. Lower number = higher priority.
passesbooleantrue when the story is completed and verified.
inProgressbooleantrue while the agent is working on the story.

Selection Logic

The agent picks the next story as follows:

  1. If a story has inProgress: true → resume it (it was interrupted)
  2. Otherwise, pick the story with passes: false and the lowest priority number
  3. If all stories have passes: true → work is complete

prd.md — The Human-Readable Context

This file is your space to give the agent context. Write whatever helps understand the project.

# [Project Name]

## Overview
What you're building and why. What problem does it solve.

## Technical Context
- Stack: [e.g., Next.js, TypeScript, PostgreSQL]
- Framework: [e.g., Prisma ORM, Tailwind CSS]
- Tests: [e.g., Vitest, `npm test`]
- Lint: [e.g., ESLint, `npm run lint`]

## Design Notes
- Follow existing patterns in `src/middleware/`
- Use Zod for input validation
- APIs must return errors in a consistent format

## References
- User model: `prisma/schema.prisma`
- API route pattern: `src/routes/health.ts`

Best Practices for Stories

Specific acceptance criteria:

// GOOD — specific and verifiable
"acceptanceCriteria": [
  "Login form with email and password fields",
  "Error message shown for invalid credentials",
  "JWT token stored in httpOnly cookie on success",
  "Redirect to /dashboard after login"
]

// BAD — vague and subjective
"acceptanceCriteria": [
  "Nice login page",
  "Good error handling",
  "Secure authentication"
]

Small stories — if a story has more than 5–7 acceptance criteria, split it.

Order by dependency — foundation stories first:

[
  { "id": "US-001", "title": "Database Schema", "priority": 1 },
  { "id": "US-002", "title": "API Endpoints", "priority": 2 },
  { "id": "US-003", "title": "Frontend Forms", "priority": 3 },
  { "id": "US-004", "title": "Integration Tests", "priority": 4 }
]

5. Creating the PRD

  1. Open a Composer session (Cmd+I / Ctrl+I), select Agent mode
  2. Type: /prd-creator
  3. Answer the clarifying questions (e.g., “1A, 2C, 3B”)
  4. The subagent creates both .ralph/prd.md and .ralph/prd.json
  5. Close this session and open a new one to start the loop

Option B: Manually

  1. Copy the templates from section 4 into .ralph/prd.md and .ralph/prd.json
  2. Fill in prd.md with your project context
  3. Define the user stories in prd.json
  4. Make sure all stories have passes: false and inProgress: false

6. Running the Loop: Step-by-Step

Initial Setup (One Time Only)

  1. Copy the three subagent files into .cursor/agents/
  2. Create the .ralph/ directory with prd.md and prd.json (section 5)
  3. Optional: create a dedicated branch — git checkout -b feature/feature-name
  4. Optional: add .ralph/ to .gitignore

For Each Iteration

LOOP:

├─ 1. Open a NEW Composer session
│     - Cmd+I (Mac) or Ctrl+I (Windows/Linux)
│     - Select "Agent" mode

├─ 2. Type: /ralph-loop
│     (the subagent has all instructions built in)

├─ 3. Subagent works autonomously in its own isolated context
│     - Reads prd.json → finds the next story
│     - Reads progress.md → learns from past iterations
│     - Implements → tests → commits
│     - Updates prd.json and progress.md

├─ 4. Subagent reports the result:
│     - "Story US-XXX completed. N stories remaining."
│     - or "ALL STORIES ARE COMPLETE"

├─ 5. (Optional) Type: /verifier
│     - Validates the work in read-only mode
│     - Uses a faster/cheaper model
│     - Reports pass/fail with details

└─ 6. If stories remain → open new session → go to step 2
      If all complete → done!

When Something Goes Wrong

If the agent gets stuck or produces bad output:

  1. Stop the current session
  2. Open a new session — fresh context, no confusion
  3. Type: /ralph-loop — the inProgress field ensures it picks up the same story

If a story is too complex:

  1. Manually edit prd.json: split the story into smaller stories
  2. Reset inProgress: false on the problematic story
  3. Open a new session and run /ralph-loop

7. Advanced Tips

Dedicated Branch per PRD

Before starting the loop:

git checkout -b feature/feature-name

All story commits land on a clean branch you can review, merge, or use for a PR.

Check Progress at a Glance

cat .ralph/prd.json | python3 -c "
import json, sys
prd = json.load(sys.stdin)
stories = prd['userStories']
done = sum(1 for s in stories if s['passes'])
print(f'{done}/{len(stories)} stories completed')
for s in stories:
    status = 'DONE' if s['passes'] else ('IN PROGRESS' if s['inProgress'] else 'TODO')
    print(f'  [{status}] {s[\"id\"]}: {s[\"title\"]}')
"

Resuming After an Interruption

The inProgress field handles this automatically. If you interrupt a session mid-work:

  1. The story stays with inProgress: true in prd.json
  2. On the next /ralph-loop invocation, the subagent finds it and resumes
  3. No manual intervention needed

Multi-PRD: Multiple Features in Parallel

For multiple concurrent features, use subdirectories:

.ralph/
├── auth-system/
│   ├── prd.md
│   ├── prd.json
│   └── progress.md
└── payments/
    ├── prd.md
    ├── prd.json
    └── progress.md

Update the paths in ralph-loop.md to point to the right subdirectory, or maintain separate subagent files per feature.

Tips to Maximize Quality

  1. Write a detailed prd.md — the more context you give, the better the output. Include patterns, conventions, reference files.
  2. Small, atomic stories — one story = one logical feature. If it feels too large, split it.
  3. Verifiable acceptance criteria — “the button works” is bad; “the button shows a confirmation dialog before deleting” is good.
  4. Run /verifier after each story — catches issues early, much cheaper to fix now than five stories later.
  5. Review each commit — a quick glance at the diff after each iteration keeps you in control.
  6. Update prd.md as needed — if the technical context changes mid-build, update it before the next iteration.