Skip to content

Instantly share code, notes, and snippets.

@fripSide
Last active January 22, 2026 05:28
Show Gist options
  • Select an option

  • Save fripSide/a722305eaad1b8e0c8c53cbb161193ed to your computer and use it in GitHub Desktop.

Select an option

Save fripSide/a722305eaad1b8e0c8c53cbb161193ed to your computer and use it in GitHub Desktop.
Make OpenCode work forever
#!/bin/bash
PROCESS_NAME="opencode"
BIN_PATH="/root/.opencode/bin/opencode"
CHECK_INTERVAL=180
FILE_CHECK_MINUTES=10
SIGNALS_APP_DIR="3-signals-app"
USER_TASK="Work now..."
WORKING_PID=""
# Template with placeholder that will be replaced dynamically
read -r -d '' RALPH_LOOP_TEMPLATE << 'EOF' || true
[search-mode]
MAXIMIZE SEARCH EFFORT. Launch multiple background agents IN PARALLEL:
- explore agents (codebase patterns, file structures, ast-grep)
- librarian agents (remote repos, official docs, GitHub examples)
Plus direct tools: Grep, ripgrep (rg), ast-grep (sg)
NEVER stop at first result - be exhaustive.
<command-instruction>
You are starting a Ralph Loop - a self-referential development loop that runs until task completion.
## How Ralph Loop Works
1. You will work on the task continuously
2. When you believe the task is FULLY complete, output: `<promise>{{COMPLETION_PROMISE}}</promise>`
3. If you don't output the promise, the loop will automatically inject another prompt to continue
4. Maximum iterations: Configurable (default 100)
## Rules
- Focus on completing the task fully, not partially
- Don't output the completion promise until the task is truly done
- Each iteration should make meaningful progress toward the goal
- If stuck, try different approaches
- Use todos to track your progress
## Exit Conditions
1. **Completion**: Output `<promise>DONE</promise>` (or custom promise text) when fully complete
2. **Max Iterations**: Loop stops automatically at limit
3. **Cancel**: User runs `/cancel-ralph` command
## Your Task
Parse the arguments below and begin working on the task. The format is:
`"task description" [--completion-promise=TEXT] [--max-iterations=N]`
Default completion promise is "DONE" and default max iterations is 100.
</command-instruction>
<user-task>
__USER_TASK_PLACEHOLDER__
</user-task>
EOF
get_ralph_loop() {
echo "${RALPH_LOOP_TEMPLATE//__USER_TASK_PLACEHOLDER__/$USER_TASK}"
}
working() {
local task="Check requirements in @Plan.md @Requriements.md . Redesign the solution, and implement the requirements. \
After completing each task, git add/commit/push the code to origin master. \
Then, repeat this process without stopping until 24 hours have passed."
local prompts=(
"Please check if there are better implementation methods"
"There are still bugs in the project, please fix them"
"The current code is too complex, can you simplify it"
"Are you sure all features are fully implemented? Please check again"
"Please submit the code to git via commit and push"
)
local random_index=$((RANDOM % ${#prompts[@]}))
USER_TASK="${task} ${prompts[$random_index]}"
echo "$(date): Working..."
COMMAND="$(get_ralph_loop)"
"$BIN_PATH" run "'$COMMAND'" &> /dev/null
echo "$(date): Working completed"
}
kill_opencode() {
echo "$(date): Killing $PROCESS_NAME..."
if pkill -x "$PROCESS_NAME" 2>/dev/null; then
echo "$(date): $PROCESS_NAME killed successfully"
else
echo "$(date): $PROCESS_NAME is not running"
fi
}
is_working_running() {
[ -n "$WORKING_PID" ] && kill -0 "$WORKING_PID" 2>/dev/null
}
check_recent_file_changes() {
if [ ! -d "$SIGNALS_APP_DIR" ]; then
return 0
fi
local recent_files=$(find "$SIGNALS_APP_DIR"/ -type f -not -path "*/\.git/*" -mmin -$FILE_CHECK_MINUTES 2>/dev/null)
if [ -z "$recent_files" ]; then
echo "$(date): No file changes in $SIGNALS_APP_DIR/ for more than $FILE_CHECK_MINUTES minutes, restarting OpenCode..."
return 1
else
echo "$(date): Recent file changes detected, OpenCode is working"
return 0
fi
}
start_working_async() {
if is_working_running; then
echo "$(date): Working function is already running (PID: $WORKING_PID)"
return
fi
echo "$(date): $PROCESS_NAME is not running. Starting process..."
working &
WORKING_PID=$!
echo "$(date): Working function started asynchronously (PID: $WORKING_PID)"
}
kill_opencode
while true; do
if pgrep -x "$PROCESS_NAME" > /dev/null; then
if ! check_recent_file_changes; then
kill_opencode
start_working_async
fi
else
start_working_async
fi
sleep $CHECK_INTERVAL
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment