How this skill is triggered — by the user, by Claude, or both
Slash command
/ralph:ralph-startThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Start Ralph's autonomous iteration loop.
Start Ralph's autonomous iteration loop.
This skill starts Ralph's autonomous loop that repeatedly spawns the ralph-worker agent to implement tasks from fix_plan.md. The loop continues until all tasks are complete, a blocker is encountered, or the user stops it.
/ralph:init has been run)docs/ai/ralph/PROMPT.md must existdocs/ai/ralph/fix_plan.md must existdocs/ai/ralph/status.json must existWhen this skill is invoked:
Check that all required files exist before starting:
# Check for required files
if [[ ! -f docs/ai/ralph/PROMPT.md ]]; then
echo "Error: PROMPT.md not found. Run /ralph:init first."
exit 1
fi
if [[ ! -f docs/ai/ralph/fix_plan.md ]]; then
echo "Error: fix_plan.md not found. Run /ralph:init first."
exit 1
fi
if [[ ! -f docs/ai/ralph/status.json ]]; then
echo "Error: status.json not found. Run /ralph:init first."
exit 1
fi
Remove any existing stop signal from a previous run:
# Remove stop signal if it exists
rm -f docs/ai/ralph/.ralph_stop
Mark Ralph as running, record the start time, and save the current HEAD as the base commit for squashing on completion:
# Update status.json with started_at timestamp, running status, and base commit
jq --arg bc "$(git rev-parse HEAD)" \
'.status = "running" | .started_at = now | .last_updated = now | .base_commit = $bc' \
docs/ai/ralph/status.json > /tmp/status.json.tmp
mv /tmp/status.json.tmp docs/ai/ralph/status.json
echo "Ralph started. Beginning autonomous iteration loop..."
echo "Base commit recorded: $(git rev-parse --short HEAD)"
The base_commit is the anchor point used to squash all of Ralph's commits into one when all tasks complete. It is only set once per /ralph:start invocation — if the loop is stopped and restarted, a new base commit is recorded.
The loop repeatedly spawns ralph-worker and checks for completion:
# Main iteration loop
while true; do
# Check for stop signal before each iteration
if [[ -f docs/ai/ralph/.ralph_stop ]]; then
echo ""
echo "Stop signal detected. Exiting loop gracefully."
rm -f docs/ai/ralph/.ralph_stop
# Update status to stopped
jq '.status = "stopped" | .last_updated = now | .stopped_at = now' \
docs/ai/ralph/status.json > /tmp/status.json.tmp
mv /tmp/status.json.tmp docs/ai/ralph/status.json
echo "Ralph stopped after iteration $(jq -r '.iteration_count' docs/ai/ralph/status.json)."
break
fi
# Get current iteration count
ITERATION=$(jq -r '.iteration_count' docs/ai/ralph/status.json)
NEXT_ITERATION=$((ITERATION + 1))
echo ""
echo "========================================="
echo "Starting iteration $NEXT_ITERATION"
echo "========================================="
# Spawn ralph-worker using Task tool
# Use subagent_type="ralph-worker" to invoke the agent
# The worker will read context, pick a task, implement it, and return a summary
# After spawning Task(ralph-worker), the result will be displayed in chat
# The worker handles incrementing iteration_count in status.json
# Check for user confirmation every 10 iterations
if (( NEXT_ITERATION % 10 == 0 )); then
# Use AskUserQuestion to prompt for continuation
# Question: "Completed 10 iterations. Continue with more iterations? (yes/no)"
# If response is not "yes", break the loop
fi
# After worker returns, check fix_plan.md for completion signals
if grep -q "^RALPH_COMPLETE" docs/ai/ralph/fix_plan.md 2>/dev/null; then
echo ""
echo "RALPH_COMPLETE signal detected. All tasks complete!"
FINAL_ITERATION=$(jq -r '.iteration_count' docs/ai/ralph/status.json)
# --- Squash all Ralph commits into one ---
BASE_COMMIT=$(jq -r '.base_commit // empty' docs/ai/ralph/status.json)
if [[ -z "$BASE_COMMIT" ]]; then
echo ""
echo "WARNING: No base_commit found in status.json. Cannot squash automatically."
# Use AskUserQuestion to ask:
# "No base commit was recorded. Provide a commit hash to squash from, or choose 'Skip squash'."
# If user provides a hash, use it as BASE_COMMIT.
# If user chooses "Skip squash", skip the squash step.
else
echo "Squashing commits from base $BASE_COMMIT to HEAD..."
# Derive a commit message from the first heading in fix_plan.md, or fall back to generic
PLAN_TITLE=$(head -5 docs/ai/ralph/fix_plan.md | grep "^#" | head -1 | sed 's/^#\+ *//')
if [[ -z "$PLAN_TITLE" ]]; then
PLAN_TITLE="Ralph autonomous implementation"
fi
git reset --soft "$BASE_COMMIT"
git add .
git commit -m "feat: ${PLAN_TITLE}
Squashed from ${FINAL_ITERATION} Ralph iterations.
Co-Authored-By: Ralph Wiggum <ralph@claude-code>"
echo "All commits squashed into one: $(git rev-parse --short HEAD)"
fi
# Update status to complete
jq '.status = "complete" | .last_updated = now | .completed_at = now' \
docs/ai/ralph/status.json > /tmp/status.json.tmp
mv /tmp/status.json.tmp docs/ai/ralph/status.json
# Report summary
echo ""
echo "Ralph completed successfully!"
echo "- Total iterations: $FINAL_ITERATION"
echo "- Status: complete"
echo "- All tasks in fix_plan.md have been completed."
echo "- All commits squashed into a single commit."
break
fi
if grep -q "^RALPH_BLOCKED" docs/ai/ralph/fix_plan.md 2>/dev/null; then
echo ""
echo "RALPH_BLOCKED signal detected. Cannot continue."
# Extract blocker reason
BLOCKER=$(grep "^RALPH_BLOCKED" docs/ai/ralph/fix_plan.md | head -1)
# Update status to blocked
jq '.status = "blocked" | .last_updated = now | .blocked_at = now' \
docs/ai/ralph/status.json > /tmp/status.json.tmp
mv /tmp/status.json.tmp docs/ai/ralph/status.json
# Report summary
FINAL_ITERATION=$(jq -r '.iteration_count' docs/ai/ralph/status.json)
echo ""
echo "Ralph blocked after $FINAL_ITERATION iterations."
echo "- Status: blocked"
echo "- Reason: $BLOCKER"
echo ""
echo "Review fix_plan.md to resolve the blocker, then run /ralph:start again."
break
fi
done
Loop structure:
.ralph_stop before each iterationralph-worker via Task tool with subagent_type="ralph-worker"fix_plan.md for RALPH_COMPLETE or RALPH_BLOCKED signalsIteration counting:
ralph-worker agent is responsible for incrementing iteration_count in status.jsonralph-start skill reads the current count before spawning each workerUser confirmation:
AskUserQuestion to ask: "Completed 10 iterations. Continue? (yes/no)"Completion signals:
RALPH_COMPLETE at top of fix_plan.md = all tasks done successfully → triggers commit squashRALPH_BLOCKED: [reason] = cannot proceed, need user interventionfix_plan.md Tasks section = treated same as RALPH_COMPLETECommit squashing:
RALPH_COMPLETE, all commits since base_commit (recorded in status.json at start) are squashed into a single commit via git reset --soft <base_commit> && git add . && git commitbase_commit is missing from status.json (e.g., older runs), the user is prompted via AskUserQuestion to provide a hash or skip the squashfix_plan.mdThe /ralph:stop skill creates a .ralph_stop signal file. This loop checks for that file before each iteration:
User: /ralph:start
Ralph started. Beginning autonomous iteration loop...
Base commit recorded: a1b2c3d
=========================================
Starting iteration 1
=========================================
[ralph-worker spawns and returns summary]
Iteration 1: Implemented task "Add user authentication"
- Files changed: auth.ts, login.tsx
- Tests: pass
- Next: Add password reset flow
=========================================
Starting iteration 2
=========================================
[ralph-worker spawns and returns summary]
Iteration 2: Implemented task "Add password reset flow"
- Files changed: reset-password.tsx, email-service.ts
- Tests: pass
- Next: RALPH_COMPLETE
RALPH_COMPLETE signal detected. All tasks complete!
Squashing commits from base a1b2c3d to HEAD...
All commits squashed into one: f4e5d6c
Ralph completed successfully!
- Total iterations: 2
- Status: complete
- All tasks in fix_plan.md have been completed.
- All commits squashed into a single commit.
jq with temp files for atomic JSON updates to avoid corruption/ralph:start can resume from current state (clears stop signal and continues)npx claudepluginhub stavarengo/ralph-wiggum-loop --plugin ralphGuides completion of development work by verifying tests, detecting environment, and presenting structured options for merge, PR, or cleanup.
Enforces test-driven development: write failing test first, then minimal code to pass. Use when implementing features or bugfixes.
Guides creation and editing of skills using test-driven development with pressure scenarios and subagents to verify agent compliance.