-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Create ralph_protocol for GitHub Copilot and Codex #97
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
…github-copilot-and-codex feat: add Codex and GitHub Copilot runners to Ralph
Greptile OverviewGreptile SummaryThis PR extends Ralph’s loop to support two additional runners ( The main functional change is in However, the current implementation reintroduces an unsafe Confidence Score: 2/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant User as User
participant Ralph as ralph.sh
participant FS as Filesystem
participant Runner as Tool runner (amp/claude/codex/copilot)
User->>Ralph: ./ralph.sh --tool <tool> [max_iterations]
Ralph->>FS: Read prd.json/.last-branch (archive if branch changed)
Ralph->>FS: Ensure progress.txt exists
loop Iterations 1..MAX_ITERATIONS
Ralph->>FS: Read prompt template (prompt.md/CLAUDE.md/CODEX.md/COPILOT.md)
Ralph->>Runner: Execute runner command (possibly from RALPH_*_CMD)
Runner-->>Ralph: Combined stdout/stderr output
Ralph->>Ralph: Search output for <promise>COMPLETE</promise>
alt COMPLETE found
Ralph-->>User: Exit 0 (completed)
else Not complete
Ralph-->>User: Sleep then next iteration
end
end
Ralph-->>User: Exit 1 (max iterations reached)
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
5 files reviewed, 3 comments
| run_with_prompt() { | ||
| local prompt_file="$1" | ||
| local command="$2" | ||
|
|
||
| if [[ ! -f "$prompt_file" ]]; then | ||
| echo "Error: Prompt file not found: $prompt_file" | ||
| return 1 | ||
| fi | ||
|
|
||
| cat "$prompt_file" | eval "$command" | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Command injection via eval
run_with_prompt pipes the prompt into eval "$command", which allows arbitrary command execution if RALPH_*_CMD contains shell metacharacters (e.g. RALPH_AMP_CMD='amp; echo pwned'). Since these env vars are explicitly documented as user-configurable, this is a real injection path. Prefer executing via an array (no eval) and/or strict validation (reject ;|&$()\n etc.) before execution, and ensure the intended binary exists before running.
| set -e | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Masked runner failures
The loop runs commands as OUTPUT=$(... ) || true, so any runner failure (non-zero exit) is ignored and the script continues as if the iteration succeeded. That can cause false progress and makes diagnosing failures harder. If the goal is to keep iterating, capture $? and log/handle it explicitly (and don’t treat <promise>COMPLETE</promise> as valid unless the runner exited 0).
Additional Comments (1)
Completion is detected with |
Summary
This PR introduces security hardening, new tool support, and documentation improvements to Ralph.
I performed a security review of ralph.sh to block malicious command execution. The unsafe eval path was removed, override variables are now validated against dangerous characters, expected binaries per tool (amp, claude, codex, gh) are verified, and commands must exist in the environment before execution.
The execution flow was hardened against false completion and prompt injection. Ralph now only accepts COMPLETE when the runner exits successfully (exit code 0) and the tag appears as an exact output line.
Runner error handling was fixed so failures are not masked. I added set -o pipefail, centralized execution in execute_runner, preserved RUN_EXIT_CODE correctly, and ensured per-iteration failures are logged instead of silently ignored.
This PR also adds native support for --tool codex and --tool copilot in Ralph’s main loop, while keeping amp and claude. It includes tool validation, automatic prompt selection per tool, and centralized execution via run_with_prompt.
CLI commands are now configurable through environment variables (RALPH_AMP_CMD, RALPH_CLAUDE_CMD, RALPH_CODEX_CMD, RALPH_COPILOT_CMD), allowing different runtime environments without modifying the script.
New instruction templates CODEX.md and COPILOT.md were added. They mirror Ralph’s autonomous iterative flow using PRD, progress.txt, checks, and the COMPLETE termination condition.
Documentation was expanded to explicitly describe the security hardening (anti-injection behavior and override restrictions), prerequisites, usage examples for Codex/Copilot, template copies, and environment-variable command overrides.
AGENTS.md was updated to reflect the new runners and the hardened security pattern for future iterations of the project.
Testing
✅ bash -n ralph.sh
✅ ./ralph.sh --tool nope 1 >/tmp/test_nope.out 2>&1
✅ RALPH_AMP_CMD='amp;echo pwned' ./ralph.sh --tool amp 1 >/tmp/test_malicious.out 2>&1
✅ RALPH_COPILOT_CMD='gh copilot agent run' ./ralph.sh --tool copilot 1 >/tmp/test_gh.out 2>&1
✅ curl -L --max-time 15 -s https://docs.github.com/en/copilot
| head -n 5
✅ curl -L --max-time 15 -s https://developers.openai.com/codex
| head -n 5
✅ ./ralph.sh --tool nope 1 >/tmp/ralph_invalid.out 2>&1; echo $?; cat /tmp/ralph_invalid.out