Ralph Wiggum — Continuous Self-Referential AI Loops
Autonomous Iteration Engine
Implements autonomous iteration where Claude works on a task repeatedly, reading its own previous output from files and git history to improve. Uses a Stop hook to block session exit and re-feed the prompt until a completion promise is satisfied.
🔄 Autonomous Loop🛑 Stop Hook📋 State Tracking✅ Completion Promise
📚 What is this & why does it exist?
Ralph Wiggum enables Claude Code to work autonomously in iterative loops. Instead of completing a single session and stopping, the plugin intercepts the session exit via a Stop hook, reads its own previous output from state files and git history, and re-feeds the prompt to continue improving. This creates a self-referential improvement cycle where each iteration builds on the last, controlled by a configurable completion promise and maximum iteration count.
💡 Real-world analogy
Think of a painter who steps back from the canvas, evaluates what they see, takes notes on what to improve, then steps forward again to make another pass — repeating until the painting matches their original vision statement. Ralph Wiggum is that evaluation-and-retry loop for Claude. The state file is the painter's notes, the completion promise is the vision statement, and the stop hook is the mechanism that keeps them at the easel instead of leaving the studio.
Architecture
flowchart LR
subgraph UserEntry["User Interaction"]
U["User"] -->|"/ralph-loop"| RL["Start Loop"]
U -->|"/cancel-ralph"| CR["Cancel Loop"]
U -->|"/ralph-wiggum:help"| HLP["Show Help"]
end
subgraph LoopEngine["Autonomous Loop Engine"]
RL --> INIT["Initialize State File"]
INIT --> WORK["Claude Performs Work"]
WORK --> EXIT["Session Attempts Exit"]
EXIT --> SH["stop-hook.sh Intercepts"]
SH --> RS["Read State File"]
RS --> CHECK{"Completion
Promise Met?"}
CHECK -->|No| RF["Re-feed Prompt"]
RF --> INCR["Increment Iteration"]
INCR --> WORK
CHECK -->|Yes| DONE["Allow Exit"]
end
subgraph StateManagement["State"]
SF["ralph-loop.local.md"]
GH["Git History"]
RS --> SF
RS --> GH
end
Commands
| Command | Description | Arguments |
|---|---|---|
/ralph-loop | Starts the autonomous iteration loop. Initializes the state file with YAML frontmatter, sets the completion promise, and begins the first work cycle. | --max-iterations <n> (default: 10), --promise "<text>" |
/cancel-ralph | Gracefully stops the loop after the current iteration completes. Sets the state file's cancelled: true flag so the stop hook allows exit. | None |
/ralph-wiggum:help | Displays usage information, current loop status, and configuration options. | None |
Hook Mechanism
stop-hook.sh
The core of the plugin is a Stop event hook that intercepts Claude Code's session exit. When the session would normally terminate, the hook:
- Reads the state file (
ralph-loop.local.md) to get current iteration count and completion promise - Checks git history for recent changes made in the current loop
- Evaluates whether the completion promise text is satisfied
- If not complete and under max iterations: blocks exit, increments counter, re-feeds the prompt
- If complete or max iterations reached: allows normal exit with a summary
sequenceDiagram
participant User
participant Claude as Claude Code
participant Hook as stop-hook.sh
participant State as ralph-loop.local.md
participant Git as Git History
User->>Claude: /ralph-loop --promise "all tests pass"
Claude->>State: Create state file (iteration: 0, max: 10)
Claude->>Claude: Perform work (iteration 1)
Claude->>Hook: Session exit triggered
Hook->>State: Read current state
State-->>Hook: iteration: 1, promise: "all tests pass"
Hook->>Git: Check recent commits & diff
Git-->>Hook: Changes summary
Hook->>Hook: Evaluate completion promise
Hook-->>Claude: Promise NOT met → block exit
Hook->>State: Update iteration: 2
Hook->>Claude: Re-feed prompt with context
Claude->>Claude: Perform work (iteration 2)
Claude->>Hook: Session exit triggered
Hook->>State: Read current state
Hook->>Git: Check recent commits
Hook->>Hook: Evaluate completion promise
Hook-->>Claude: Promise MET → allow exit
Claude-->>User: Loop complete (2 iterations)
State File Format
The state file ralph-loop.local.md uses YAML frontmatter to track loop state. It is created in the project root and is gitignored by convention (the .local. suffix).
---
iteration: 3
max_iterations: 10
completion_promise: "all tests pass and coverage exceeds 80%"
started_at: "2026-03-25T14:30:00Z"
last_iteration_at: "2026-03-25T14:45:22Z"
cancelled: false
status: "in_progress"
---
## Iteration Log
### Iteration 1
- Fixed failing test in auth module
- Coverage: 72%
### Iteration 2
- Added missing edge case tests
- Coverage: 78%
### Iteration 3
- Refactored test helpers, added integration tests
- Coverage: 83% ✓
Key Components
| Component | File | Role |
|---|---|---|
ralph-loop | commands/ralph-loop.md | Main command to start autonomous iteration loop |
cancel-ralph | commands/cancel-ralph.md | Gracefully stop the loop after current iteration |
ralph-wiggum:help | commands/help.md | Display usage and current loop status |
stop-hook.sh | hooks/stop-hook.sh | Intercepts session exit, evaluates state, re-feeds prompt |
state-manager | lib/state-manager.sh | Reads and writes the YAML frontmatter state file |
git-reader | lib/git-reader.sh | Extracts recent git changes for context injection |
promise-evaluator | lib/promise-evaluator.sh | Checks if completion promise is satisfied |
plugin.json | .claude-plugin/plugin.json | Plugin manifest with hook registration |
Data Flow
flowchart TD
subgraph Initialization
CMD["/ralph-loop --promise 'tests pass'"] --> PARSE["Parse Arguments"]
PARSE --> CREATE["Create State File"]
CREATE --> REGISTER["Register Stop Hook"]
end
subgraph IterationCycle["Each Iteration"]
REGISTER --> WORK["Claude Performs Work"]
WORK --> COMMIT["Changes Committed"]
COMMIT --> TRIGGER["Exit Triggers Hook"]
TRIGGER --> READ["Read State + Git"]
READ --> EVAL{"Promise
Evaluation"}
EVAL -->|"Not Met"| UPDATE["Update State File"]
UPDATE --> REFEED["Re-feed Prompt"]
REFEED --> WORK
EVAL -->|"Met"| SUMMARY["Generate Summary"]
end
subgraph Termination
SUMMARY --> LOG["Write Final Log"]
LOG --> CLEANUP["Clean Up Hook"]
CLEANUP --> EXIT["Session Exits"]
end
Interactions
| Module | Interface | Data Exchanged |
|---|---|---|
| Claude Code CLI | Stop Hook event | Session exit signal intercepted and conditionally blocked |
| Git | CLI commands | Recent commits, diffs, and file change lists for context |
| File System | State file I/O | YAML frontmatter state with iteration count and promise |
| Claude Code Prompt | Re-feed mechanism | Previous context, iteration log, and remaining work summary |
| User | Commands | Loop configuration, cancellation, and status queries |
Directory Map
Source tree for Ralph Wiggum
ralph-wiggum/
├── .claude-plugin/plugin.json ← Plugin manifest with hook registration
├── README.md ← Plugin documentation
├── commands/
│ ├── ralph-loop.md ← Start autonomous loop command
│ ├── cancel-ralph.md ← Cancel loop command
│ └── help.md ← Help and status command
├── hooks/
│ └── stop-hook.sh ← Core stop event interceptor
└── lib/
├── state-manager.sh ← YAML state file read/write
├── git-reader.sh ← Git history context extraction
└── promise-evaluator.sh ← Completion promise checker
Configuration Reference
| Parameter | Default | Description |
|---|---|---|
max_iterations | 10 | Maximum number of loop iterations before forced exit |
completion_promise | (required) | Natural language description of the goal that must be satisfied to end the loop |
state_file_path | ralph-loop.local.md | Path to the state file relative to project root |
git_context_depth | 5 | Number of recent commits to include as context |
auto_commit | true | Whether to auto-commit changes after each iteration |
cooldown_seconds | 0 | Delay between iterations to avoid rate limits |
verbose_logging | false | Write detailed iteration logs to the state file body |
Error Handling
⚠️ Max Iterations Reached
When the iteration count exceeds max_iterations, the hook allows exit and writes a summary noting the promise was not met. The state file status is set to max_reached.
🛑 Corrupted State File
If the state file is missing or has invalid YAML, the hook fails open (allows exit) and logs an error. The user can re-run /ralph-loop to start fresh.
🔄 Cancellation
Running /cancel-ralph sets cancelled: true in the state file. The next time the stop hook fires, it sees the flag and allows graceful exit with a partial summary.