Ralph Start
npx machina-cli add skill stavarengo/ralph-wiggum-loop/ralph-start --openclawralph-start
Start Ralph's autonomous iteration loop.
What This Skill Does
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.
Prerequisites
- Ralph must be initialized (
/ralph:inithas been run) docs/ai/ralph/PROMPT.mdmust existdocs/ai/ralph/fix_plan.mdmust existdocs/ai/ralph/status.jsonmust exist
Implementation
When this skill is invoked:
1. Validate Prerequisites
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
2. Clear Stop Signal (if present)
Remove any existing stop signal from a previous run:
# Remove stop signal if it exists
rm -f docs/ai/ralph/.ralph_stop
3. Update status.json to 'running' and record base commit
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.
4. Enter Main Loop
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
5. Orchestration Details
Loop structure:
- Check for
.ralph_stopbefore each iteration - Spawn
ralph-workervia Task tool withsubagent_type="ralph-worker" - Display worker's iteration summary in chat
- Check
fix_plan.mdforRALPH_COMPLETEorRALPH_BLOCKEDsignals - Prompt user every 10 iterations for confirmation
- Continue until completion signal, blocker, stop signal, or user declines
Iteration counting:
- The
ralph-workeragent is responsible for incrementingiteration_countinstatus.json - The
ralph-startskill reads the current count before spawning each worker - This ensures accurate tracking even if the loop is stopped and restarted
User confirmation:
- Every 10 iterations, use
AskUserQuestionto ask: "Completed 10 iterations. Continue? (yes/no)" - Only continue if user responds "yes"
- This prevents runaway loops and gives user control points
Completion signals:
RALPH_COMPLETEat top offix_plan.md= all tasks done successfully → triggers commit squashRALPH_BLOCKED: [reason]= cannot proceed, need user intervention- Empty
fix_plan.mdTasks section = treated same asRALPH_COMPLETE
Commit squashing:
- On
RALPH_COMPLETE, all commits sincebase_commit(recorded in status.json at start) are squashed into a single commit viagit reset --soft <base_commit> && git add . && git commit - If
base_commitis missing from status.json (e.g., older runs), the user is prompted viaAskUserQuestionto provide a hash or skip the squash - The squash commit message is derived from the first heading in
fix_plan.md
Coordination with /ralph:stop
The /ralph:stop skill creates a .ralph_stop signal file. This loop checks for that file before each iteration:
- If found, the loop exits gracefully
- The current iteration completes normally before checking
- The signal file is removed after detection
- Status is updated to 'stopped'
Example Session Flow
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.
Important Notes
- Fresh context: Each ralph-worker starts with zero memory and reads all context from files
- Atomic updates: Use
jqwith temp files for atomic JSON updates to avoid corruption - Graceful exit: Always allow current iteration to finish before stopping
- Progress display: Each iteration's summary is displayed in chat for user visibility
- Resumable: If stopped,
/ralph:startcan resume from current state (clears stop signal and continues)
Source
git clone https://github.com/stavarengo/ralph-wiggum-loop/blob/main/skills/ralph-start/SKILL.mdView on GitHub Overview
This skill launches Ralph's autonomous iteration loop, repeatedly spawning 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.
How This Skill Works
When invoked, the skill validates prerequisites (PROMPT.md, fix_plan.md, and status.json), clears any existing stop signal, and updates status.json to running while recording the base commit. It then enters a main loop that spawns a ralph-worker via the Task tool to implement tasks from fix_plan.md, checks for a stop signal, and updates iteration counts. Upon completion signaled by fix_plan.md (RALPH_COMPLETE), it squashes all Ralph commits into one using the recorded base_commit.
When to Use It
- When you want to start Ralph's autonomous iteration loop to implement tasks from fix_plan.md.
- When you need to ensure prerequisites PROMPT.md, fix_plan.md, and status.json exist before running.
- When you want to monitor progress through iterations and detect blockers or a user stop signal.
- When you want to squash all Ralph commits into a single base commit after completion.
- When you need to gracefully stop the loop with a stop signal and proper cleanup.
Quick Start
- Step 1: Ensure PROMPT.md, fix_plan.md, and status.json exist and Ralph is initialized.
- Step 2: Run the /ralph:start command to begin the autonomous loop.
- Step 3: Monitor docs/ai/ralph/status.json for iteration updates and create docs/ai/ralph/.ralph_stop to stop gracefully.
Best Practices
- Always verify prerequisites (PROMPT.md, fix_plan.md, status.json) before starting the loop.
- Use the stop signal at docs/ai/ralph/.ralph_stop to gracefully exit the loop.
- Regularly check docs/ai/ralph/status.json for iteration_count and status updates.
- Ensure fix_plan.md contains a clear RALPH_COMPLETE signal to indicate completion.
- Capture the base commit at start to enable proper squashing of Ralph's commits after completion.
Example Use Cases
- Kick off an autonomous task sequence where Ralph reads fix_plan.md and iteratively implements steps via ralph-worker until all tasks are done.
- Use in a development project to apply batch changes across a repository, with progress tracked in status.json.
- Run a multi-step experiment where each iteration refines the plan based on ralph-worker output and status updates.
- Gracefully stop the loop after a milestone by creating the stop signal, then review the final status.
- After completion, the commit history is squashed into a single base commit for clean project history.