mirror of
https://github.com/anthropics/claude-code.git
synced 2025-11-28 00:30:27 +08:00
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>
176 lines
5.3 KiB
Bash
Executable file
176 lines
5.3 KiB
Bash
Executable file
#!/bin/bash
|
|
|
|
# Ralph Loop Setup Script
|
|
# Creates state file for in-session Ralph loop
|
|
|
|
set -euo pipefail
|
|
|
|
# Parse arguments
|
|
PROMPT_PARTS=()
|
|
MAX_ITERATIONS=0
|
|
COMPLETION_PROMISE="null"
|
|
|
|
# Parse options and positional arguments
|
|
while [[ $# -gt 0 ]]; do
|
|
case $1 in
|
|
-h|--help)
|
|
cat << 'HELP_EOF'
|
|
Ralph Loop - Interactive self-referential development loop
|
|
|
|
USAGE:
|
|
/ralph-loop [PROMPT...] [OPTIONS]
|
|
|
|
ARGUMENTS:
|
|
PROMPT... Initial prompt to start the loop (can be multiple words without quotes)
|
|
|
|
OPTIONS:
|
|
--max-iterations <n> Maximum iterations before auto-stop (default: unlimited)
|
|
--completion-promise '<text>' Promise phrase (USE QUOTES for multi-word)
|
|
-h, --help Show this help message
|
|
|
|
DESCRIPTION:
|
|
Starts a Ralph Wiggum loop in your CURRENT session. The stop hook prevents
|
|
exit and feeds your output back as input until completion or iteration limit.
|
|
|
|
To signal completion, you must output: <promise>YOUR_PHRASE</promise>
|
|
|
|
Use this for:
|
|
- Interactive iteration where you want to see progress
|
|
- Tasks requiring self-correction and refinement
|
|
- Learning how Ralph works
|
|
|
|
EXAMPLES:
|
|
/ralph-loop Build a todo API --completion-promise 'DONE' --max-iterations 20
|
|
/ralph-loop --max-iterations 10 Fix the auth bug
|
|
/ralph-loop Refactor cache layer (runs forever)
|
|
/ralph-loop --completion-promise 'TASK COMPLETE' Create a REST API
|
|
|
|
STOPPING:
|
|
Only by reaching --max-iterations or detecting --completion-promise
|
|
No manual stop - Ralph runs infinitely by default!
|
|
|
|
MONITORING:
|
|
# View current iteration:
|
|
grep '^iteration:' .claude/ralph-loop.local.md
|
|
|
|
# View full state:
|
|
head -10 .claude/ralph-loop.local.md
|
|
HELP_EOF
|
|
exit 0
|
|
;;
|
|
--max-iterations)
|
|
if [[ -z "${2:-}" ]]; then
|
|
echo "❌ Error: --max-iterations requires a number argument" >&2
|
|
echo "" >&2
|
|
echo " Valid examples:" >&2
|
|
echo " --max-iterations 10" >&2
|
|
echo " --max-iterations 50" >&2
|
|
echo " --max-iterations 0 (unlimited)" >&2
|
|
echo "" >&2
|
|
echo " You provided: --max-iterations (with no number)" >&2
|
|
exit 1
|
|
fi
|
|
if ! [[ "$2" =~ ^[0-9]+$ ]]; then
|
|
echo "❌ Error: --max-iterations must be a positive integer or 0, got: $2" >&2
|
|
echo "" >&2
|
|
echo " Valid examples:" >&2
|
|
echo " --max-iterations 10" >&2
|
|
echo " --max-iterations 50" >&2
|
|
echo " --max-iterations 0 (unlimited)" >&2
|
|
echo "" >&2
|
|
echo " Invalid: decimals (10.5), negative numbers (-5), text" >&2
|
|
exit 1
|
|
fi
|
|
MAX_ITERATIONS="$2"
|
|
shift 2
|
|
;;
|
|
--completion-promise)
|
|
if [[ -z "${2:-}" ]]; then
|
|
echo "❌ Error: --completion-promise requires a text argument" >&2
|
|
echo "" >&2
|
|
echo " Valid examples:" >&2
|
|
echo " --completion-promise 'DONE'" >&2
|
|
echo " --completion-promise 'TASK COMPLETE'" >&2
|
|
echo " --completion-promise 'All tests passing'" >&2
|
|
echo "" >&2
|
|
echo " You provided: --completion-promise (with no text)" >&2
|
|
echo "" >&2
|
|
echo " Note: Multi-word promises must be quoted!" >&2
|
|
exit 1
|
|
fi
|
|
COMPLETION_PROMISE="$2"
|
|
shift 2
|
|
;;
|
|
*)
|
|
# Non-option argument - collect all as prompt parts
|
|
PROMPT_PARTS+=("$1")
|
|
shift
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Join all prompt parts with spaces
|
|
PROMPT="${PROMPT_PARTS[*]}"
|
|
|
|
# Validate prompt is non-empty
|
|
if [[ -z "$PROMPT" ]]; then
|
|
echo "❌ Error: No prompt provided" >&2
|
|
echo "" >&2
|
|
echo " Ralph needs a task description to work on." >&2
|
|
echo "" >&2
|
|
echo " Examples:" >&2
|
|
echo " /ralph-loop Build a REST API for todos" >&2
|
|
echo " /ralph-loop Fix the auth bug --max-iterations 20" >&2
|
|
echo " /ralph-loop --completion-promise 'DONE' Refactor code" >&2
|
|
echo "" >&2
|
|
echo " For all options: /ralph-loop --help" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# Create state file for stop hook (markdown with YAML frontmatter)
|
|
mkdir -p .claude
|
|
|
|
# Quote completion promise for YAML if it contains special chars or is not null
|
|
if [[ -n "$COMPLETION_PROMISE" ]] && [[ "$COMPLETION_PROMISE" != "null" ]]; then
|
|
COMPLETION_PROMISE_YAML="\"$COMPLETION_PROMISE\""
|
|
else
|
|
COMPLETION_PROMISE_YAML="null"
|
|
fi
|
|
|
|
cat > .claude/ralph-loop.local.md <<EOF
|
|
---
|
|
active: true
|
|
iteration: 1
|
|
max_iterations: $MAX_ITERATIONS
|
|
completion_promise: $COMPLETION_PROMISE_YAML
|
|
started_at: "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
---
|
|
|
|
$PROMPT
|
|
EOF
|
|
|
|
# Output setup message
|
|
cat <<EOF
|
|
🔄 Ralph loop activated in this session!
|
|
|
|
Iteration: 1
|
|
Max iterations: $(if [[ $MAX_ITERATIONS -gt 0 ]]; then echo $MAX_ITERATIONS; else echo "unlimited"; fi)
|
|
Completion promise: $(if [[ "$COMPLETION_PROMISE" != "null" ]]; then echo "${COMPLETION_PROMISE//\"/} (ONLY output when TRUE - do not lie!)"; else echo "none (runs forever)"; fi)
|
|
|
|
The stop hook is now active. When you try to exit, the SAME PROMPT will be
|
|
fed back to you. You'll see your previous work in files, creating a
|
|
self-referential loop where you iteratively improve on the same task.
|
|
|
|
To monitor: head -10 .claude/ralph-loop.local.md
|
|
|
|
⚠️ WARNING: This loop cannot be stopped manually! It will run infinitely
|
|
unless you set --max-iterations or --completion-promise.
|
|
|
|
🔄
|
|
EOF
|
|
|
|
# Output the initial prompt if provided
|
|
if [[ -n "$PROMPT" ]]; then
|
|
echo ""
|
|
echo "$PROMPT"
|
|
fi
|