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."
Ralph is a technique for autonomous AI development that treats LLM context like memory:
while :; do cat PROMPT.md | agent ; doneThe 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.
In traditional programming:
malloc()allocates memoryfree()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:
- Context pollution - Failed attempts, unrelated code, and mixed concerns accumulate and confuse the model
- 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.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β 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 β
β β
β When ROTATE β fresh context, continue from git β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
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)
- Learning from failures - Agent updates
.ralph/guardrails.mdwith 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
| Requirement | Check | How to Set Up |
|---|---|---|
| Git repo | git status works |
git init |
| cursor-agent CLI | which cursor-agent |
curl https://cursor.com/install -fsS | bash |
| gum (optional) | which gum |
brew install gum - for enhanced UI |
cd your-project
curl -fsSL https://raw.githubusercontent.com/agrimsingh/ralph-wiggum-cursor/main/install.sh | bashThis 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)
β βββ stream-parser.sh # Token tracking
β βββ ralph-common.sh # Shared functions
β βββ 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)
βββ RALPH_TASK.md # Your task definition
brew install gumWith 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
Without gum, Ralph falls back to simple numbered prompts.
Edit RALPH_TASK.md:
---
task: Build a REST API
test_command: "npm 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.
./.cursor/ralph-scripts/ralph-setup.shRalph will:
- Show interactive UI for model and options (or simple prompts if gum not installed)
- Run
cursor-agentwith your task - Parse output in real-time, tracking token usage
- At 70k tokens: warn agent to wrap up current work
- At 80k tokens: rotate to fresh context
- Repeat until all
[ ]are[x](or max iterations reached)
# 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 npm 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| Command | Description |
|---|---|
ralph-setup.sh |
Primary - Interactive setup + run loop |
ralph-once.sh |
Test single iteration before going AFK |
ralph-loop.sh |
CLI mode for scripting (see flags below) |
init-ralph.sh |
Re-initialize Ralph state |
./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 Create and work on a new branch
--pr Open PR when complete (requires --branch)
-y, --yes Skip confirmation promptExamples:
# 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-highIteration 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:
- Reads task and state from files (not from previous context)
- Works on unchecked criteria
- Commits progress to git
- Updates
.ralph/progress.mdand.ralph/guardrails.md - Rotates when context is full
The agent is instructed to commit frequently:
# After each criterion
git add -A && git commit -m 'ralph: [criterion] - description'
# Push periodically
git pushCommits are the agent's memory. The next iteration picks up from git history.
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 failureFuture iterations read guardrails first and follow them, preventing repeated mistakes.
Error occurs β errors.log β Agent analyzes β Updates guardrails.md β Future agents follow
The activity log shows context health with emoji:
| Emoji | Status | Token % | Meaning |
|---|---|---|---|
| π’ | Healthy | < 60% | Plenty of room |
| π‘ | Warning | 60-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
The parser detects when the agent is stuck:
| Pattern | Trigger | What Happens |
|---|---|---|
| Repeated failure | Same command failed 3x | GUTTER signal |
| File thrashing | Same file written 5x in 10 min | GUTTER signal |
| Agent signals | Agent outputs <ralph>GUTTER</ralph> |
GUTTER signal |
When gutter is detected:
- Check
.ralph/errors.logfor the pattern - Fix the issue manually or add a guardrail
- Re-run the loop
Ralph detects completion in two ways:
- Checkbox check: All
[ ]in RALPH_TASK.md changed to[x] - Agent sigil: Agent outputs
<ralph>COMPLETE</ralph>
Both are verified before declaring success.
| File | Purpose | Who Uses It |
|---|---|---|
RALPH_TASK.md |
Task definition + success criteria | You define, agent reads |
.ralph/progress.md |
What's been accomplished | Agent writes after work |
.ralph/guardrails.md |
Lessons learned (Signs) | Agent reads first, writes after failures |
.ralph/activity.log |
Tool call log with token counts | Parser writes, you monitor |
.ralph/errors.log |
Failures + gutter detection | Parser writes, agent reads |
.ralph/.iteration |
Current iteration number | Parser reads/writes |
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.shDefault 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 rotationcurl https://cursor.com/install -fsS | bashCheck .ralph/errors.log for the pattern. Either:
- Fix the underlying issue manually
- Add a guardrail to
.ralph/guardrails.mdexplaining what to do differently
The agent might be reading too many large files. Check activity.log for large READs and consider:
- Adding a guardrail: "Don't read the entire file, use grep to find relevant sections"
- Breaking the task into smaller pieces
Check if criteria are too vague. Each criterion should be:
- Specific and testable
- Achievable in a single iteration
- Not dependent on manual steps
./ralph-setup.sh # Interactive setup β runs loop β done./ralph-once.sh # Run ONE iteration
# Review changes...
./ralph-setup.sh # Continue with full loop./ralph-loop.sh --branch feature/foo --pr -y- Original Ralph technique - Geoffrey Huntley
- Context as memory - The malloc/free metaphor
- Cursor CLI docs
- gum - A tool for glamorous shell scripts
- Original technique: Geoffrey Huntley - the Ralph Wiggum methodology
- Cursor port: Agrim Singh - this implementation
MIT