All notable changes to this project are documented here.
Format based on Keep a Changelog.
- "Cannot reach the server" errors (Windows). Setup now registers the provider at
http://localhost:<port>/v1(was127.0.0.1) and the provider reaches OpenCode vialocalhost— Node/undici on Windows can time out on the127.0.0.1IPv4 literal whilelocalhostresolves fine. Existing installs: re-runsetup --forceto refreshopencode.json.
- The
ralph-workeragent now gets every tool (*: allowplus the ralph_/rlm_ allows) — workers are trusted implementers, so all built-in OpenCode tools are explicitly available (the destructive-tool gate untilralph_load_contextstill applies). - The supervisor prompt now documents the messaging API (
POST /api/loops/:id/messageand thesend-messageCLI) so it knows it can be messaged out-of-band by scripts/watchers and can propose that automation.
- No more console window popping up on Windows when the provider auto-starts. Added
windowsHide: trueto the auto-start plugin's spawn and to theservecommand's provider spawn (theshell: truecmd launch was what opened the window). Re-runsetup --forceto refresh an already-installedralph-autostart.ts.
- Upstream token streaming. The supervisor now streams tokens from the model itself —
callSupervisorLlmparses the upstream provider's SSE and forwards content deltas live — so the final answer appears token-by-token as the model generates it, instead of only after the call returns. Builds on 0.4.0's per-round progress markers. (Unit-tested: content deltas forwarded, tool calls reassembled across deltas.)
- Worker-model guard. Ralph now refuses to spawn a worker on the
ralph-rlmprovider (the supervisor) and warns when no worker model is configured. This prevents the failure the smoke loop surfaced: withworker.providerID/worker.modelIDunset, OpenCode could default the worker to the supervisor model, turning the worker into a rogue orchestrator (callingwrite_plan/stop_loop) instead of writing code. Documented in the troubleshooting reference.
- Streaming supervisor responses. The chat-completions endpoint now streams progressively: as the turn runs its tool rounds (the slow part), live markers (
→ start_loop,→ loop_status, …) appear, then the final answer streams — instead of hanging silently until the whole turn finishes and dumping it at once. Verified live: SSEchat.completion.chunks arrive incrementally.
- Supervisor tool calls within a round run concurrently now (was sequential), and the default
maxToolRoundsis raised 8 → 12. Hitting the round limit no longer reads as an error — it's a calm "I've taken several steps … ask me to continue" status. (Surfaced by the end-to-end smoke loop, where the prior limit/error was easy to hit.)
- The end-to-end smoke loop validated the full stack live (auto-start, credential auto-detect, orchestration, the
ralph-workeragent, and a real worker creating a file untilverifypassed). It also surfaced a footgun to address next: when no worker model is set, the worker can fall back to theralph-rlm/supervisormodel — setworker.providerID/worker.modelIDinralph-provider.json.
- Setup-skill references now fully document provider auto-start: the
--no-autostartflag and expected output (cli.md), a.opencode/plugins/ralph-autostart.tssection (config-files.md), and auto-start-aware "provider unreachable" guidance — including thenode-on-PATH requirement (troubleshooting.md).
- Provider auto-start —
setupinstalls.opencode/plugins/ralph-autostart.ts, which launches the Ralph provider when OpenCode loads, so you no longer runopencode-ralph-rlm serveby hand. It's idempotent (theservepre-flight reuses a running provider), starts eagerly at OpenCode launch, and logs to<tmp>/opencode-ralph-rlm/provider.log. Disable withsetup --no-autostartorRALPH_AUTOSTART=0. (Verified live: OpenCode runs the plugin at launch; the provider comes up and is reused across restarts.) - Interview skill + planning playbook: a step on assumptions — state them explicitly to the user, record them in a
## Assumptionssection ofPLAN.md, and add an early milestone to test any load-bearing unverified assumption.
- The supervisor now develops the
verify.commandwith you — it's the loop's only stop condition, so this matters. New toolsget_verify/set_verify/run_verifylet the supervisor read, write (ralph.json, merge-safe), and dry-run the command out-of-loop to validate it (a good command fails before the work is done). Crafting it is now part of the planning phase (supervisor +interview-and-create-planskill), andstart_loopwarns whenverify.commandis missing.
- Supervisor system prompt gained a "Verification is the contract" section and a richer Swarms section (when/why to use them, that they never run verify or end the loop, and how to collect/merge results).
ralph_*/rlm_*tools are now hidden from normal OpenCode sessions (not just inert). The worker plugin'sconfighook denies them globally and re-allows them only in a dedicatedralph-workeragent that workers run under (the new defaultworker.agent). Verified live: a normal session reports the tools as unavailable; a worker session can use them and still has full coding tools. The 0.3.6 session-scoped gate/prompt remain as defense-in-depth.- Do not set
worker.agent(e.g. tobuild) — that agent has the Ralph tools denied; workers must useralph-worker. The example/scaffold configs no longer set it.
- Worker plugin no longer pollutes normal OpenCode sessions. The plugin loads for every session in a project, but its worker system prompt, the edit/bash context gate, and compaction context were being applied to all sessions — which injected worker instructions into normal chats and blocked
edit/bashuntilralph_load_context()(a call a normal session never makes). These now apply only to Ralph worker sessions (identified by therlm-worker-attempt-*session title). In normal sessions theralph_*/rlm_*tools are inert (they error if invoked) andedit/bashare never gated.
- Setup skill + troubleshooting now cover the
servepre-flight check: stop a stale/already-running provider before starting a new version, and recognize that an "already running" message explains wrong-version / missing-feature symptoms.
servepre-flight check — before starting, the CLI probes the target port and, if a Ralph provider is already running, reports its version vs. the one being started and tells you to stop the old one (a running provider does not pick up new code). Also detects when the port is held by a non-Ralph service. (Probes bothlocalhostand127.0.0.1to dodge a Node fetch/IPv6 timeout quirk.)
- The "no supervisor API key" error now explains the full lookup order (env →
ralph-provider.json→ OpenCode auth) and how to fix it (opencode auth login+ restart, or set the key), and reports the resolvedsource.
- Confirmed supervisor auto-detect endpoints + model ids against the live OpenCode provider registry (
/config/providers): OpenCode Zen (opencode/opencode-go) →https://opencode.ai/zen/v1with the freedeepseek-v4-flash-freemodel; Google →gemini-2.5-flash. Prefer the free Zen model first. - Updated the stale OpenAI default model (
gpt-4o-mini→gpt-5.4-mini) in the supervisor default and all docs/examples.
- Supervisor credential auto-detect — when no
RALPH_SUPERVISOR_API_KEY(orralph-provider.jsonkey) is set, the provider falls back to OpenCode's own auth (~/.local/share/opencode/auth.json), using a keyed provider you've already authenticated (e.g. Google, OpenCode Zen). So an OpenCode user usually needs no separate supervisor key. Precedence: env →ralph-provider.json→ OpenCode auth → built-in default. GET /api/healthreports supervisor readiness —supervisor.ready, the resolvedmodel, andsource(env/opencode-auth:<provider>/default), with ahintwhen no credential is found. The setup skill uses this to verify before launching.
- Setup skill is now discovery-driven: it inspects
opencode auth list/opencode models, relies on auto-detect for the supervisor, recommends (does not force) a free OpenCode model for workers, and directs the user to authenticate (opencode auth login) if nothing usable is found — before starting the provider. Added a re-open-OpenCode step.
- Planning phase before the loop —
interview-and-create-planskill (Understand → Sketch → Plan → Review → Write). Two paths: the supervisor runs the interview itself (newrepo_search/repo_grep/write_plantools) or you run the skill in a TUI session.start_looplaunches against an authoredPLAN.mdinstead of a placeholder, and weaves the goal into a freshly bootstrapped plan. - Named plans (versions) — protocol files live in
.ralph-rlm/plans/<name>/with per-plan.state/markers, so multiple plans can coexist and be switched. New supervisor toolslist_plans/select_plan/new_plan. Configurable viaplans.dir/plans.activeinralph.json(default.ralph-rlm/plans;""/"."keeps the legacy root layout, which is also auto-detected for existing repos). - Config location —
ralph.jsonis now read from.ralph-rlm/ralph.jsonfirst, then.opencode/ralph.json. - External messages to the supervisor —
POST /api/loops/:sessionId/message(andopencode-ralph-rlm send-message/sessionsCLI) let watchers/scripts notify or steer the supervisor out-of-band. Records to protocol files, toasts the TUI, and runs a supervisor turn so it can act autonomously (runTurn:falseto only record). Supervisor turns are now serialized per session. opencode-ralph-rlm plan-pathCLI — prints the active plan'sPLAN.mdlocation (layout-aware), so a planning skill/script writes the plan wherestart_loopdetects it.ralph_load_context()now returnsplan_dirand aprotocol_pathsmap so workers edit protocol files at the correct location in named-plan mode.
NOTES_AND_LEARNINGS.mdis now a curated, editable knowledge base (no longer framed as append-only). Workers are encouraged to edit/reorganize/prune it and to link out to the domain glossary, ADRs, and design docs rather than restating them.- Removed the supervisor
read_filetool — planning usesrepo_grep; Path B uses OpenCode's built-inread. - Rewrote the README to lead with a plain-language explanation (and credit ralph-wiggum.ai); deep architecture moved to an "under the hood" section. Getting-started guide updated for planning, named plans, and the new commands.
- Plan-name path traversal —
normalizePlanNamenow rejects./../dot-only names so a plan name (viaselect_plan/new_planor the.activepointer) can't resolve to or escape the plans directory. Version-like names with internal dots (e.g.v1.2) are preserved. - Protocol-patch rewriting now only adjusts
a//b/diff prefixes (the formgit apply -p1needs), avoiding a mis-strip on bare path headers. - Accelerated
rlm_greptarget-file matching is separator-insensitive, so it stays accelerated in named-plan mode on Windows. ralph.json-related error messages no longer hard-code.opencode/now that config can also live in.ralph-rlm/.
- Packaged setup CLI — Node-compatible
opencode-ralph-rlm setup|serve|doctorfornpx @doeixd/opencode-ralph-rlm ...project initialization, provider startup, and diagnostics - Setup skill —
skills/setup-opencode-ralph-rlm/SKILL.mdplus references for agents installing Ralph RLM into target repositories - Installation guide —
INSTALLATION.mdleads with the agent skill, then CLI setup, then manual setup - FFF worker search acceleration — optional
@ff-labs/fff-nodeintegration forrlm_grep, plus newrlm_file_searchandrlm_globworker tools with graceful fallback when native search is unavailable - Session bridge plugin —
.opencode/plugins/ralph-session-bridge.tsinjectsx-opencode-session-idon Ralph provider requests via OpenCodeauth.loaderfetch wrapper - Session debug logging —
RALPH_SESSION_DEBUG=1logs correlation headers on/v1/chat/completions - E2E smoke helper —
bun run bin/e2e-smoke.ts(HTTP checks;--spawnfor self-contained runs) - Provider-as-supervisor architecture — OpenAI-compatible Nitro server (
ralph-rlm/supervisormodel) at:8787 @ralph-rlm/engine—LoopEngine, verify/rollover, OpenCode SDK integration,LoopRegistry@ralph-rlm/provider—SupervisorAgent, supervisor tools, SSE/v1/chat/completions, management/api/loops/*@ralph-rlm/worker-plugin— thin worker tools (rlm_grep,rlm_slice, context gate,ralph_ask)bin/ralph-serve— start provider;--doctor,--autofix,--port,--opencode-url,--worktree- Worker ↔ supervisor questions —
pending_input.json,list_worker_questions,answer_worker - Hardening (M4) — heartbeat warnings, spawn/error recovery, CI
verify.yml - Swarm parallelism (M6) —
spawn_swarm,swarm_status,swarm_cancel,swarm_collect,/api/swarms/* - Opt-in unsafe swarm scripts —
swarm_unsafe_runtime_code_evalwith audit log under.opencode/swarm/runs/ - Documentation — provider-first README, GETTINGSTARTEDGUIDE, MIGRATION.md
- Hardening (M7) —
WorktreeEventBridge(oneevent.subscribeper worktree),createAsyncEventQueue(serialized events, 10k cap), loop in-flight guards (spawnInFlight,verifyInFlight,resumeInFlight),stop_loop→done+outcome: "stopped",pause_loopaborts worker, productionanonymoussession block, worker attempt sync via.opencode/loop_attempt.json, swarm registry prune, no silent supervisor API-key fallback, expanded provider/engine tests (55+)
- Loop orchestration is deterministic code in
LoopEngine, not LLM self-discipline in the main session - Default plugin path:
ralph-worker.ts(legacy monolith moved toplugins-legacy/) - Default agent instructions — comprehensive supervisor + worker prompts; v0.2-accurate bootstrap
PLAN.md/RLM_INSTRUCTIONS.md; removed stale v0.1subagent_*references; worker plugin system prompt sourced from@ralph-rlm/enginetemplates
.opencode/plugins-legacy/ralph-rlm.ts— v0.1 plugin-as-orchestrator; kept for reference, not auto-loaded
- Nothing yet — legacy bundle
dist/ralph-rlm.jsstill built for npm compatibility
- Experimental OpenCode plugin with
ralph_spawn_worker,session.idlehooks, and in-session orchestration - See git history and legacy README sections for v0.1 tool reference