Skip to content

Commit e4cc459

Browse files
committed
🏗️ Add Ralph Wiggum long-running agent loop script
1 parent 3e22fe1 commit e4cc459

2 files changed

Lines changed: 122 additions & 0 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ Opinionated Python stack for fast development. The `saas` branch extends `main`
4949
| Auth (WorkOS + API keys) |||
5050
| Payments (Stripe) |||
5151
| Referrals + Agent system |||
52+
| Ralph Wiggum Agent Loop |||
5253

5354
[Full comparison](docs/branch_comparison.md)
5455

scripts/ralph.sh

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
#!/bin/bash
2+
# Ralph Wiggum - Long-running AI agent loop
3+
# Usage: ./ralph.sh [--tool opencode|amp|claude] [max_iterations]
4+
5+
set -e
6+
7+
# Parse arguments
8+
TOOL="opencode" # Default to opencode
9+
MAX_ITERATIONS=10
10+
11+
while [[ $# -gt 0 ]]; do
12+
case $1 in
13+
--tool)
14+
TOOL="$2"
15+
shift 2
16+
;;
17+
--tool=*)
18+
TOOL="${1#*=}"
19+
shift
20+
;;
21+
*)
22+
# Assume it's max_iterations if it's a number
23+
if [[ "$1" =~ ^[0-9]+$ ]]; then
24+
MAX_ITERATIONS="$1"
25+
fi
26+
shift
27+
;;
28+
esac
29+
done
30+
31+
# Validate tool choice
32+
if [[ "$TOOL" != "opencode" && "$TOOL" != "amp" && "$TOOL" != "claude" ]]; then
33+
echo "Error: Invalid tool '$TOOL'. Must be 'opencode', 'amp' or 'claude'."
34+
exit 1
35+
fi
36+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
37+
PRD_FILE="$SCRIPT_DIR/prd.json"
38+
PROGRESS_FILE="$SCRIPT_DIR/progress.txt"
39+
ARCHIVE_DIR="$SCRIPT_DIR/archive"
40+
LAST_BRANCH_FILE="$SCRIPT_DIR/.last-branch"
41+
42+
# Archive previous run if branch changed
43+
if [ -f "$PRD_FILE" ] && [ -f "$LAST_BRANCH_FILE" ]; then
44+
CURRENT_BRANCH=$(jq -r '.branchName // empty' "$PRD_FILE" 2>/dev/null || echo "")
45+
LAST_BRANCH=$(cat "$LAST_BRANCH_FILE" 2>/dev/null || echo "")
46+
47+
if [ -n "$CURRENT_BRANCH" ] && [ -n "$LAST_BRANCH" ] && [ "$CURRENT_BRANCH" != "$LAST_BRANCH" ]; then
48+
# Archive the previous run
49+
DATE=$(date +%Y-%m-%d)
50+
# Strip "ralph/" prefix from branch name for folder
51+
FOLDER_NAME=$(echo "$LAST_BRANCH" | sed 's|^ralph/||')
52+
ARCHIVE_FOLDER="$ARCHIVE_DIR/$DATE-$FOLDER_NAME"
53+
54+
echo "Archiving previous run: $LAST_BRANCH"
55+
mkdir -p "$ARCHIVE_FOLDER"
56+
[ -f "$PRD_FILE" ] && cp "$PRD_FILE" "$ARCHIVE_FOLDER/"
57+
[ -f "$PROGRESS_FILE" ] && cp "$PROGRESS_FILE" "$ARCHIVE_FOLDER/"
58+
echo " Archived to: $ARCHIVE_FOLDER"
59+
60+
# Reset progress file for new run
61+
echo "# Ralph Progress Log" > "$PROGRESS_FILE"
62+
echo "Started: $(date)" >> "$PROGRESS_FILE"
63+
echo "---" >> "$PROGRESS_FILE"
64+
fi
65+
fi
66+
67+
# Track current branch
68+
if [ -f "$PRD_FILE" ]; then
69+
CURRENT_BRANCH=$(jq -r '.branchName // empty' "$PRD_FILE" 2>/dev/null || echo "")
70+
if [ -n "$CURRENT_BRANCH" ]; then
71+
echo "$CURRENT_BRANCH" > "$LAST_BRANCH_FILE"
72+
fi
73+
fi
74+
75+
# Initialize progress file if it doesn't exist
76+
if [ ! -f "$PROGRESS_FILE" ]; then
77+
echo "# Ralph Progress Log" > "$PROGRESS_FILE"
78+
echo "Started: $(date)" >> "$PROGRESS_FILE"
79+
echo "---" >> "$PROGRESS_FILE"
80+
fi
81+
82+
echo "Starting Ralph - Tool: $TOOL - Max iterations: $MAX_ITERATIONS"
83+
84+
for i in $(seq 1 $MAX_ITERATIONS); do
85+
echo ""
86+
echo "==============================================================="
87+
echo " Ralph Iteration $i of $MAX_ITERATIONS ($TOOL)"
88+
echo "==============================================================="
89+
90+
# Run the selected tool with the ralph prompt
91+
if [[ "$TOOL" == "opencode" ]]; then
92+
# opencode run: use prompt from prompt.md
93+
if [ -f "$SCRIPT_DIR/prompt.md" ]; then
94+
OUTPUT=$(opencode run "$(cat "$SCRIPT_DIR/prompt.md")" 2>&1 | tee /dev/stderr) || true
95+
else
96+
echo "Error: $SCRIPT_DIR/prompt.md not found. Ralph needs a prompt to work."
97+
exit 1
98+
fi
99+
elif [[ "$TOOL" == "amp" ]]; then
100+
OUTPUT=$(cat "$SCRIPT_DIR/prompt.md" | amp --dangerously-allow-all 2>&1 | tee /dev/stderr) || true
101+
else
102+
# Claude Code: use --dangerously-skip-permissions for autonomous operation, --print for output
103+
OUTPUT=$(claude --dangerously-skip-permissions --print < "$SCRIPT_DIR/CLAUDE.md" 2>&1 | tee /dev/stderr) || true
104+
fi
105+
106+
# Check for completion signal
107+
if echo "$OUTPUT" | grep -q "<promise>COMPLETE</promise>"; then
108+
echo ""
109+
echo "Ralph completed all tasks!"
110+
echo "Completed at iteration $i of $MAX_ITERATIONS"
111+
exit 0
112+
fi
113+
114+
echo "Iteration $i complete. Continuing..."
115+
sleep 2
116+
done
117+
118+
echo ""
119+
echo "Ralph reached max iterations ($MAX_ITERATIONS) without completing all tasks."
120+
echo "Check $PROGRESS_FILE for status."
121+
exit 1

0 commit comments

Comments
 (0)