Last active
January 25, 2026 16:13
-
-
Save markomitranic/547f0a798dcb1fdeb2384eff6f8fcb38 to your computer and use it in GitHub Desktop.
Ralph loop for Opencode. Because everything currently out there sucks :(
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 | |
| set -o pipefail | |
| AI_MODEL="opencode/gemini-3-flash" | |
| PLANNER_MESSAGE=$(cat <<'EOF' | |
| @./PRD.md | |
| 1. Pick the first available task that has not yet been marked as complete in the `PRD.md` file. | |
| 2. Plan must start with: PRD Task number/name and a detailed 3-paragraph description of the feature. | |
| 3. Plan must also include all testing steps required to verify the feature is working as expected, according to the testing requirements in `PRD.md`. | |
| 4. Write the plan into a file as per system instructions. This will be something like `.opencode/plans/1769356983063-tidy-rocket.md`. | |
| 5. Once the file is written, use cp to copy it to our repository root as `.ralph-plan.md`. | |
| IMPORTANT: You run in **non-interactive mode**: | |
| - Never ask the user for input or clarification | |
| - Never offer follow-up tasks or suggestions | |
| - Exit immediately after writing the plan | |
| EOF | |
| ) | |
| BUILDER_MESSAGE=$(cat <<'EOF' | |
| @./.ralph-plan.md | |
| 1. You are a task implementation agent. Read the instructions in `.ralph-plan.md`. | |
| 2. If there is no instructions in `.ralph-plan.md`, exit immediately with an error!!! | |
| 3. Implement the feature described in `.ralph-plan.md`. | |
| 4. Verify your changes as described in `PRD.md`. Do all testing a human would do. A task CANNOT be complete until all testing requirements are met. | |
| 5. Update `PRD.md` and check-off the task as complete. Do not modify any other tasks. | |
| 6. Stage and Commit all modified files using git. **COMMIT ONLY** - never push! | |
| IMPORTANT: You run in **non-interactive mode**: | |
| - Never ask the user for input or clarification | |
| - Never offer follow-up tasks or suggestions | |
| EOF | |
| ) | |
| # Max Loops MUST be provided as a positive integer. | |
| skip_planning=false | |
| max_loops="" | |
| for arg in "$@"; do | |
| case "$arg" in | |
| --continue) | |
| skip_planning=true | |
| ;; | |
| *) | |
| if [ -n "$max_loops" ]; then | |
| echo "Usage: $(basename "$0") <max-loops> [--continue]" >&2 | |
| exit 1 | |
| fi | |
| max_loops="$arg" | |
| ;; | |
| esac | |
| done | |
| if [ -z "$max_loops" ]; then | |
| echo "Usage: $(basename "$0") <max-loops> [--continue]" >&2 | |
| exit 1 | |
| fi | |
| if [ -n "$max_loops" ] && { ! [[ "$max_loops" =~ ^[0-9]+$ ]] || [ "$max_loops" -le 0 ]; }; then | |
| echo "Usage: $(basename "$0") <max-loops> [--continue]" >&2 | |
| exit 1 | |
| fi | |
| count=1 | |
| run_once() { | |
| if [ ! -s PRD.md ]; then | |
| echo "PRD.md missing or empty; aborting." >&2 | |
| return 1 | |
| fi | |
| if [ "$skip_planning" = false ]; then | |
| echo "## PLANNING PHASE ##" | |
| OPENCODE_PERMISSION='{"*":"allow"}' OPENCODE_EXPERIMENTAL_PLAN_MODE=1 opencode run ./ \ | |
| --model "$AI_MODEL" \ | |
| --file ./PRD.md \ | |
| --agent plan "$PLANNER_MESSAGE" | |
| if [ ! -s ./.ralph-plan.md ]; then | |
| echo "Plan missing or empty; aborting." >&2 | |
| return 1 | |
| fi | |
| fi | |
| echo "## IMPLEMENTATION PHASE ##" | |
| OPENCODE_PERMISSION='{"*":"allow"}' opencode run ./ \ | |
| --model "$AI_MODEL" \ | |
| --file ./.ralph-plan.md \ | |
| --agent build "$BUILDER_MESSAGE" | |
| rm -rf ./.ralph-plan.md | |
| } | |
| # Run the loop until max loops is reached. | |
| while [ "$count" -le "$max_loops" ]; do | |
| echo "## RALPH LOOP $count/$max_loops ##" | |
| run_once | |
| status=$? | |
| if [ "$status" -ne 0 ]; then | |
| echo "ralph failed (exit $status); aborting." >&2 | |
| exit "$status" | |
| fi | |
| count=$((count + 1)) | |
| done | |
| echo "Reached max loops ($max_loops); exiting." |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment