Skip to content

Instantly share code, notes, and snippets.

@markomitranic
Last active January 25, 2026 16:13
Show Gist options
  • Select an option

  • Save markomitranic/547f0a798dcb1fdeb2384eff6f8fcb38 to your computer and use it in GitHub Desktop.

Select an option

Save markomitranic/547f0a798dcb1fdeb2384eff6f8fcb38 to your computer and use it in GitHub Desktop.
Ralph loop for Opencode. Because everything currently out there sucks :(
#!/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