Created
January 7, 2026 14:35
-
-
Save pengelbrecht/3782f1c41edb7ccf9a21e3cfb630f13a to your computer and use it in GitHub Desktop.
bead-ralph: Autonomous Beads epic completion - Claude CLI loops until done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/bin/bash | |
| # Ralph Pattern: Finish a Beads Epic | |
| # | |
| # Runs Claude in an autonomous loop to complete all tasks in a Beads epic. | |
| # Claude operates bd directly - the script just loops until COMPLETE. | |
| # | |
| # Beads: https://github.com/steveyegge/beads | |
| # | |
| # Usage: ./bead-ralph.sh <max-iterations> [epic-id] | |
| # | |
| # If epic-id is omitted, automatically selects the highest priority ready epic. | |
| # | |
| # Prerequisites: | |
| # - Claude CLI installed | |
| # - Beads CLI installed (bd) | |
| set -e | |
| if [ -z "$1" ]; then | |
| echo "Usage: $0 <iterations> [epic-id]" | |
| echo "" | |
| echo "Examples:" | |
| echo " $0 20 bd-a3f8 # Complete up to 20 tasks in epic bd-a3f8" | |
| echo " $0 50 bd-c7e2 # Complete up to 50 tasks in epic bd-c7e2" | |
| echo " $0 30 # Auto-select highest priority ready epic" | |
| exit 1 | |
| fi | |
| MAX_ITERATIONS=$1 | |
| if [ -z "$2" ]; then | |
| echo "No epic specified, finding highest priority ready epic..." | |
| EPIC_ID=$(bd ready --type=epic --limit=1 --sort=priority --json 2>/dev/null | jq -r '.[0].id // empty') | |
| if [ -z "$EPIC_ID" ]; then | |
| echo "Error: No ready epics found. Create one with: bd create --type=epic --title=\"...\"" | |
| exit 1 | |
| fi | |
| echo "Selected: $EPIC_ID" | |
| else | |
| EPIC_ID="$2" | |
| fi | |
| echo "Starting Ralph loop for Beads epic..." | |
| echo "Max iterations: $MAX_ITERATIONS" | |
| echo "Epic: $EPIC_ID" | |
| echo "" | |
| for ((i=1; i<=MAX_ITERATIONS; i++)); do | |
| echo "=== Iteration $i of $MAX_ITERATIONS ===" | |
| result=$(claude --dangerously-skip-permissions --print " | |
| BEADS EPIC RALPH - ITERATION $i of $MAX_ITERATIONS | |
| Epic: $EPIC_ID | |
| CONTEXT: | |
| You are running in an autonomous loop. A bash script invokes you repeatedly, once per iteration. | |
| Each iteration is a fresh Claude session - you have no memory of previous iterations. | |
| Read the epic's comments to see what earlier iterations accomplished and learned. | |
| PROCESS: | |
| 1. Run 'bd show $EPIC_ID' to see epic context, children status, and notes from previous iterations. | |
| 2. Run 'bd ready --parent $EPIC_ID' to see unblocked tasks for this epic. | |
| 3. If no tasks remain, output <promise>COMPLETE</promise> and stop. | |
| 4. Pick the highest priority ready task. | |
| 5. Implement it fully - code, tests, verification. | |
| 6. Run tests to ensure nothing broke. | |
| 7. Mark complete: bd close <task-id> | |
| 8. Commit changes: git add -A && git commit -m \"feat(<task-id>): <brief description>\" | |
| 9. Add iteration note: bd comments add $EPIC_ID \"Iteration $i: <task-id> | <what you did> | <any blockers or learnings>\" | |
| 10. Summarize what you did. | |
| RULES: | |
| - Complete ONE task per iteration. | |
| - Always leave tests passing. | |
| - Only work on tasks under epic $EPIC_ID. | |
| - Use bd commands directly (bd show, bd ready, bd close, bd comments add, bd update). | |
| - Always add a comment after completing a task - this is required, not optional. | |
| - Only output <promise>COMPLETE</promise> when bd ready shows no remaining tasks for this epic. | |
| AUTONOMY: | |
| - You are running NON-INTERACTIVELY. Never ask questions or wait for input. | |
| - Make smart autonomous decisions - install dependencies, choose reasonable defaults. | |
| - For small installs (Go, Node, Python packages): just do it. | |
| - For large installs (>1GB like Xcode, Android SDK, Docker images): output <promise>EJECT: <reason></promise> instead. | |
| - If truly blocked (missing credentials, unclear requirements): output <promise>BLOCKED: <reason></promise>. | |
| ") | |
| echo "$result" | |
| if [[ "$result" == *"<promise>COMPLETE</promise>"* ]]; then | |
| echo "" | |
| echo "=== Epic completed after $i iterations ===" | |
| exit 0 | |
| fi | |
| if [[ "$result" == *"<promise>EJECT:"* ]]; then | |
| echo "" | |
| echo "=== Ejected - manual intervention required ===" | |
| exit 2 | |
| fi | |
| if [[ "$result" == *"<promise>BLOCKED:"* ]]; then | |
| echo "" | |
| echo "=== Blocked - cannot proceed ===" | |
| exit 3 | |
| fi | |
| echo "" | |
| sleep 2 | |
| done | |
| echo "" | |
| echo "=== Max iterations ($MAX_ITERATIONS) reached ===" | |
| exit 1 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment