Ralphex is a specs-first CLI for running iterative coding loops against external agent CLIs such as OpenCode, Claude Code, and Cursor. It gives you built-in plan and build prompts, deterministic configuration precedence, and a simple command model that works well in repository-driven workflows.
It wraps a supported agent CLI in a repeatable loop: resolve a prompt, run the agent, and repeat until the agent emits <promise>COMPLETE</promise> or max iterations is reached. Each pass works against the updated repository, which makes it a good fit for specs, implementation plans, and repository-local prompts.
Note
The repository is iyaki/ralphex, but the CLI command remains ralph.
Important
Ralphex does not bundle an agent runtime. Install and authenticate a supported agent CLI separately, then make sure its binary is available on your PATH.
- Runs a repeatable prompt loop until the agent signals completion or max iterations is reached.
- Supports built-in
buildandplanprompts plus inline, stdin, and file-based prompts. - Applies predictable precedence across flags, environment variables, config files, and prompt front matter.
- Keeps repository-specific prompts and local overrides easy to manage.
- Fits the Ralph Wiggum style of specs-first development.
| Agent | Binary |
|---|---|
| OpenCode | opencode |
| Claude Code | claude |
| Cursor | cursor |
Codex, Copilot, Gemini, and more agents, coming soon
model and agent-mode are forwarded when the selected agent CLI supports them.
Adding support for new agents
Agent support Pull Requests are always welcomed. To add or update agent integrations, follow the workflow in CONTRIBUTING.md ("Adding Support for a New Agent"):
agent-spec-creationfor spec definitionagent-implementationfor TDD-based code changes
Requirements:
- A supported agent CLI in
PATH - Go
1.25if you are building from source
Prebuilt binaries are published on GitHub Releases. The latest release page is https://github.com/iyaki/ralphex/releases/latest.
Devcontainer feature:
ghcr.io/iyaki/devcontainer-features/ralph:1
Build from source:
make build
./bin/ralph --helpRun directly from source without building:
make run ARGS='--help'Install system-wide after building:
make installFor a reproducible local environment, open the repository with the included dev container in .devcontainer/devcontainer.json.
If you are already doing spec-driven development:
# Create a starter config
ralph init
# Generate or refresh the implementation plan for a scope
ralph plan authentication
# Run the default build loop
ralph
# Run the same default loop through the explicit entrypoint and prompt name
ralph run build
# Use a different agent for one run
ralph --agent claude --model claude-sonnet-4 buildCommon prompt entrypoints:
# Inline prompt text
ralph --prompt "Review the repository and summarize the highest-risk area"
# Prompt from stdin
printf 'Prompt from stdin' | ralph -
# Prompt from a file with an explicit prompt name
ralph --prompt-file ./prompts/review.md review
# Per-run child agent environment override
ralph --env HTTP_PROXY=http://127.0.0.1:8080 build| Command | Behavior |
|---|---|
ralph |
Equivalent to ralph run build |
ralph run [prompt] [scope] |
Explicit loop entrypoint |
ralph <prompt> [scope] |
Alias to ralph run <prompt> [scope] when <prompt> is not a subcommand |
ralph init |
Generate a starter config file |
ralph run init |
Run a prompt named init |
Useful examples:
# Built-in planning prompt
ralph plan payment-service
# Explicit run command
ralph run build
# Inline prompt text
ralph --prompt "Review the repository and summarize the highest-risk area"
# Prompt from stdin
printf 'Prompt from stdin' | ralph -
# Prompt from a file with an explicit prompt name
ralph --prompt-file ./prompts/review.md review
# Per-run child agent environment override
ralph --env HTTP_PROXY=http://127.0.0.1:8080 buildralph init currently writes a starter config with repository-friendly defaults. It requires an interactive terminal, writes to ./ralph.toml by default, and fails if the target already exists unless --force is set.
ralph init
ralph init --output ./team/ralph.toml
ralph init --forceThe generated starter config enables logging to ./ralph.log and sets prompts-dir = ".ralph/prompts" so prompt files can live inside the repository.
Prompt content is resolved in this order:
--prompt- stdin via
ralph -or--prompt-file - --prompt-file <path><prompts-dir>/<prompt>.md, searched upward from the current directory whenprompts-diris relative- Built-in
buildandplanprompts
If prompts-dir is an absolute path, Ralphex checks that exact path instead of walking parent directories.
Markdown prompt files can include YAML front matter for model and agent-mode overrides:
---
model: claude-sonnet-4
agent-mode: planner
---
Review the repository, compare it against the specs, and update the plan.Front matter is stripped before the prompt body is sent to the agent.
For model and agent-mode, effective precedence is:
flags > environment variables > prompt front matter > [prompt-overrides.<prompt>] > global config
Ralphex resolves settings with this precedence:
flags > environment variables > config file > defaults
Base config selection happens in this order:
--config <path>RALPH_CONFIG./ralph.tomlin the current directory
If a base config file is selected, a sibling ralph-local.toml is merged over it before environment variables and flags are applied. This lets you commit shared defaults in ralph.toml and keep machine-specific overrides untracked in ralph-local.toml.
For example, --config ./team/ralph.toml loads ./team/ralph-local.toml if it exists. It does not look for ./ralph-local.toml in the current working directory.
[env] entries and [prompt-overrides.<prompt>] entries merge by key across ralph.toml and ralph-local.toml. Parse errors in either file stop the run before the agent starts.
Tip
Keep shared team defaults in ralph.toml, add ralph-local.toml to .gitignore, and use the local file for personal overrides and secrets.
Example ralph.toml:
agent = "opencode"
model = "gpt-5"
max-iterations = 30
specs-dir = "specs"
specs-index-file = "README.md"
implementation-plan-name = "IMPLEMENTATION_PLAN.md"
prompts-dir = ".ralph/prompts"
no-log = false
log-file = "./ralph.log"
[prompt-overrides.plan]
agent-mode = "planner"
[env]
HTTP_PROXY = "http://127.0.0.1:8080"| Variable | Purpose |
|---|---|
RALPH_CONFIG |
Select the base config file path |
RALPH_MAX_ITERATIONS |
Override max-iterations |
RALPH_SPECS_DIR |
Override specs-dir |
RALPH_SPECS_INDEX_FILE |
Override specs-index-file |
RALPH_IMPLEMENTATION_PLAN_NAME |
Override implementation-plan-name |
RALPH_CUSTOM_PROMPT |
Provide inline prompt text, similar to --prompt |
RALPH_LOG_FILE |
Override the log file path |
RALPH_LOG_ENABLED |
Boolean: 1 or true enables logging, 0 or false disables it |
RALPH_LOG_APPEND |
Boolean: 1 or true appends, 0 or false truncates on start |
RALPH_PROMPTS_DIR |
Override prompts-dir |
RALPH_AGENT |
Select the agent: opencode, claude, or cursor |
RALPH_MODEL |
Override model |
RALPH_AGENT_MODE |
Override agent-mode |
If prompts-dir is unset everywhere, the runtime default is $HOME/.ralph. The starter config written by ralph init pins prompts-dir to .ralph/prompts so prompt files live in the repository.
Ralphex's own RALPH_* settings are separate from the environment passed to the child agent. Use [env] in config for shared values and repeatable --env KEY=VALUE flags for per-run overrides.
Child agent environment precedence is:
inherited environment < [env] in config < repeated --env flags
Later --env flags win for the same key. Each flag entry must use KEY=VALUE, and keys must match [A-Za-z_][A-Za-z0-9_]*.
With no config file, logging is disabled by default. When logging is enabled and no explicit path is configured, the effective default log file is ./ralph.log in the current working directory.
Logs mirror stdout and are written with 0600 permissions. Each run starts with a header that includes a timestamp plus git branch and commit metadata; unresolved git values are recorded as N/A.
# Enable logs for one run even if config disables them
ralph --no-log=false --log-file ./ralph.log build
# Start from an empty log file
ralph --no-log=false --log-file ./ralph.log --log-truncate build
# Same behavior through environment variables
RALPH_LOG_ENABLED=1 RALPH_LOG_APPEND=0 ralph buildCaution
Prompt text and agent output are written to stdout and, when logging is enabled, to the configured log file. Treat prompt files, config overrides, and logs as sensitive.
Ralphex is designed around a specs-first loop inspired by Geoffrey Huntley's Ralph methodology.
Typical flow:
- Define or refine requirements in
specs/. - Run
ralph plan <scope>to generate or updateIMPLEMENTATION_PLAN.md. - Run
ralphorralph buildto implement the next task. - Repeat until the agent returns the completion signal.
The built-in prompts use a <COMPLETION_SIGNAL> placeholder, which Ralphex replaces with <promise>COMPLETE</promise> before sending the prompt to the agent.
This repo includes the spec-creator skill (see .agents/skills/spec-creator/SKILL.md) for the first phase of Geoffrey Huntley's Ralph Wiggum methodology.
To install it using Vercel's skills CLI, run:
npx skills add https://github.com/iyaki/ralphex/ --skill spec-creator