Ralph Wiggum for Cursor

January 26, 2026 · View on GitHub

An implementation of Geoffrey Huntley's Ralph Wiggum technique for Cursor, enabling autonomous AI development with deliberate context management.

"That's the beauty of Ralph - the technique is deterministically bad in an undeterministic world."

What is Ralph?

Ralph is a technique for autonomous AI development that treats LLM context like memory:

while :; do cat PROMPT.md | agent ; done

The same prompt is fed repeatedly to an AI agent. Progress persists in files and git, not in the LLM's context window. When context fills up, you get a fresh agent with fresh context.

The malloc/free Problem

In traditional programming:

  • malloc() allocates memory
  • free() releases memory

In LLM context:

  • Reading files, tool outputs, conversation = malloc()
  • There is no free() - context cannot be selectively released
  • Only way to free: start a new conversation

This creates two problems:

  1. Context pollution - Failed attempts, unrelated code, and mixed concerns accumulate and confuse the model
  2. The gutter - Once polluted, the model keeps referencing bad context. Like a bowling ball in the gutter, there's no saving it.

Ralph's solution: Deliberately rotate to fresh context before pollution builds up. State lives in files and git, not in the LLM's memory.

Architecture

┌─────────────────────────────────────────────────────────────┐
│                      ralph-setup.sh                          │
│                           │                                  │
│              ┌────────────┴────────────┐                    │
│              ▼                         ▼                    │
│         [gum UI]                  [fallback]                │
│     Model selection            Simple prompts               │
│     Max iterations                                          │
│     Options (branch, PR)                                    │
│              │                         │                    │
│              └────────────┬────────────┘                    │
│                           ▼                                  │
│    cursor-agent -p --force --output-format stream-json       │
│                           │                                  │
│                           ▼                                  │
│                   stream-parser.sh                           │
│                      │        │                              │
│     ┌────────────────┴────────┴────────────────┐            │
│     ▼                                           ▼            │
│  .ralph/                                    Signals          │
│  ├── activity.log  (tool calls)            ├── WARN at 70k  │
│  ├── errors.log    (failures)              ├── ROTATE at 80k│
│  ├── progress.md   (agent writes)          ├── COMPLETE     │
│  ├── guardrails.md (lessons learned)       ├── GUTTER       │
│  └── tasks.yaml    (cached task state)     └── DEFER        │
│                                                              │
│  When ROTATE → fresh context, continue from git             │
│  When DEFER → exponential backoff, retry same task          │
└─────────────────────────────────────────────────────────────┘

Key features:

  • Interactive setup - Beautiful gum-based UI for model selection and options
  • Accurate token tracking - Parser counts actual bytes from every file read/write
  • Gutter detection - Detects when agent is stuck (same command failed 3x, file thrashing)
  • Rate limit handling - Detects rate limits/network errors, waits with exponential backoff
  • Task caching - YAML backend with mtime invalidation for efficient task parsing
  • Learning from failures - Agent updates .ralph/guardrails.md with lessons
  • State in git - Commits frequently so next agent picks up from git history
  • Branch/PR workflow - Optionally work on a branch and open PR when complete

Prerequisites

RequirementCheckHow to Set Up
Git repogit status worksgit init
cursor-agent CLIwhich cursor-agentcurl https://cursor.com/install -fsS | bash
gum (optional)which gumInstaller offers to install, or brew install gum

Quick Start

1. Install Ralph

cd your-project
curl -fsSL https://raw.githubusercontent.com/agrimsingh/ralph-wiggum-cursor/main/install.sh | bash

This creates:

your-project/
├── .cursor/ralph-scripts/      # Ralph scripts
│   ├── ralph-setup.sh          # Main entry point (interactive)
│   ├── ralph-loop.sh           # CLI mode (for scripting)
│   ├── ralph-once.sh           # Single iteration (testing)
│   ├── ralph-parallel.sh       # Parallel execution with worktrees
│   ├── stream-parser.sh        # Token tracking + error detection
│   ├── ralph-common.sh         # Shared functions
│   ├── ralph-retry.sh          # Exponential backoff retry logic
│   ├── task-parser.sh          # YAML-backed task parsing
│   └── init-ralph.sh           # Re-initialize if needed
├── .ralph/                     # State files (tracked in git)
│   ├── progress.md             # Agent updates: what's done
│   ├── guardrails.md           # Lessons learned (Signs)
│   ├── activity.log            # Tool call log (parser writes)
│   ├── errors.log              # Failure log (parser writes)
│   └── tasks.yaml              # Cached task state (auto-generated)
├── .ralph-worktrees/           # Temporary (parallel mode only)
└── RALPH_TASK.md               # Your task definition

2. (Optional) gum for Enhanced UI

The installer will offer to install gum automatically. You can also:

  • Skip the prompt and auto-install: curl ... | INSTALL_GUM=1 bash
  • Install manually: brew install gum (macOS) or see gum installation

With gum, you get a beautiful interactive menu for selecting models and options:

? Select model:
  ◉ opus-4.5-thinking
  ◯ sonnet-4.5-thinking
  ◯ gpt-5.2-high
  ◯ composer-1
  ◯ Custom...

? Max iterations: 20

? Options:
  ◯ Commit to current branch
  ◯ Run single iteration first
  ◯ Work on new branch
  ◯ Open PR when complete
  ◯ Run in parallel mode         ← runs multiple agents concurrently

If you select "Run in parallel mode", you'll be prompted for:

? Max parallel agents: 3         ← default is 3, enter any number

Without gum, Ralph falls back to simple numbered prompts.

3. Define Your Task

Edit RALPH_TASK.md:

---
task: Build a REST API
test_command: "pnpm test"
---

# Task: REST API

Build a REST API with user management.

## Success Criteria

1. [ ] GET /health returns 200
2. [ ] POST /users creates a user  
3. [ ] GET /users/:id returns user
4. [ ] All tests pass

## Context

- Use Express.js
- Store users in memory (no database needed)

Important: Use [ ] checkboxes. Ralph tracks completion by counting unchecked boxes.

4. Start the Loop

./.cursor/ralph-scripts/ralph-setup.sh

Ralph will:

  1. Show interactive UI for model and options (or simple prompts if gum not installed)
  2. Run cursor-agent with your task
  3. Parse output in real-time, tracking token usage
  4. At 70k tokens: warn agent to wrap up current work
  5. At 80k tokens: rotate to fresh context
  6. Repeat until all [ ] are [x] (or max iterations reached)

5. Monitor Progress

# Watch activity in real-time
tail -f .ralph/activity.log

# Example output:
# [12:34:56] 🟢 READ src/index.ts (245 lines, ~24.5KB)
# [12:34:58] 🟢 WRITE src/routes/users.ts (50 lines, 2.1KB)
# [12:35:01] 🟢 SHELL pnpm test → exit 0
# [12:35:10] 🟢 TOKENS: 45,230 / 80,000 (56%) [read:30KB write:5KB assist:10KB shell:0KB]

# Check for failures
cat .ralph/errors.log

Commands

CommandDescription
ralph-setup.shPrimary - Interactive setup + run loop
ralph-once.shTest single iteration before going AFK
ralph-loop.shCLI mode for scripting (see flags below)
init-ralph.shRe-initialize Ralph state

ralph-loop.sh Flags (for scripting/CI)

./ralph-loop.sh [options] [workspace]

Options:
  -n, --iterations N     Max iterations (default: 20)
  -m, --model MODEL      Model to use (default: opus-4.5-thinking)
  --branch NAME          Sequential: create/work on branch; Parallel: integration branch name
  --pr                   Sequential: open PR (requires --branch); Parallel: open ONE integration PR (branch optional)
  --parallel             Run tasks in parallel with worktrees
  --max-parallel N       Max parallel agents (default: 3)
  --no-merge             Skip auto-merge in parallel mode
  -y, --yes              Skip confirmation prompt

Examples:

# Scripted PR workflow
./ralph-loop.sh --branch feature/api --pr -y

# Use a different model with more iterations
./ralph-loop.sh -n 50 -m gpt-5.2-high

# Run 4 agents in parallel
./ralph-loop.sh --parallel --max-parallel 4

# Parallel: keep branches separate
./ralph-loop.sh --parallel --no-merge

# Parallel: merge into an integration branch + open ONE PR
./ralph-loop.sh --parallel --max-parallel 5 --branch feature/multi-task --pr

# Parallel: open ONE PR using an auto-named integration branch
./ralph-loop.sh --parallel --max-parallel 5 --pr

Parallel Execution

Ralph can run multiple agents concurrently, each in an isolated git worktree.

Starting Parallel Mode

Via gum UI (interactive):

./ralph-setup.sh
# Select "Run in parallel mode" in options
# Enter number of agents when prompted (default: 3, no upper limit)

Via CLI (scripting/CI):

# Run 3 agents in parallel (default)
./ralph-loop.sh --parallel

# Run 10 agents in parallel (no hard cap)
./ralph-loop.sh --parallel --max-parallel 10

# Keep branches separate (no auto-merge)
./ralph-loop.sh --parallel --no-merge

# Merge into an integration branch (no PR)
./ralph-loop.sh --parallel --max-parallel 5 --branch feature/multi-task

# Merge into an integration branch and open ONE PR
./ralph-loop.sh --parallel --max-parallel 5 --branch feature/multi-task --pr

# Open ONE PR using an auto-named integration branch
./ralph-loop.sh --parallel --max-parallel 5 --pr

Note: There's no hard limit on --max-parallel. The practical limit depends on your machine's resources and API rate limits.

Integration branch + single PR

Parallel --pr creates one integration branch (either your --branch NAME or an auto-named ralph/parallel-<run_id>), merges all successful agent branches into it, then opens one PR back to the base branch.

This avoids “one PR per task” spam while keeping agents isolated.

How Parallel Mode Works

┌────────────────────────────────────────────────────────────────┐
│                    Parallel Execution Flow                      │
├────────────────────────────────────────────────────────────────┤
│                                                                  │
│  RALPH_TASK.md                                                  │
│  - [ ] Task A                                                    │
│  - [ ] Task B           ┌──────────────────────────┐            │
│  - [ ] Task C     ───▶  │   Create Worktrees       │            │
│                         └──────────────────────────┘            │
│                                    │                             │
│                    ┌───────────────┼───────────────┐            │
│                    ▼               ▼               ▼            │
│              ┌──────────┐   ┌──────────┐   ┌──────────┐         │
│              │ Agent 1  │   │ Agent 2  │   │ Agent 3  │         │
│              │ worktree │   │ worktree │   │ worktree │         │
│              │  Task A  │   │  Task B  │   │  Task C  │         │
│              └────┬─────┘   └────┬─────┘   └────┬─────┘         │
│                   │              │              │                │
│                   ▼              ▼              ▼                │
│              branch-a       branch-b       branch-c              │
│                   │              │              │                │
│                   └──────────────┼──────────────┘                │
│                                  ▼                               │
│                         ┌──────────────┐                        │
│                         │  Auto-Merge  │                        │
│                         │  to base     │                        │
│                         └──────────────┘                        │
└────────────────────────────────────────────────────────────────┘

Key benefits:

  • Each agent works in complete isolation (separate git worktree)
  • No interference between agents working on different tasks
  • Branches auto-merge after completion (or keep separate with --no-merge)
  • Conflict detection and reporting
  • Tasks are processed in batches (e.g., 5 agents = 5 tasks per batch)
  • In parallel mode, agents do not update .ralph/progress.md (they write per-agent reports instead)

When to use parallel mode:

  • Multiple independent tasks that don't conflict
  • Large task lists you want completed faster
  • CI/CD pipelines with parallelization budget

When to use sequential mode:

  • Tasks that depend on each other
  • Single complex task that needs focused attention
  • Limited API rate limits

For best results, structure your work in two phases:

Phase 1: Parallel execution (isolated, independent tasks)

# Tasks
- [ ] Add user authentication to /api/auth
- [ ] Create dashboard component
- [ ] Implement data export feature
- [ ] Add unit tests for utils/

Phase 2: Integration pass (one sequential agent, repo-wide polish)

# Tasks
- [ ] Update README with new features
- [ ] Bump version in package.json
- [ ] Update CHANGELOG
- [ ] Fix any integration issues from parallel work

This pattern maximizes parallelism while avoiding merge conflicts on shared files. The integration pass runs after parallel agents finish and handles all "touch everything" work.

Task Groups (Phased Execution)

Control execution order with <!-- group: N --> annotations:

# Tasks

- [ ] Create database schema <!-- group: 1 -->
- [ ] Create User model <!-- group: 1 -->
- [ ] Create Post model <!-- group: 1 -->
- [ ] Add relationships between models <!-- group: 2 -->
- [ ] Build API endpoints <!-- group: 3 -->
- [ ] Update README  # no annotation = runs LAST

Execution order:

  1. Group 1 - runs first (all tasks in parallel, up to --max-parallel)
  2. Group 2 - runs after group 1 merges complete
  3. Group 3 - runs after group 2 merges complete
  4. Unannotated tasks - run LAST (after all annotated groups)

Why unannotated = last?

  • Safer default: forgetting to annotate doesn't jump the queue
  • Integration/polish tasks naturally go last
  • Override with DEFAULT_GROUP=0 env var if you prefer unannotated first

Within each group:

  • Tasks run in parallel (up to --max-parallel)
  • All merges complete before next group starts
  • RALPH_TASK.md checkboxes updated per group

Worktree structure:

project/
├── .ralph-worktrees/           # Temporary worktrees (auto-cleaned)
│   ├── <run_id>-job1/          # Agent worktree (isolated)
│   ├── <run_id>-job2/          # Agent worktree (isolated)
│   └── <run_id>-job3/          # Agent worktree (isolated)
└── (original project files)

Worktrees are automatically cleaned up after agents complete. Failed agents preserve their worktree for manual inspection.

Parallel logs & per-agent reports

Each parallel run creates a run directory:

.ralph/parallel/<run_id>/
├── manifest.tsv                # job_id -> task_id -> branch -> status -> log
└── jobN.log                    # full cursor-agent output for that job

Agents are instructed to write a committed per-agent report (to avoid .ralph/progress.md merge conflicts):

.ralph/parallel/<run_id>/agent-jobN.md

How It Works

The Loop

Iteration 1                    Iteration 2                    Iteration N
┌──────────────────┐          ┌──────────────────┐          ┌──────────────────┐
│ Fresh context    │          │ Fresh context    │          │ Fresh context    │
│       │          │          │       │          │          │       │          │
│       ▼          │          │       ▼          │          │       ▼          │
│ Read RALPH_TASK  │          │ Read RALPH_TASK  │          │ Read RALPH_TASK  │
│ Read guardrails  │──────────│ Read guardrails  │──────────│ Read guardrails  │
│ Read progress    │  (state  │ Read progress    │  (state  │ Read progress    │
│       │          │  in git) │       │          │  in git) │       │          │
│       ▼          │          │       ▼          │          │       ▼          │
│ Work on criteria │          │ Work on criteria │          │ Work on criteria │
│ Commit to git    │          │ Commit to git    │          │ Commit to git    │
│       │          │          │       │          │          │       │          │
│       ▼          │          │       ▼          │          │       ▼          │
│ 80k tokens       │          │ 80k tokens       │          │ All [x] done!    │
│ ROTATE ──────────┼──────────┼──────────────────┼──────────┼──► COMPLETE      │
└──────────────────┘          └──────────────────┘          └──────────────────┘

Each iteration:

  1. Reads task and state from files (not from previous context)
  2. Works on unchecked criteria
  3. Commits progress to git
  4. Updates .ralph/progress.md and .ralph/guardrails.md
  5. Rotates when context is full

Git Protocol

The agent is instructed to commit frequently:

# After each criterion
git add -A && git commit -m 'ralph: [criterion] - description'

# Push periodically
git push

Commits are the agent's memory. The next iteration picks up from git history.

The Learning Loop (Signs)

When something fails, the agent adds a "Sign" to .ralph/guardrails.md:

### Sign: Check imports before adding
- **Trigger**: Adding a new import statement
- **Instruction**: First check if import already exists in file
- **Added after**: Iteration 3 - duplicate import caused build failure

Future iterations read guardrails first and follow them, preventing repeated mistakes.

Error occurs → errors.log → Agent analyzes → Updates guardrails.md → Future agents follow

Context Health Indicators

The activity log shows context health with emoji:

EmojiStatusToken %Meaning
🟢Healthy< 60%Plenty of room
🟡Warning60-80%Approaching limit
🔴Critical> 80%Rotation imminent

Example:

[12:34:56] 🟢 READ src/index.ts (245 lines, ~24.5KB)
[12:40:22] 🟡 TOKENS: 58,000 / 80,000 (72%) - approaching limit [read:40KB write:8KB assist:10KB shell:0KB]
[12:45:33] 🔴 TOKENS: 72,500 / 80,000 (90%) - rotation imminent

Gutter Detection

The parser detects when the agent is stuck:

PatternTriggerWhat Happens
Repeated failureSame command failed 3xGUTTER signal
File thrashingSame file written 5x in 10 minGUTTER signal
Agent signalsAgent outputs <ralph>GUTTER</ralph>GUTTER signal

When gutter is detected:

  1. Check .ralph/errors.log for the pattern
  2. Fix the issue manually or add a guardrail
  3. Re-run the loop

Rate Limit & Transient Error Handling

The parser detects retryable API errors and handles them gracefully:

Error TypeExamplesWhat Happens
Rate limits429, "rate limit exceeded", "quota"DEFER signal
Network errorstimeout, connection reset, ECONNRESETDEFER signal
Server errors502, 503, 504, "service unavailable"DEFER signal

When DEFER is triggered:

  1. Agent stops current iteration
  2. Waits with exponential backoff (15s base, doubles each retry, max 120s)
  3. Adds jitter (0-25%) to prevent thundering herd
  4. Retries the same task (does not increment iteration)

Example log:

⏸️  Rate limit or transient error detected.
   Waiting 32s before retrying (attempt 2)...
   Resuming...

Completion Detection

Ralph detects completion in two ways:

  1. Checkbox check: All [ ] in RALPH_TASK.md changed to [x]
  2. Agent sigil: Agent outputs <ralph>COMPLETE</ralph>

Both are verified before declaring success.

File Reference

FilePurposeWho Uses It
RALPH_TASK.mdTask definition + success criteriaYou define, agent reads
.ralph/progress.mdWhat's been accomplishedAgent writes after work
.ralph/guardrails.mdLessons learned (Signs)Agent reads first, writes after failures
.ralph/activity.logTool call log with token countsParser writes, you monitor
.ralph/errors.logFailures + gutter detectionParser writes, agent reads
.ralph/tasks.yamlCached task state (auto-generated)Task parser writes/reads
.ralph/tasks.mtimeTask file modification timeCache invalidation
.ralph/.iterationCurrent iteration numberParser reads/writes

Configuration

Configuration is set via command-line flags or environment variables:

# Via flags (recommended)
./ralph-loop.sh -n 50 -m gpt-5.2-high

# Via environment
RALPH_MODEL=gpt-5.2-high MAX_ITERATIONS=50 ./ralph-loop.sh

Default thresholds in ralph-common.sh:

MAX_ITERATIONS=20       # Max rotations before giving up
WARN_THRESHOLD=70000    # Tokens: send wrapup warning
ROTATE_THRESHOLD=80000  # Tokens: force rotation

Troubleshooting

"cursor-agent CLI not found"

curl https://cursor.com/install -fsS | bash

Agent keeps failing on same thing

Check .ralph/errors.log for the pattern. Either:

  1. Fix the underlying issue manually
  2. Add a guardrail to .ralph/guardrails.md explaining what to do differently

Context rotates too frequently

The agent might be reading too many large files. Check activity.log for large READs and consider:

  1. Adding a guardrail: "Don't read the entire file, use grep to find relevant sections"
  2. Breaking the task into smaller pieces

Task never completes

Check if criteria are too vague. Each criterion should be:

  • Specific and testable
  • Achievable in a single iteration
  • Not dependent on manual steps

Workflows

Basic (default)

./ralph-setup.sh  # Interactive setup → runs loop → done
./ralph-once.sh   # Run ONE iteration
# Review changes...
./ralph-setup.sh  # Continue with full loop

Scripted/CI

./ralph-loop.sh --branch feature/foo --pr -y

Learn More

Credits

License

MIT