spacehub

surshar / claude-code

Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.

Built by Anthropic ยท github.com/anthropics

feat: Add ralph-wiggum plugin for iterative self-referential developmentBrowse files
Migrates the ralph-wiggum plugin from internal marketplace to public marketplace.
Implements Geoffrey Huntley's "Ralph Wiggum" technique using Claude Code's Stop
hook mechanism for continuous iterative development loops.

Key features:
- Interactive self-referential AI loops in current session
- Stop hook intercepts exit and feeds same prompt back
- Iteration tracking and completion promise detection
- Max iterations safety limits

Changes:
- Remove all tmux dependencies and background execution mode
- Simplify to interactive-only mode using Stop hooks
- Add comprehensive error handling with clear messages
- Fix documentation to accurately describe Stop hook mechanism
- Add input validation for all command-line arguments
- Register plugin in public marketplace

Security fixes:
- Remove eval usage (command injection vulnerability)
- Add numeric validation before arithmetic operations
- Remove silent error suppression

๐Ÿค– Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Daisy S. Hollman authored on Nov 16, 2025 parent 5dd91a9 ยท commit 68f90e05dd91
9 changed files+767 -0compared with 5dd91a9
M.claude-plugin/marketplace.json
Aplugins/ralph-wiggum/.claude-plugin/plugin.json
Aplugins/ralph-wiggum/README.md
Aplugins/ralph-wiggum/commands/cancel-ralph.md
Aplugins/ralph-wiggum/commands/help.md
Aplugins/ralph-wiggum/commands/ralph-loop.md
Aplugins/ralph-wiggum/hooks/hooks.json
Aplugins/ralph-wiggum/hooks/stop-hook.sh
Aplugins/ralph-wiggum/scripts/setup-ralph-loop.sh
@@ -101,6 +101,17 @@
101101 },
102102 "source": "./plugins/frontend-design",
103103 "category": "development"
104+ },
105+ {
106+ "name": "ralph-wiggum",
107+ "description": "Interactive self-referential AI loops for iterative development. Claude works on the same task repeatedly, seeing its previous work, until completion.",
108+ "version": "1.0.0",
109+ "author": {
110+ "name": "Daisy Hollman",
111+ "email": "daisy@anthropic.com"
112+ },
113+ "source": "./plugins/ralph-wiggum",
114+ "category": "development"
104115 }
105116 ]
106117 }
@@ -1,0 +1,9 @@
1+{
2+ "name": "ralph-wiggum",
3+ "version": "1.0.0",
4+ "description": "Implementation of the Ralph Wiggum technique - continuous self-referential AI loops for interactive iterative development. Run Claude in a while-true loop with the same prompt until task completion.",
5+ "author": {
6+ "name": "Daisy Hollman",
7+ "email": "daisy@anthropic.com"
8+ }
9+}
@@ -1,0 +1,179 @@
1+# Ralph Wiggum Plugin
2+
3+Implementation of the Ralph Wiggum technique for iterative, self-referential AI development loops in Claude Code.
4+
5+## What is Ralph?
6+
7+Ralph is a development methodology based on continuous AI agent loops. As Geoffrey Huntley describes it: **"Ralph is a Bash loop"** - a simple `while true` that repeatedly feeds an AI agent a prompt file, allowing it to iteratively improve its work until completion.
8+
9+The technique is named after Ralph Wiggum from The Simpsons, embodying the philosophy of persistent iteration despite setbacks.
10+
11+### Core Concept
12+
13+This plugin implements Ralph using a **Stop hook** that intercepts Claude's exit attempts:
14+
15+```bash
16+# You run ONCE:
17+/ralph-loop "Your task description" --completion-promise "DONE"
18+
19+# Then Claude Code automatically:
20+# 1. Works on the task
21+# 2. Tries to exit
22+# 3. Stop hook blocks exit
23+# 4. Stop hook feeds the SAME prompt back
24+# 5. Repeat until completion
25+```
26+
27+The loop happens **inside your current session** - you don't need external bash loops. The Stop hook in `hooks/stop-hook.sh` creates the self-referential feedback loop by blocking normal session exit.
28+
29+This creates a **self-referential feedback loop** where:
30+- The prompt never changes between iterations
31+- Claude's previous work persists in files
32+- Each iteration sees modified files and git history
33+- Claude autonomously improves by reading its own past work in files
34+
35+## Quick Start
36+
37+```bash
38+/ralph-loop "Build a REST API for todos. Requirements: CRUD operations, input validation, tests. Output <promise>COMPLETE</promise> when done." --completion-promise "COMPLETE" --max-iterations 50
39+```
40+
41+Claude will:
42+- Implement the API iteratively
43+- Run tests and see failures
44+- Fix bugs based on test output
45+- Iterate until all requirements met
46+- Output the completion promise when done
47+
48+## Commands
49+
50+### /ralph-loop
51+
52+Start a Ralph loop in your current session.
53+
54+**Usage:**
55+```bash
56+/ralph-loop "<prompt>" --max-iterations <n> --completion-promise "<text>"
57+```
58+
59+**Options:**
60+- `--max-iterations <n>` - Stop after N iterations (default: unlimited)
61+- `--completion-promise <text>` - Phrase that signals completion
62+
63+### /cancel-ralph
64+
65+Cancel the active Ralph loop.
66+
67+**Usage:**
68+```bash
69+/cancel-ralph
70+```
71+
72+## Prompt Writing Best Practices
73+
74+### 1. Clear Completion Criteria
75+
76+โŒ Bad: "Build a todo API and make it good."
77+
78+โœ… Good:
79+```markdown
80+Build a REST API for todos.
81+
82+When complete:
83+- All CRUD endpoints working
84+- Input validation in place
85+- Tests passing (coverage > 80%)
86+- README with API docs
87+- Output: <promise>COMPLETE</promise>
88+```
89+
90+### 2. Incremental Goals
91+
92+โŒ Bad: "Create a complete e-commerce platform."
93+
94+โœ… Good:
95+```markdown
96+Phase 1: User authentication (JWT, tests)
97+Phase 2: Product catalog (list/search, tests)
98+Phase 3: Shopping cart (add/remove, tests)
99+
100+Output <promise>COMPLETE</promise> when all phases done.
101+```
102+
103+### 3. Self-Correction
104+
105+โŒ Bad: "Write code for feature X."
106+
107+โœ… Good:
108+```markdown
109+Implement feature X following TDD:
110+1. Write failing tests
111+2. Implement feature
112+3. Run tests
113+4. If any fail, debug and fix
114+5. Refactor if needed
115+6. Repeat until all green
116+7. Output: <promise>COMPLETE</promise>
117+```
118+
119+### 4. Escape Hatches
120+
121+Always use `--max-iterations` as a safety net to prevent infinite loops on impossible tasks:
122+
123+```bash
124+# Recommended: Always set a reasonable iteration limit
125+/ralph-loop "Try to implement feature X" --max-iterations 20
126+
127+# In your prompt, include what to do if stuck:
128+# "After 15 iterations, if not complete:
129+# - Document what's blocking progress
130+# - List what was attempted
131+# - Suggest alternative approaches"
132+```
133+
134+**Note**: The `--completion-promise` uses exact string matching, so you cannot use it for multiple completion conditions (like "SUCCESS" vs "BLOCKED"). Always rely on `--max-iterations` as your primary safety mechanism.
135+
136+## Philosophy
137+
138+Ralph embodies several key principles:
139+
140+### 1. Iteration > Perfection
141+Don't aim for perfect on first try. Let the loop refine the work.
142+
143+### 2. Failures Are Data
144+"Deterministically bad" means failures are predictable and informative. Use them to tune prompts.
145+
146+### 3. Operator Skill Matters
147+Success depends on writing good prompts, not just having a good model.
148+
149+### 4. Persistence Wins
150+Keep trying until success. The loop handles retry logic automatically.
151+
152+## When to Use Ralph
153+
154+**Good for:**
155+- Well-defined tasks with clear success criteria
156+- Tasks requiring iteration and refinement (e.g., getting tests to pass)
157+- Greenfield projects where you can walk away
158+- Tasks with automatic verification (tests, linters)
159+
160+**Not good for:**
161+- Tasks requiring human judgment or design decisions
162+- One-shot operations
163+- Tasks with unclear success criteria
164+- Production debugging (use targeted debugging instead)
165+
166+## Real-World Results
167+
168+- Successfully generated 6 repositories overnight in Y Combinator hackathon testing
169+- One $50k contract completed for $297 in API costs
170+- Created entire programming language ("cursed") over 3 months using this approach
171+
172+## Learn More
173+
174+- Original technique: https://ghuntley.com/ralph/
175+- Ralph Orchestrator: https://github.com/mikeyobrien/ralph-orchestrator
176+
177+## For Help
178+
179+Run `/help` in Claude Code for detailed command reference and examples.
@@ -1,0 +1,26 @@
1+---
2+description: "Cancel active Ralph Wiggum loop"
3+allowed-tools: ["Bash"]
4+hide-from-slash-command-tool: "true"
5+---
6+
7+# Cancel Ralph
8+
9+```!
10+if [[ -f .claude/ralph-loop.local.md ]]; then
11+ ITERATION=$(grep '^iteration:' .claude/ralph-loop.local.md | sed 's/iteration: *//')
12+ echo "FOUND_LOOP=true"
13+ echo "ITERATION=$ITERATION"
14+else
15+ echo "FOUND_LOOP=false"
16+fi
17+```
18+
19+Check the output above:
20+
21+1. **If FOUND_LOOP=false**:
22+ - Say "No active Ralph loop found."
23+
24+2. **If FOUND_LOOP=true**:
25+ - Use Bash: `rm .claude/ralph-loop.local.md`
26+ - Report: "Cancelled Ralph loop (was at iteration N)" where N is the ITERATION value from above.
@@ -1,0 +1,126 @@
1+---
2+description: "Explain Ralph Wiggum technique and available commands"
3+---
4+
5+# Ralph Wiggum Plugin Help
6+
7+Please explain the following to the user:
8+
9+## What is the Ralph Wiggum Technique?
10+
11+The Ralph Wiggum technique is an iterative development methodology based on continuous AI loops, pioneered by Geoffrey Huntley.
12+
13+**Core concept:**
14+```bash
15+while :; do
16+ cat PROMPT.md | claude-code --continue
17+done
18+```
19+
20+The same prompt is fed to Claude repeatedly. The "self-referential" aspect comes from Claude seeing its own previous work in the files and git history, not from feeding output back as input.
21+
22+**Each iteration:**
23+1. Claude receives the SAME prompt
24+2. Works on the task, modifying files
25+3. Tries to exit
26+4. Stop hook intercepts and feeds the same prompt again
27+5. Claude sees its previous work in the files
28+6. Iteratively improves until completion
29+
30+The technique is described as "deterministically bad in an undeterministic world" - failures are predictable, enabling systematic improvement through prompt tuning.
31+
32+## Available Commands
33+
34+### /ralph-loop <PROMPT> [OPTIONS]
35+
36+Start a Ralph loop in your current session.
37+
38+**Usage:**
39+```
40+/ralph-loop "Refactor the cache layer" --max-iterations 20
41+/ralph-loop "Add tests" --completion-promise "TESTS COMPLETE"
42+```
43+
44+**Options:**
45+- `--max-iterations <n>` - Max iterations before auto-stop
46+- `--completion-promise <text>` - Promise phrase to signal completion
47+
48+**How it works:**
49+1. Creates `.claude/.ralph-loop.local.md` state file
50+2. You work on the task
51+3. When you try to exit, stop hook intercepts
52+4. Same prompt fed back
53+5. You see your previous work
54+6. Continues until promise detected or max iterations
55+
56+---
57+
58+### /cancel-ralph
59+
60+Cancel an active Ralph loop (removes the loop state file).
61+
62+**Usage:**
63+```
64+/cancel-ralph
65+```
66+
67+**How it works:**
68+- Checks for active loop state file
69+- Removes `.claude/.ralph-loop.local.md`
70+- Reports cancellation with iteration count
71+
72+---
73+
74+## Key Concepts
75+
76+### Completion Promises
77+
78+To signal completion, Claude must output a `<promise>` tag:
79+
80+```
81+<promise>TASK COMPLETE</promise>
82+```
83+
84+The stop hook looks for this specific tag. Without it (or `--max-iterations`), Ralph runs infinitely.
85+
86+### Self-Reference Mechanism
87+
88+The "loop" doesn't mean Claude talks to itself. It means:
89+- Same prompt repeated
90+- Claude's work persists in files
91+- Each iteration sees previous attempts
92+- Builds incrementally toward goal
93+
94+## Example
95+
96+### Interactive Bug Fix
97+
98+```
99+/ralph-loop "Fix the token refresh logic in auth.ts. Output <promise>FIXED</promise> when all tests pass." --completion-promise "FIXED" --max-iterations 10
100+```
101+
102+You'll see Ralph:
103+- Attempt fixes
104+- Run tests
105+- See failures
106+- Iterate on solution
107+- In your current session
108+
109+## When to Use Ralph
110+
111+**Good for:**
112+- Well-defined tasks with clear success criteria
113+- Tasks requiring iteration and refinement
114+- Iterative development with self-correction
115+- Greenfield projects
116+
117+**Not good for:**
118+- Tasks requiring human judgment or design decisions
119+- One-shot operations
120+- Tasks with unclear success criteria
121+- Debugging production issues (use targeted debugging instead)
122+
123+## Learn More
124+
125+- Original technique: https://ghuntley.com/ralph/
126+- Ralph Orchestrator: https://github.com/mikeyobrien/ralph-orchestrator
@@ -1,0 +1,48 @@
1+---
2+description: "Start Ralph Wiggum loop in current session"
3+argument-hint: "PROMPT [--max-iterations N] [--completion-promise TEXT]"
4+allowed-tools: ["Bash(${CLAUDE_PLUGIN_ROOT}/scripts/setup-ralph-loop.sh)"]
5+hide-from-slash-command-tool: "true"
6+---
7+
8+# Ralph Loop Command
9+
10+Execute the setup script to initialize the Ralph loop:
11+
12+```!
13+"${CLAUDE_PLUGIN_ROOT}/scripts/setup-ralph-loop.sh" $ARGUMENTS
14+
15+# Extract and display completion promise if set
16+if [ -f .claude/ralph-loop.local.md ]; then
17+ PROMISE=$(grep '^completion_promise:' .claude/ralph-loop.local.md | sed 's/completion_promise: *//' | sed 's/^"\(.*\)"$/\1/')
18+ if [ -n "$PROMISE" ] && [ "$PROMISE" != "null" ]; then
19+ echo ""
20+ echo "โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•"
21+ echo "CRITICAL - Ralph Loop Completion Promise"
22+ echo "โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•"
23+ echo ""
24+ echo "To complete this loop, output this EXACT text:"
25+ echo " <promise>$PROMISE</promise>"
26+ echo ""
27+ echo "STRICT REQUIREMENTS (DO NOT VIOLATE):"
28+ echo " โœ“ Use <promise> XML tags EXACTLY as shown above"
29+ echo " โœ“ The statement MUST be completely and unequivocally TRUE"
30+ echo " โœ“ Do NOT output false statements to exit the loop"
31+ echo " โœ“ Do NOT lie even if you think you should exit"
32+ echo ""
33+ echo "IMPORTANT - Do not circumvent the loop:"
34+ echo " Even if you believe you're stuck, the task is impossible,"
35+ echo " or you've been running too long - you MUST NOT output a"
36+ echo " false promise statement. The loop is designed to continue"
37+ echo " until the promise is GENUINELY TRUE. Trust the process."
38+ echo ""
39+ echo " If the loop should stop, the promise statement will become"
40+ echo " true naturally. Do not force it by lying."
41+ echo "โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•โ•"
42+ fi
43+fi
44+```
45+
46+Please work on the task. When you try to exit, the Ralph loop will feed the SAME PROMPT back to you for the next iteration. You'll see your previous work in files and git history, allowing you to iterate and improve.
47+
48+CRITICAL RULE: If a completion promise is set, you may ONLY output it when the statement is completely and unequivocally TRUE. Do not output false promises to escape the loop, even if you think you're stuck or should exit for other reasons. The loop is designed to continue until genuine completion.
@@ -1,0 +1,15 @@
1+{
2+ "description": "Ralph Wiggum plugin stop hook for self-referential loops",
3+ "hooks": {
4+ "Stop": [
5+ {
6+ "hooks": [
7+ {
8+ "type": "command",
9+ "command": "${CLAUDE_PLUGIN_ROOT}/hooks/stop-hook.sh"
10+ }
11+ ]
12+ }
13+ ]
14+ }
15+}
@@ -1,0 +1,177 @@
1+#!/bin/bash
2+
3+# Ralph Wiggum Stop Hook
4+# Prevents session exit when a ralph-loop is active
5+# Feeds Claude's output back as input to continue the loop
6+
7+set -euo pipefail
8+
9+# Read hook input from stdin (advanced stop hook API)
10+HOOK_INPUT=$(cat)
11+
12+# Check if ralph-loop is active
13+RALPH_STATE_FILE=".claude/ralph-loop.local.md"
14+
15+if [[ ! -f "$RALPH_STATE_FILE" ]]; then
16+ # No active loop - allow exit
17+ exit 0
18+fi
19+
20+# Parse markdown frontmatter (YAML between ---) and extract values
21+FRONTMATTER=$(sed -n '/^---$/,/^---$/{ /^---$/d; p; }' "$RALPH_STATE_FILE")
22+ITERATION=$(echo "$FRONTMATTER" | grep '^iteration:' | sed 's/iteration: *//')
23+MAX_ITERATIONS=$(echo "$FRONTMATTER" | grep '^max_iterations:' | sed 's/max_iterations: *//')
24+# Extract completion_promise and strip surrounding quotes if present
25+COMPLETION_PROMISE=$(echo "$FRONTMATTER" | grep '^completion_promise:' | sed 's/completion_promise: *//' | sed 's/^"\(.*\)"$/\1/')
26+
27+# Validate numeric fields before arithmetic operations
28+if [[ ! "$ITERATION" =~ ^[0-9]+$ ]]; then
29+ echo "โš ๏ธ Ralph loop: State file corrupted" >&2
30+ echo " File: $RALPH_STATE_FILE" >&2
31+ echo " Problem: 'iteration' field is not a valid number (got: '$ITERATION')" >&2
32+ echo "" >&2
33+ echo " This usually means the state file was manually edited or corrupted." >&2
34+ echo " Ralph loop is stopping. Run /ralph-loop again to start fresh." >&2
35+ rm "$RALPH_STATE_FILE"
36+ exit 0
37+fi
38+
39+if [[ ! "$MAX_ITERATIONS" =~ ^[0-9]+$ ]]; then
40+ echo "โš ๏ธ Ralph loop: State file corrupted" >&2
41+ echo " File: $RALPH_STATE_FILE" >&2
42+ echo " Problem: 'max_iterations' field is not a valid number (got: '$MAX_ITERATIONS')" >&2
43+ echo "" >&2
44+ echo " This usually means the state file was manually edited or corrupted." >&2
45+ echo " Ralph loop is stopping. Run /ralph-loop again to start fresh." >&2
46+ rm "$RALPH_STATE_FILE"
47+ exit 0
48+fi
49+
50+# Check if max iterations reached
51+if [[ $MAX_ITERATIONS -gt 0 ]] && [[ $ITERATION -ge $MAX_ITERATIONS ]]; then
52+ echo "๐Ÿ›‘ Ralph loop: Max iterations ($MAX_ITERATIONS) reached."
53+ rm "$RALPH_STATE_FILE"
54+ exit 0
55+fi
56+
57+# Get transcript path from hook input
58+TRANSCRIPT_PATH=$(echo "$HOOK_INPUT" | jq -r '.transcript_path')
59+
60+if [[ ! -f "$TRANSCRIPT_PATH" ]]; then
61+ echo "โš ๏ธ Ralph loop: Transcript file not found" >&2
62+ echo " Expected: $TRANSCRIPT_PATH" >&2
63+ echo " This is unusual and may indicate a Claude Code internal issue." >&2
64+ echo " Ralph loop is stopping." >&2
65+ rm "$RALPH_STATE_FILE"
66+ exit 0
67+fi
68+
69+# Read last assistant message from transcript (JSONL format - one JSON per line)
70+# First check if there are any assistant messages
71+if ! grep -q '"role":"assistant"' "$TRANSCRIPT_PATH"; then
72+ echo "โš ๏ธ Ralph loop: No assistant messages found in transcript" >&2
73+ echo " Transcript: $TRANSCRIPT_PATH" >&2
74+ echo " This is unusual and may indicate a transcript format issue" >&2
75+ echo " Ralph loop is stopping." >&2
76+ rm "$RALPH_STATE_FILE"
77+ exit 0
78+fi
79+
80+# Extract last assistant message with explicit error handling
81+LAST_LINE=$(grep '"role":"assistant"' "$TRANSCRIPT_PATH" | tail -1)
82+if [[ -z "$LAST_LINE" ]]; then
83+ echo "โš ๏ธ Ralph loop: Failed to extract last assistant message" >&2
84+ echo " Ralph loop is stopping." >&2
85+ rm "$RALPH_STATE_FILE"
86+ exit 0
87+fi
88+
89+# Parse JSON with error handling
90+LAST_OUTPUT=$(echo "$LAST_LINE" | jq -r '
91+ .message.content |
92+ map(select(.type == "text")) |
93+ map(.text) |
94+ join("\n")
95+' 2>&1)
96+
97+# Check if jq succeeded
98+if [[ $? -ne 0 ]]; then
99+ echo "โš ๏ธ Ralph loop: Failed to parse assistant message JSON" >&2
100+ echo " Error: $LAST_OUTPUT" >&2
101+ echo " This may indicate a transcript format issue" >&2
102+ echo " Ralph loop is stopping." >&2
103+ rm "$RALPH_STATE_FILE"
104+ exit 0
105+fi
106+
107+if [[ -z "$LAST_OUTPUT" ]]; then
108+ echo "โš ๏ธ Ralph loop: Assistant message contained no text content" >&2
109+ echo " Ralph loop is stopping." >&2
110+ rm "$RALPH_STATE_FILE"
111+ exit 0
112+fi
113+
114+# Check for completion promise (only if set)
115+if [[ "$COMPLETION_PROMISE" != "null" ]] && [[ -n "$COMPLETION_PROMISE" ]]; then
116+ # Extract text from <promise> tags using Perl for multiline support
117+ # -0777 slurps entire input, s flag makes . match newlines
118+ # .*? is non-greedy (takes FIRST tag), whitespace normalized
119+ PROMISE_TEXT=$(echo "$LAST_OUTPUT" | perl -0777 -pe 's/.*?<promise>(.*?)<\/promise>.*/$1/s; s/^\s+|\s+$//g; s/\s+/ /g' 2>/dev/null || echo "")
120+
121+ # Use = for literal string comparison (not pattern matching)
122+ # == in [[ ]] does glob pattern matching which breaks with *, ?, [ characters
123+ if [[ -n "$PROMISE_TEXT" ]] && [[ "$PROMISE_TEXT" = "$COMPLETION_PROMISE" ]]; then
124+ echo "โœ… Ralph loop: Detected <promise>$COMPLETION_PROMISE</promise>"
125+ rm "$RALPH_STATE_FILE"
126+ exit 0
127+ fi
128+fi
129+
130+# Not complete - continue loop with SAME PROMPT
131+NEXT_ITERATION=$((ITERATION + 1))
132+
133+# Extract prompt (everything after the closing ---)
134+# Skip first --- line, skip until second --- line, then print everything after
135+# Use i>=2 instead of i==2 to handle --- in prompt content
136+PROMPT_TEXT=$(awk '/^---$/{i++; next} i>=2' "$RALPH_STATE_FILE")
137+
138+if [[ -z "$PROMPT_TEXT" ]]; then
139+ echo "โš ๏ธ Ralph loop: State file corrupted or incomplete" >&2
140+ echo " File: $RALPH_STATE_FILE" >&2
141+ echo " Problem: No prompt text found" >&2
142+ echo "" >&2
143+ echo " This usually means:" >&2
144+ echo " โ€ข State file was manually edited" >&2
145+ echo " โ€ข File was corrupted during writing" >&2
146+ echo "" >&2
147+ echo " Ralph loop is stopping. Run /ralph-loop again to start fresh." >&2
148+ rm "$RALPH_STATE_FILE"
149+ exit 0
150+fi
151+
152+# Update iteration in frontmatter (portable across macOS and Linux)
153+# Create temp file, then atomically replace
154+TEMP_FILE="${RALPH_STATE_FILE}.tmp.$$"
155+sed "s/^iteration: .*/iteration: $NEXT_ITERATION/" "$RALPH_STATE_FILE" > "$TEMP_FILE"
156+mv "$TEMP_FILE" "$RALPH_STATE_FILE"
157+
158+# Build system message with iteration count and completion promise info
159+if [[ "$COMPLETION_PROMISE" != "null" ]] && [[ -n "$COMPLETION_PROMISE" ]]; then
160+ SYSTEM_MSG="๐Ÿ”„ Ralph iteration $NEXT_ITERATION | To stop: output <promise>$COMPLETION_PROMISE</promise> (ONLY when statement is TRUE - do not lie to exit!)"
161+else
162+ SYSTEM_MSG="๐Ÿ”„ Ralph iteration $NEXT_ITERATION | No completion promise set - loop runs infinitely"
163+fi
164+
165+# Output JSON to block the stop and feed prompt back
166+# The "reason" field contains the prompt that will be sent back to Claude
167+jq -n \
168+ --arg prompt "$PROMPT_TEXT" \
169+ --arg msg "$SYSTEM_MSG" \
170+ '{
171+ "decision": "block",
172+ "reason": $prompt,
173+ "systemMessage": $msg
174+ }'
175+
176+# Exit 0 for successful hook execution
177+exit 0
@@ -1,0 +1,176 @@
1+#!/bin/bash
2+
3+# Ralph Loop Setup Script
4+# Creates state file for in-session Ralph loop
5+
6+set -euo pipefail
7+
8+# Parse arguments
9+PROMPT_PARTS=()
10+MAX_ITERATIONS=0
11+COMPLETION_PROMISE="null"
12+
13+# Parse options and positional arguments
14+while [[ $# -gt 0 ]]; do
15+ case $1 in
16+ -h|--help)
17+ cat << 'HELP_EOF'
18+Ralph Loop - Interactive self-referential development loop
19+
20+USAGE:
21+ /ralph-loop [PROMPT...] [OPTIONS]
22+
23+ARGUMENTS:
24+ PROMPT... Initial prompt to start the loop (can be multiple words without quotes)
25+
26+OPTIONS:
27+ --max-iterations <n> Maximum iterations before auto-stop (default: unlimited)
28+ --completion-promise '<text>' Promise phrase (USE QUOTES for multi-word)
29+ -h, --help Show this help message
30+
31+DESCRIPTION:
32+ Starts a Ralph Wiggum loop in your CURRENT session. The stop hook prevents
33+ exit and feeds your output back as input until completion or iteration limit.
34+
35+ To signal completion, you must output: <promise>YOUR_PHRASE</promise>
36+
37+ Use this for:
38+ - Interactive iteration where you want to see progress
39+ - Tasks requiring self-correction and refinement
40+ - Learning how Ralph works
41+
42+EXAMPLES:
43+ /ralph-loop Build a todo API --completion-promise 'DONE' --max-iterations 20
44+ /ralph-loop --max-iterations 10 Fix the auth bug
45+ /ralph-loop Refactor cache layer (runs forever)
46+ /ralph-loop --completion-promise 'TASK COMPLETE' Create a REST API
47+
48+STOPPING:
49+ Only by reaching --max-iterations or detecting --completion-promise
50+ No manual stop - Ralph runs infinitely by default!
51+
52+MONITORING:
53+ # View current iteration:
54+ grep '^iteration:' .claude/ralph-loop.local.md
55+
56+ # View full state:
57+ head -10 .claude/ralph-loop.local.md
58+HELP_EOF
59+ exit 0
60+ ;;
61+ --max-iterations)
62+ if [[ -z "${2:-}" ]]; then
63+ echo "โŒ Error: --max-iterations requires a number argument" >&2
64+ echo "" >&2
65+ echo " Valid examples:" >&2
66+ echo " --max-iterations 10" >&2
67+ echo " --max-iterations 50" >&2
68+ echo " --max-iterations 0 (unlimited)" >&2
69+ echo "" >&2
70+ echo " You provided: --max-iterations (with no number)" >&2
71+ exit 1
72+ fi
73+ if ! [[ "$2" =~ ^[0-9]+$ ]]; then
74+ echo "โŒ Error: --max-iterations must be a positive integer or 0, got: $2" >&2
75+ echo "" >&2
76+ echo " Valid examples:" >&2
77+ echo " --max-iterations 10" >&2
78+ echo " --max-iterations 50" >&2
79+ echo " --max-iterations 0 (unlimited)" >&2
80+ echo "" >&2
81+ echo " Invalid: decimals (10.5), negative numbers (-5), text" >&2
82+ exit 1
83+ fi
84+ MAX_ITERATIONS="$2"
85+ shift 2
86+ ;;
87+ --completion-promise)
88+ if [[ -z "${2:-}" ]]; then
89+ echo "โŒ Error: --completion-promise requires a text argument" >&2
90+ echo "" >&2
91+ echo " Valid examples:" >&2
92+ echo " --completion-promise 'DONE'" >&2
93+ echo " --completion-promise 'TASK COMPLETE'" >&2
94+ echo " --completion-promise 'All tests passing'" >&2
95+ echo "" >&2
96+ echo " You provided: --completion-promise (with no text)" >&2
97+ echo "" >&2
98+ echo " Note: Multi-word promises must be quoted!" >&2
99+ exit 1
100+ fi
101+ COMPLETION_PROMISE="$2"
102+ shift 2
103+ ;;
104+ *)
105+ # Non-option argument - collect all as prompt parts
106+ PROMPT_PARTS+=("$1")
107+ shift
108+ ;;
109+ esac
110+done
111+
112+# Join all prompt parts with spaces
113+PROMPT="${PROMPT_PARTS[*]}"
114+
115+# Validate prompt is non-empty
116+if [[ -z "$PROMPT" ]]; then
117+ echo "โŒ Error: No prompt provided" >&2
118+ echo "" >&2
119+ echo " Ralph needs a task description to work on." >&2
120+ echo "" >&2
121+ echo " Examples:" >&2
122+ echo " /ralph-loop Build a REST API for todos" >&2
123+ echo " /ralph-loop Fix the auth bug --max-iterations 20" >&2
124+ echo " /ralph-loop --completion-promise 'DONE' Refactor code" >&2
125+ echo "" >&2
126+ echo " For all options: /ralph-loop --help" >&2
127+ exit 1
128+fi
129+
130+# Create state file for stop hook (markdown with YAML frontmatter)
131+mkdir -p .claude
132+
133+# Quote completion promise for YAML if it contains special chars or is not null
134+if [[ -n "$COMPLETION_PROMISE" ]] && [[ "$COMPLETION_PROMISE" != "null" ]]; then
135+ COMPLETION_PROMISE_YAML="\"$COMPLETION_PROMISE\""
136+else
137+ COMPLETION_PROMISE_YAML="null"
138+fi
139+
140+cat > .claude/ralph-loop.local.md <<EOF
141+---
142+active: true
143+iteration: 1
144+max_iterations: $MAX_ITERATIONS
145+completion_promise: $COMPLETION_PROMISE_YAML
146+started_at: "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
147+---
148+
149+$PROMPT
150+EOF
151+
152+# Output setup message
153+cat <<EOF
154+๐Ÿ”„ Ralph loop activated in this session!
155+
156+Iteration: 1
157+Max iterations: $(if [[ $MAX_ITERATIONS -gt 0 ]]; then echo $MAX_ITERATIONS; else echo "unlimited"; fi)
158+Completion promise: $(if [[ "$COMPLETION_PROMISE" != "null" ]]; then echo "${COMPLETION_PROMISE//\"/} (ONLY output when TRUE - do not lie!)"; else echo "none (runs forever)"; fi)
159+
160+The stop hook is now active. When you try to exit, the SAME PROMPT will be
161+fed back to you. You'll see your previous work in files, creating a
162+self-referential loop where you iteratively improve on the same task.
163+
164+To monitor: head -10 .claude/ralph-loop.local.md
165+
166+โš ๏ธ WARNING: This loop cannot be stopped manually! It will run infinitely
167+ unless you set --max-iterations or --completion-promise.
168+
169+๐Ÿ”„
170+EOF
171+
172+# Output the initial prompt if provided
173+if [[ -n "$PROMPT" ]]; then
174+ echo ""
175+ echo "$PROMPT"
176+fi