@john-ezra/openralph 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.dockerignore ADDED
@@ -0,0 +1,25 @@
1
+ node_modules/
2
+ dist/
3
+ coverage/
4
+ runs/
5
+ plan/
6
+ specs/
7
+ .opencode/
8
+ TODO.md
9
+ HANDOFF*.md
10
+ RELEASE-PREP.md
11
+ IMPLEMENTATION_PLAN.md
12
+ *.log
13
+ *.tgz
14
+ *.tsbuildinfo
15
+ .eslintcache
16
+ .git/
17
+ .DS_Store
18
+ .envrc
19
+ tui.json
20
+ .env
21
+ .env.*
22
+ !.env.example
23
+ !.env.sample
24
+ !.env.template
25
+ !.env.dist
package/AGENTS.md ADDED
@@ -0,0 +1,148 @@
1
+ # OpenRalph
2
+
3
+ OpenRalph is a light opencode plugin that implements the Ralph workflow from Clayton Farr's Ralph Playbook.
4
+
5
+ ## Core Principles
6
+
7
+ - Keep the implementation simple.
8
+ - Preserve Ralph's central mechanism: one fresh top-level opencode run per loop iteration.
9
+ - Use disk files as persistent state: `specs/*`, `AGENTS.md`, `IMPLEMENTATION_PLAN.md`, `PROMPT_plan.md`, and `PROMPT_build.md`; use `runs/*` only for durable local run artifacts and audit/debug output.
10
+ - Do not turn OpenRalph into a general sandbox or orchestration platform.
11
+ - Safety strategy is the user's responsibility. OpenRalph provides only lightweight guardrails and optional Dockerized loop execution.
12
+ - Avoid complex modes, safety matrices, Podman requirements, or heavy process abstractions.
13
+
14
+ ## Ralph Phases
15
+
16
+ - Phase 1: Define Requirements -> `/ralph` Design
17
+ - Phase 2: Planning -> `/ralph` Plan
18
+ - Phase 3: Building -> `/ralph` Build
19
+
20
+ Use these phase names consistently.
21
+
22
+ ## Public Commands
23
+
24
+ - `/ralph`: the only public TUI slash command. It opens Design, Plan, and Build modes.
25
+ - `openralph plan` and `openralph build`: CLI/headless launcher entrypoints with the same public loop args.
26
+
27
+ ## Internal Commands
28
+
29
+ - `/ralph-plan-iteration`: one fresh planning iteration.
30
+ - `/ralph-build-iteration`: one fresh build iteration/task.
31
+
32
+ The server plugin should inject these commands only for authorized loop child processes. Normal host TUI sessions must not expose internal iteration prompts.
33
+
34
+ ## Loop Rules
35
+
36
+ - Plan/build loops launch child `opencode run` processes.
37
+ - Each child process handles one iteration with fresh top-level context.
38
+ - Never use `--continue` for child runs.
39
+ - Always pass `--dir <project-root>` to child runs.
40
+ - Plan/build child runs use `--dangerously-skip-permissions`.
41
+ - When Docker mode is enabled, host plan/build commands launch one Docker container and the full loop runs inside it.
42
+ - Docker mode runs the container `openralph plan` or `openralph build` CLI entrypoint, never public prompt command replay.
43
+ - Container loops set `OPENRALPH_IN_DOCKER=1` and require token-backed Docker attestation before running.
44
+ - Docker mode disables project OpenCode config and injects config that loads only image-bundled OpenRalph.
45
+ - Docker mode injects a `chrome-devtools` MCP server into the container OpenCode config for browser validation.
46
+ - Docker mode runs containers with `--pull=never`, `--shm-size=1g`, and `--security-opt no-new-privileges:true`.
47
+ - The default image uses a non-root `opencode` user when Docker cannot run as the host UID/GID.
48
+ - Default max iterations is unlimited.
49
+ - Retry child process failures.
50
+ - Stop after 3 consecutive child process failures.
51
+ - Stop when Ralph reports completion.
52
+ - Ctrl+C is the manual stop mechanism.
53
+ - On first Ctrl+C, request shutdown, forward SIGINT to the active child process, and stop launching new iterations.
54
+ - On second Ctrl+C, force terminate the active child process and exit.
55
+ - User interrupt is not a child process failure and must not be retried.
56
+ - Push only when `--push` is passed and Docker mode is not used.
57
+ - Plan/build loops write project-local run artifacts under `runs/openralph-<phase>-YYYYMMDD-HHMMSS/`; artifacts must not replace `IMPLEMENTATION_PLAN.md` as the work queue.
58
+ - `runLoop()` must not independently launch Docker or inspect `docker.enabled`; the shared launcher resolves `docker-host-launch`, `host-explicit`, `host-config-default`, or `container-attested` once.
59
+
60
+ ## Model Selection
61
+
62
+ Model selection is intentionally simple.
63
+
64
+ Precedence:
65
+
66
+ ```text
67
+ command --model -> OpenRalph config -> opencode default
68
+ ```
69
+
70
+ Plugin options:
71
+
72
+ ```json
73
+ {
74
+ "defineModel": "heavy-model",
75
+ "planModel": "cheap-model",
76
+ "buildModel": "cheap-model",
77
+ "docker": {
78
+ "enabled": true,
79
+ "image": "openralph:local",
80
+ "maskEnv": true
81
+ }
82
+ }
83
+ ```
84
+
85
+ If no model is configured or passed, omit `--model` and let opencode use its default.
86
+
87
+ ## Git Guardrails
88
+
89
+ - Require a Git worktree before running OpenRalph Plan or Build.
90
+ - Warn, but do not block, on `main` or `master`.
91
+ - Create lightweight namespaced Git tags after each successful clean build iteration.
92
+ - Tags are local by default.
93
+ - Do not push commits unless `--push` is passed.
94
+ - Do not push tags in v1 unless explicitly implemented later.
95
+
96
+ Recommended tag shape:
97
+
98
+ ```text
99
+ openralph/build-YYYYMMDD-HHMMSS/001
100
+ openralph/build-YYYYMMDD-HHMMSS/002
101
+ ```
102
+
103
+ Use tags only after a successful build iteration with a new commit and clean worktree.
104
+
105
+ ## Development Git Workflow
106
+
107
+ - Do not make feature, fix, or improvement changes directly on `main`.
108
+ - Create a short-lived branch before editing, such as `feature/<name>` or `fix/<name>`.
109
+ - Keep `main` as the integration branch; merge reviewed/validated branch work back into `main`.
110
+ - Push branches for collaboration or backup, then merge to `main` only after validation passes.
111
+ - If accidental local edits happen on `main`, move them to a branch before committing unless the user explicitly approves a direct `main` commit.
112
+
113
+ ## Safety Posture
114
+
115
+ OpenRalph v1 supports optional Dockerized execution for Plan and Build.
116
+
117
+ Rationale:
118
+
119
+ - Ralph requires autonomy, so plan/build child runs use `--dangerously-skip-permissions`.
120
+ - Docker mode reduces host filesystem blast radius but is not a formal sandbox guarantee.
121
+ - TUI Design mode remains host-side so host memory/MCP integrations can participate in ideation.
122
+ - TUI Design mode is host-side and injects a Ralph Design prompt into the current session after an optional initial idea prompt.
123
+ - Docker mode mounts the repo read/write at `/workspace`, mounts OpenCode auth read-only, masks real `.env*` files by default, and does not mount host home, SSH, config, desktop sockets, or the Docker socket.
124
+ - Docker mode does not mount host Git config, SSH keys, GPG material, browser profiles, browser cookies, or desktop sockets.
125
+ - Dockerized OpenRalph Build requires host/project Git `user.name` and `user.email`; OpenRalph passes them through author/committer environment variables, disables commit/tag signing inside Docker, and marks `/workspace` as a safe Git directory.
126
+ - The default `openralph:local` image includes Bun, Node 22, npm/npx/corepack, Git, Bash, curl, Python 3, native build tools, ripgrep, Google Chrome stable, screenshot-friendly fonts, `opencode-ai@1.15.13`, and `chrome-devtools-mcp@1.1.1`.
127
+ - Chrome DevTools MCP runs through `/opt/openralph/bin/chrome-devtools-mcp-wrapper`, which starts isolated headless Chrome on a loopback debugging port with a temporary profile and connects MCP via `--browser-url`.
128
+ - The user still chooses their own isolation strategy and risk level.
129
+ - Recommended operator practice is to run on a dedicated branch or disposable clone.
130
+
131
+ ## Implementation Preference
132
+
133
+ - Use TypeScript targeting Bun/opencode's plugin runtime.
134
+ - Keep the plugin small and deterministic.
135
+ - Prefer plain Markdown prompt/state files over JSON orchestration.
136
+ - Do not hardcode specific model IDs.
137
+ - Do not add additional public flags unless they are clearly necessary.
138
+ - Keep project setup guidance lean: validation commands, project conventions, and prioritized plan items matter more than prompt complexity.
139
+ - Do not add every language runtime to the default Docker image; projects needing Go, Rust, Java, databases, or other specialized tooling should extend `openralph:local`.
140
+ - Keep browser tooling Docker-only in v1; do not make Chrome DevTools MCP a host-side dependency.
141
+ - Public Design/Plan/Build commands are not prompt-backed `cfg.command` entries. The TUI plugin registers only `/ralph`; the server plugin deletes stale public command entries and throws if a stale prompt-backed public command is executed.
142
+
143
+ ## References
144
+
145
+ - Ralph Playbook: https://github.com/ClaytonFarr/ralph-playbook
146
+ - Formatted guide: https://claytonfarr.github.io/ralph-playbook/
147
+ - opencode plugin docs: https://opencode.ai/docs/plugins/
148
+ - opencode command docs: https://opencode.ai/docs/commands/
package/CHANGELOG.md ADDED
@@ -0,0 +1,16 @@
1
+ # Changelog
2
+
3
+ All notable changes to OpenRalph will be documented in this file.
4
+
5
+ The format is based on Keep a Changelog, and this project uses semantic versioning.
6
+
7
+ ## [0.1.0] - 2026-06-04
8
+
9
+ ### Added
10
+
11
+ - Initial public release of the OpenRalph opencode plugin and CLI.
12
+ - TUI `/ralph` command with Design, Plan, and Build modes.
13
+ - `openralph plan` and `openralph build` CLI/headless loop entrypoints.
14
+ - Optional attested Docker mode for Plan and Build loops.
15
+ - Docker `.env*` masking with example/template env files preserved.
16
+ - Local lightweight build tags for successful clean build commits.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 John Ezra
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,48 @@
1
+ # Ralph Build Iteration
2
+
3
+ 0a. Study `specs/*` with up to 500 parallel research subagents to understand the required behavior.
4
+ 0b. Study `IMPLEMENTATION_PLAN.md`.
5
+ 0c. Study current source code and shared project patterns before making changes.
6
+ 0d. Study `AGENTS.md` for build, test, lint, typecheck, and operational guidance.
7
+
8
+ 1. Choose the most important actionable item from `IMPLEMENTATION_PLAN.md`.
9
+
10
+ 2. Before editing, search the codebase with up to 500 parallel research subagents for searches, reads, and context gathering. Do not assume functionality is missing; confirm the current state first. Use higher-reasoning subagents only for complex debugging or architectural decisions.
11
+
12
+ 3. Implement exactly one coherent task from the plan. Keep the change complete, minimal, and consistent with existing project patterns.
13
+
14
+ 3a. If the chosen task is too large or unclear to complete cleanly in one iteration, split or clarify it in `IMPLEMENTATION_PLAN.md`, document what should happen next, and stop rather than doing a partial implementation.
15
+
16
+ 4. Run the relevant validation from `AGENTS.md`, including targeted tests for the changed unit when available. Use only 1 validation subagent at a time for build/tests so validation creates clear backpressure. Fix failures caused by the change before proceeding.
17
+
18
+ 4a. For frontend or web UI tasks, validate in a browser when practical. Start the app, inspect desktop and mobile layouts, check console errors, and use screenshots or visual inspection for layout/design issues before committing.
19
+
20
+ 5. If unrelated failures or bugs are discovered, either resolve them if they are part of the current increment or document them in `IMPLEMENTATION_PLAN.md`.
21
+
22
+ 5a. If the iteration exposes a validation gap, unsafe operation pattern, repeated failure mode, or missing backpressure, document a concrete follow-up in `IMPLEMENTATION_PLAN.md` or a brief reusable operational note in `AGENTS.md`.
23
+
24
+ 6. Keep `IMPLEMENTATION_PLAN.md` up to date. Remove or mark completed work, add discovered follow-up work, and document blockers.
25
+
26
+ 7. Update `AGENTS.md` only for brief operational learnings, such as correct commands or important run/build notes. Do not use it as a progress log.
27
+
28
+ 8. Before committing, update `IMPLEMENTATION_PLAN.md` so the next fresh iteration can choose the next most important task without relying on prior context. When validation passes and the task is complete, commit the changes with a concise message. After `git commit` succeeds, confirm `git status --short` is clean. Only then mark commit-related todos complete. Do not push. Do not create tags.
29
+
30
+ 9. If you completed and committed one task in this iteration, print exactly this standalone final line, even if that task was the last actionable item:
31
+
32
+ RALPH_ITERATION_COMPLETE
33
+
34
+ 10. If this iteration starts with no actionable tasks remaining, ensure `IMPLEMENTATION_PLAN.md` reflects that state, confirm `git status --short` is clean, and print exactly this standalone final line:
35
+
36
+ RALPH_COMPLETE
37
+
38
+ 11. If work cannot continue because of a real blocker, document the blocker in `IMPLEMENTATION_PLAN.md` and print exactly:
39
+
40
+ RALPH_BLOCKED
41
+
42
+ 99999. Important: capture the why when authoring documentation, tests, and implementation notes.
43
+ 999999. Important: single sources of truth; avoid placeholder implementations and ad-hoc copies.
44
+ 9999999. Important: keep `AGENTS.md` operational only. Status and progress belong in `IMPLEMENTATION_PLAN.md`. Do not use Ralph sentinel strings in todos or prose; reserve exactly one standalone sentinel for the final output line.
45
+
46
+ ## IMPLEMENTATION_PLAN.md Hygiene
47
+
48
+ Treat `IMPLEMENTATION_PLAN.md` as the canonical prioritized checklist. Keep remaining actionable work sorted from highest to lowest value. Completed items should be removed or clearly marked complete. Blocked items must include the blocker and what would unblock them before printing `RALPH_BLOCKED`. Add discovered bugs, audit findings, validation gaps, and follow-up work in the correct priority position. Remove stale, duplicated, or contradicted tasks. If the plan becomes noisy or large, clean completed/stale entries while preserving remaining work and blockers. Do not record progress in `AGENTS.md`.
package/PROMPT_plan.md ADDED
@@ -0,0 +1,29 @@
1
+ # Ralph Planning Iteration
2
+
3
+ 0a. Study `specs/*` with up to 250 parallel research subagents to learn the application requirements.
4
+ 0b. Study `IMPLEMENTATION_PLAN.md` if present; it may be incomplete or wrong.
5
+ 0c. Study the current source code and project structure with up to 250 parallel research subagents before making plan changes.
6
+ 0d. Study shared utilities, components, and existing patterns before recommending new ones.
7
+
8
+ 1. Compare `specs/*` against the current implementation using up to 500 parallel research subagents for code search, reads, and gap analysis. Do not assume functionality is missing; confirm with code search first. Use one higher-reasoning subagent where useful to synthesize findings and prioritize the plan.
9
+
10
+ 2. Create or update `IMPLEMENTATION_PLAN.md` as a prioritized list of remaining actionable work. Keep it up to date with items that are complete, incomplete, blocked, or discovered during research.
11
+
12
+ 3. Consider TODOs, placeholder implementations, skipped or flaky tests, minimal stubs, inconsistent patterns, missing validation, missing backpressure, and audit findings from recent `runs/openralph-*` artifacts when available.
13
+
14
+ 4. Plan only. Do not implement code. Do not commit. Do not push. Do not create tags.
15
+
16
+ 5. If specs are missing or inconsistent, document the issue clearly. Only create or refine specs when necessary to unblock accurate planning, and keep specs behavioral rather than implementation-prescriptive.
17
+
18
+ 99999. Important: capture the why when documenting tasks, tests, and implementation importance.
19
+ 999999. Important: keep `AGENTS.md` operational only. Status, progress, and planning belong in `IMPLEMENTATION_PLAN.md`.
20
+
21
+ ## IMPLEMENTATION_PLAN.md Hygiene
22
+
23
+ Treat `IMPLEMENTATION_PLAN.md` as the canonical prioritized checklist. Keep remaining actionable work sorted from highest to lowest value. Prefer tasks small enough for one build iteration when practical. If a task would require broad refactoring, unclear sequencing, or repeated retries, split it into smaller independently validatable tasks. Remove or clearly mark completed work. Remove stale, duplicated, or contradicted tasks. Blocked items must include the blocker and what would unblock them. Add discovered bugs, audit findings, validation gaps, and follow-up work in the correct priority position. Do not record progress in `AGENTS.md`.
24
+
25
+ When the specs, current code, and `IMPLEMENTATION_PLAN.md` have converged into a stable prioritized task list, print exactly:
26
+
27
+ RALPH_PLAN_COMPLETE
28
+
29
+ If more planning work remains, update `IMPLEMENTATION_PLAN.md` and exit without printing a completion sentinel so the outer loop can continue.
package/README.md ADDED
@@ -0,0 +1,247 @@
1
+ # OpenRalph
2
+
3
+ OpenRalph is a light opencode plugin/package that implements the Ralph workflow through TUI and CLI entrypoints:
4
+
5
+ - `/ralph`: the only public TUI slash command. It opens a Design, Plan, Build mode selector.
6
+ - `openralph plan [max] [--model <model>] [--no-docker]`: CLI/headless launcher for fresh planning iterations until `IMPLEMENTATION_PLAN.md` is stable.
7
+ - `openralph build [max] [--model <model>] [--push] [--no-docker]`: CLI/headless launcher for fresh build iterations, one task and one commit at a time.
8
+
9
+ ## Installation
10
+
11
+ OpenRalph is distributed as the npm package `@john-ezra/openralph`. OpenRalph itself stays Bun/TypeScript-native. Direct package execution through `bunx @john-ezra/openralph ...` or an installed `openralph` binary requires Bun.
12
+
13
+ The normal install path is opencode's built-in plugin installer:
14
+
15
+ 1. Open opencode in the target project.
16
+ 2. Run `Install plugin` from the command palette/plugins UI.
17
+ 3. Enter `@john-ezra/openralph` at the `npm package name` prompt.
18
+ 4. Leave scope as `local` for a project install, or press `Tab` to toggle to `global`.
19
+ 5. Restart opencode if needed.
20
+ 6. Run `/ralph`.
21
+
22
+ CLI equivalent for non-TUI users:
23
+
24
+ ```bash
25
+ opencode plugin @john-ezra/openralph
26
+ opencode plugin --global @john-ezra/openralph
27
+ ```
28
+
29
+ The opencode installer installs the npm package into opencode's plugin cache, detects both OpenRalph server and TUI targets, and patches the matching config files automatically. Local scope writes under `<worktree>/.opencode/` when run in a Git worktree; global scope writes under `~/.config/opencode/`.
30
+
31
+ ## Advanced Manual Config
32
+
33
+ Manual config is only needed when you want to bypass opencode's plugin installer or edit plugin options directly. Use `@john-ezra/openralph` for both server and TUI config; do not configure `@john-ezra/openralph/tui` as the plugin name.
34
+
35
+ Server plugin in `opencode.json`:
36
+
37
+ ```json
38
+ {
39
+ "$schema": "https://opencode.ai/config.json",
40
+ "plugin": [
41
+ [
42
+ "@john-ezra/openralph",
43
+ {
44
+ "defineModel": "provider/heavy-model",
45
+ "planModel": "provider/cheap-model",
46
+ "buildModel": "provider/cheap-model",
47
+ "docker": {
48
+ "enabled": true,
49
+ "image": "openralph:local",
50
+ "maskEnv": true
51
+ }
52
+ }
53
+ ]
54
+ ]
55
+ }
56
+ ```
57
+
58
+ TUI plugin in `tui.json`:
59
+
60
+ ```json
61
+ {
62
+ "$schema": "https://opencode.ai/tui.json",
63
+ "plugin": [
64
+ [
65
+ "@john-ezra/openralph",
66
+ {
67
+ "defineModel": "provider/heavy-model",
68
+ "planModel": "provider/cheap-model",
69
+ "buildModel": "provider/cheap-model",
70
+ "docker": {
71
+ "enabled": true,
72
+ "image": "openralph:local",
73
+ "maskEnv": true
74
+ }
75
+ }
76
+ ]
77
+ ]
78
+ }
79
+ ```
80
+
81
+ All model options are optional. Command `--model` values override plugin options. If no model is resolved, OpenRalph omits `--model` and lets opencode use its default.
82
+
83
+ Server and TUI plugin options use the same shape. Direct CLI/headless runs can pass the same launcher options through `OPENRALPH_OPTIONS_JSON`; without that env var, `openralph plan/build` uses default options, including Docker disabled.
84
+
85
+ ## Docker Mode
86
+
87
+ Docker mode is optional. When `docker.enabled` is true, Plan and Build from `/ralph`, `openralph plan`, and `openralph build` launch one Docker container from the host and run the full Ralph loop inside it through the container `openralph` CLI entrypoint. Docker uses `--pull=never`, so build the default image locally before running Dockerized loops.
88
+
89
+ If you installed through opencode's plugin installer, the package bin may not be available on your shell `PATH`. Build the image with direct package execution:
90
+
91
+ ```bash
92
+ bunx @john-ezra/openralph docker build
93
+ ```
94
+
95
+ If the `openralph` binary is already on `PATH`, such as from a global package install, AUR/Omarchy install, or local checkout, you can use:
96
+
97
+ ```bash
98
+ openralph docker build
99
+ ```
100
+
101
+ Use a custom tag for the default image if desired:
102
+
103
+ ```bash
104
+ bunx @john-ezra/openralph docker build --tag openralph:rust
105
+ ```
106
+
107
+ Projects can extend the local image with a small Dockerfile:
108
+
109
+ ```Dockerfile
110
+ FROM openralph:local
111
+
112
+ USER root
113
+
114
+ RUN apt-get update \
115
+ && apt-get install -y --no-install-recommends cargo rustc \
116
+ && rm -rf /var/lib/apt/lists/*
117
+
118
+ USER opencode
119
+ ```
120
+
121
+ Build it with Docker directly:
122
+
123
+ ```bash
124
+ docker build -f Dockerfile.openralph -t openralph:rust .
125
+ ```
126
+
127
+ Then point plugin options at that tag with `"docker": { "enabled": true, "image": "openralph:rust" }`.
128
+
129
+ The default image includes `opencode-ai@1.15.13`, Bun, Node 22, npm/npx/corepack, Git, Bash, curl, Python 3, native build tools, ripgrep, Google Chrome stable, screenshot-friendly fonts, and `chrome-devtools-mcp@1.1.1`.
130
+
131
+ Restart opencode after installing or changing `opencode.json`, `tui.json`, or plugin files. opencode loads plugin/config files only at startup.
132
+
133
+ ## Security Posture
134
+
135
+ OpenRalph Plan and Build child iterations run `opencode run --dangerously-skip-permissions`. Treat the agent's actions as untrusted.
136
+
137
+ Host mode runs those child iterations directly on your machine with inherited environment variables, host filesystem access, and unrestricted network access. Direct CLI/headless runs use host mode unless Docker is enabled through plugin options or `OPENRALPH_OPTIONS_JSON`.
138
+
139
+ Docker mode reduces host filesystem blast radius, but it is not a formal sandbox. The agent can read the mounted repository and the read-only mounted OpenCode auth file, and Docker mode does not restrict network egress. The `.env*` masking feature only replaces files whose basename starts with `.env`, except `.env.example`, `.env.sample`, `.env.template`, and `.env.dist`; it does not mask other in-repo secrets such as `.npmrc`, private keys, cloud credentials, or service-account JSON.
140
+
141
+ Docker mode mounts the repository read/write, including `.git`, because Build must create commits inside the container. OpenRalph disables hooks and fsmonitor for Git commands it runs on the host, but your own host-side Git commands may still honor agent-written hooks or Git config after a Docker run. Use a disposable clone or dedicated branch for autonomous Ralph runs, review changes before running host tools, and push manually only after review.
142
+
143
+ ## Local Development
144
+
145
+ For local development against this checkout, use relative file plugin specs instead of absolute machine paths:
146
+
147
+ ```json
148
+ {
149
+ "$schema": "https://opencode.ai/config.json",
150
+ "plugin": [["./src/plugin.ts", {}]]
151
+ }
152
+ ```
153
+
154
+ ```json
155
+ {
156
+ "$schema": "https://opencode.ai/tui.json",
157
+ "plugin": [["./src/tui.ts", {}]]
158
+ }
159
+ ```
160
+
161
+ ## Lean Project Setup
162
+
163
+ OpenRalph works best when the target project supplies a small set of clear disk artifacts:
164
+
165
+ - `specs/*`: behavioral requirements for Plan to compare against the codebase.
166
+ - `AGENTS.md`: operational contract only, especially build/test/lint/typecheck commands and important project conventions.
167
+ - `IMPLEMENTATION_PLAN.md`: prioritized mutable work queue maintained by Plan and Build.
168
+ - Validation backpressure: tests, typecheck, lint, and browser checks for UI work when practical.
169
+
170
+ Keep setup lean. If output is poor, improve validation or split plan items before expanding prompts or adding modes.
171
+
172
+ ## TUI Usage
173
+
174
+ Run `/ralph` from the opencode TUI to open the Ralph mode selector. Select Design, Plan, or Build with the arrow keys.
175
+
176
+ Design opens an optional idea prompt. If you leave it blank, Ralph starts by asking what you are working on. If you enter an idea, Ralph starts the current host session with a design prompt that guides ideation toward planning-ready `specs/*.md` artifacts.
177
+
178
+ Plan and Build open an args dialog after you choose them from the `/ralph` menu. The dialog collects the same loop args as the CLI entrypoints.
179
+
180
+ The dialog placeholder is only an example. For bounded smoke tests, enter `1`. Leaving the dialog empty uses the default unlimited loop, though Ralph may still stop after one iteration when it reports completion.
181
+
182
+ When Plan or Build starts, OpenRalph opens the output viewer automatically so you can inspect recent Docker/opencode output without streaming raw child output into the TUI renderer. While a loop is active, the output viewer asks for confirmation: Confirm or Esc closes only the viewer, while Cancel stops the active loop.
183
+
184
+ ## Run Artifacts
185
+
186
+ Plan and Build write durable project-local run artifacts under `runs/openralph-<phase>-YYYYMMDD-HHMMSS/`. OpenRalph creates `runs/.gitignore` so the artifacts stay out of normal Git status; you can also add `/runs/` to the target repo's tracked `.gitignore` if you want that ignore rule shared.
187
+
188
+ Typical shape:
189
+
190
+ ```text
191
+ runs/openralph-build-YYYYMMDD-HHMMSS/
192
+ ralph.log
193
+ iter-001.jsonl
194
+ iter-001.txt
195
+ ```
196
+
197
+ Artifacts are audit/debug output, not loop state. Fresh child iterations still rely on `specs/*`, `AGENTS.md`, `IMPLEMENTATION_PLAN.md`, and the static prompts.
198
+
199
+ Use artifacts as the backpressure audit trail. Review them for repeated failures, dangerous commands, unexpected sensitive path access, skipped validation, bad assumptions, or missing tests, then convert those findings into better tests, lint/typecheck rules, `AGENTS.md` operational notes, specs, or new `IMPLEMENTATION_PLAN.md` tasks.
200
+
201
+ Run artifacts may contain terminal output, command details, paths, and model text. Do not commit or share them blindly.
202
+
203
+ ## Runtime Notes
204
+
205
+ - Plan and Build require a Git worktree.
206
+ - `/ralph` is the only public TUI slash command. It selects Design, Plan, and Build. Design is a current-session requirements conversation; Plan and Build are external launcher loops.
207
+ - Public prompt-backed Ralph commands are stale. OpenRalph deletes stale `ralph-define`, `ralph-plan`, and `ralph-build` command config entries when the server plugin loads and throws if one is executed anyway.
208
+ - `/ralph-plan-iteration` and `/ralph-build-iteration` are internal prompt-backed commands and are exposed only to authorized loop child processes.
209
+ - `main` and `master` produce a warning but are not blocked.
210
+ - Docker mode disables project OpenCode config inside the container and injects config that loads only image-bundled OpenRalph for internal child commands.
211
+ - Docker mode is enforced with runtime attestation: the host passes a random token through env and a read-only token-file mount, and the container refuses to run the loop if the token/evidence check fails.
212
+ - Docker mode injects a `chrome-devtools` MCP server for browser validation. The MCP server uses `/opt/openralph/bin/chrome-devtools-mcp-wrapper`, which starts isolated headless Chrome on a loopback debugging port and connects via `--browser-url`.
213
+ - The default image uses a non-root `opencode` user when Docker cannot run as the host UID/GID.
214
+ - Docker mode mounts the repo read/write at `/workspace`, mounts host OpenCode auth read-only but readable by the agent, and masks real `.env*` files by default.
215
+ - `.env.example`, `.env.sample`, `.env.template`, and `.env.dist` remain visible in Docker mode.
216
+ - Docker mode does not restrict network egress.
217
+ - `.env*` masking is best-effort and does not cover other in-repo secret files such as `.npmrc`, private keys, cloud credentials, or service-account JSON.
218
+ - Docker mode does not mount host home, host OpenCode config, Git config, SSH keys, GPG material, browser profiles, browser cookies, desktop sockets, or the Docker socket.
219
+ - Dockerized OpenRalph Build requires host/project Git `user.name` and `user.email`. OpenRalph passes those values as author/committer env vars, disables commit/tag signing inside Docker, and rejects `--push` in Docker mode.
220
+ - Child iterations run `opencode run --dir <project-root> --command <internal-command> --dangerously-skip-permissions`.
221
+ - Docker mode runs `openralph plan` or `openralph build` inside the container. It never replays public prompt-backed Ralph commands.
222
+ - Child iterations never use `--continue`.
223
+ - Plan and Build persist project-local run artifacts under `runs/openralph-<phase>-YYYYMMDD-HHMMSS/` for audit/debug output.
224
+ - Ctrl+C is the manual stop mechanism.
225
+ - OpenRalph Build with `--push` pushes commits only in host mode. Docker mode rejects `--push`; review local commits on the host before pushing.
226
+ - Use `--no-docker` to intentionally run a loop on the host when Docker mode is enabled.
227
+ - Build tags are local lightweight tags shaped like `openralph/build-YYYYMMDD-HHMMSS/001`.
228
+ - Frontend or web UI build tasks should validate in a browser when practical, using the Docker-provided Chrome DevTools MCP tools for screenshots, console errors, desktop/mobile layout checks, and browser-visible issues.
229
+ - If a build task stalls repeatedly, stop the loop and split the plan item; retries are not a substitute for smaller tasks.
230
+
231
+ Use a dedicated branch or disposable clone for autonomous Ralph runs. Docker mode reduces host filesystem blast radius, but it is not a formal sandbox guarantee.
232
+
233
+ ## Verified Smoke Tests
234
+
235
+ The Docker/TUI migration was smoke-tested with `opencode-ai@1.15.13` using a disposable fixture repo.
236
+
237
+ - OpenRalph Plan selected from `/ralph` ran Docker with token attestation, produced `IMPLEMENTATION_PLAN.md`, and emitted `RALPH_PLAN_COMPLETE`.
238
+ - OpenRalph Build selected from `/ralph` with args `1` ran Docker with token attestation, implemented one greeting task, passed `npm test`, and created a commit in the fixture repo.
239
+ - Spoofed Docker markers and a direct container run without the mounted attestation token both failed before `runLoop()`.
240
+ - Build tags are created only when the worktree is clean after a successful build commit; an untracked local `tui.json` in the fixture correctly prevented tagging.
241
+
242
+ ## Development
243
+
244
+ ```bash
245
+ bun install
246
+ bun run validate
247
+ ```
package/bin/openralph ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ script_dir="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
5
+ exec bun "${script_dir}/../src/cli.ts" "$@"
package/bun.lock ADDED
@@ -0,0 +1,85 @@
1
+ {
2
+ "lockfileVersion": 1,
3
+ "configVersion": 1,
4
+ "workspaces": {
5
+ "": {
6
+ "name": "@john-ezra/openralph",
7
+ "devDependencies": {
8
+ "@opencode-ai/plugin": "1.15.13",
9
+ "@types/bun": "latest",
10
+ "typescript": "latest",
11
+ },
12
+ },
13
+ },
14
+ "packages": {
15
+ "@msgpackr-extract/msgpackr-extract-darwin-arm64": ["@msgpackr-extract/msgpackr-extract-darwin-arm64@3.0.4", "", { "os": "darwin", "cpu": "arm64" }, "sha512-LCkGo6JDfaBhgST7UpPWgNgLINpcpabaHfyz5OBx75nUYxBsaEPxjnyNjWpeb/xBup/682QnBfRBy2/LvPutZQ=="],
16
+
17
+ "@msgpackr-extract/msgpackr-extract-darwin-x64": ["@msgpackr-extract/msgpackr-extract-darwin-x64@3.0.4", "", { "os": "darwin", "cpu": "x64" }, "sha512-zExlW9zUJKZH/tOtVMttwjKa4Xm/3KcNjnE3dPN92uCktwavMxpgCA3MoJK/DOnTWsQgo224OaST27/mPNAf+w=="],
18
+
19
+ "@msgpackr-extract/msgpackr-extract-linux-arm": ["@msgpackr-extract/msgpackr-extract-linux-arm@3.0.4", "", { "os": "linux", "cpu": "arm" }, "sha512-Tg3yX65f5GbtXLkrYEHE5oibZG9epyYWas7FogTTEJeDEF9JlXJzKgXaNhT3UXlTOeA+AfZpYZYZ0uPj7Cfquw=="],
20
+
21
+ "@msgpackr-extract/msgpackr-extract-linux-arm64": ["@msgpackr-extract/msgpackr-extract-linux-arm64@3.0.4", "", { "os": "linux", "cpu": "arm64" }, "sha512-dgX0P/9wGPJeHFBG+ZmhgE6bmtMt7NP5CRBGyyktpopdk/mW4POnrpQsSLtKI1dwpc+pPLuXHDh6vvskyQE/sw=="],
22
+
23
+ "@msgpackr-extract/msgpackr-extract-linux-x64": ["@msgpackr-extract/msgpackr-extract-linux-x64@3.0.4", "", { "os": "linux", "cpu": "x64" }, "sha512-8TNXMEjJc3QEy7R/x1INhgiU+XakDAFUzBhaz7+Rbrs8NH5UQeHQxxmzsSBJGyV6I1jW79undiQm8tOI+D+8FQ=="],
24
+
25
+ "@msgpackr-extract/msgpackr-extract-win32-x64": ["@msgpackr-extract/msgpackr-extract-win32-x64@3.0.4", "", { "os": "win32", "cpu": "x64" }, "sha512-CmCXPQrkbwExx3j946/PtHWHbYJiCRBRDl4BlkRQcJB/YOwQxJRTpoo7aTsortjgoJ1x7opzTSxn7C+ASSLVjQ=="],
26
+
27
+ "@opencode-ai/plugin": ["@opencode-ai/plugin@1.15.13", "", { "dependencies": { "@opencode-ai/sdk": "1.15.13", "effect": "4.0.0-beta.66", "zod": "4.1.8" }, "peerDependencies": { "@opentui/core": ">=0.2.16", "@opentui/keymap": ">=0.2.16", "@opentui/solid": ">=0.2.16" }, "optionalPeers": ["@opentui/core", "@opentui/keymap", "@opentui/solid"] }, "sha512-NFwZGhmxIPijtfz9swPJXDmhOpq4UWP8WjEE7GEMr7FwtJrK/hv6v36nFimed5+OKk+pQCrTJn/vhRW7Io72IA=="],
28
+
29
+ "@opencode-ai/sdk": ["@opencode-ai/sdk@1.15.13", "", { "dependencies": { "cross-spawn": "7.0.6" } }, "sha512-4TwojIoQ8EG6/mVBuUVYZXiFcwNmiiytEnjnvyuvSJjGwFIlw2YIBFxtSVC3FbwwbwHT63teh1RHiQUUC4U5xw=="],
30
+
31
+ "@standard-schema/spec": ["@standard-schema/spec@1.1.0", "", {}, "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="],
32
+
33
+ "@types/bun": ["@types/bun@1.3.14", "", { "dependencies": { "bun-types": "1.3.14" } }, "sha512-h1hFqFVcvAvD9j9K7ZW7vd82aSA+rTdznZa+5bwvCwqSB1jmmfLcbIWhOLx1/+boy/xmjgCs/OMUL8hRJSmnPw=="],
34
+
35
+ "@types/node": ["@types/node@25.9.1", "", { "dependencies": { "undici-types": ">=7.24.0 <7.24.7" } }, "sha512-xfrlY7UD5rMJk3ZVJP8BNzS28J36YJg+xp+LPXV1TdWxr8uMH5A860QNxYDGQe/ylDSgjxE52Q9VnO7p75tJxg=="],
36
+
37
+ "bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="],
38
+
39
+ "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
40
+
41
+ "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="],
42
+
43
+ "effect": ["effect@4.0.0-beta.66", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.6.0", "find-my-way-ts": "^0.1.6", "ini": "^6.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^1.11.9", "multipasta": "^0.2.7", "toml": "^4.1.1", "uuid": "^13.0.0", "yaml": "^2.8.3" } }, "sha512-4arEr62cziFa8BBVDUwJCJJmaVepXf/kRg7KtC0h8+bufngscrHbwWFhr9c+HonwOF+31U3iD3xUJmw9KzX7Dw=="],
44
+
45
+ "fast-check": ["fast-check@4.8.0", "", { "dependencies": { "pure-rand": "^8.0.0" } }, "sha512-GOJ158CUMnN6cSahsv4+ExARvIDuzzinFjkp0E9WtiBa5zcVeLozVkWaE4IzFcc+Y48Wp1EDlUZsXRyAztQcSg=="],
46
+
47
+ "find-my-way-ts": ["find-my-way-ts@0.1.6", "", {}, "sha512-a85L9ZoXtNAey3Y6Z+eBWW658kO/MwR7zIafkIUPUMf3isZG0NCs2pjW2wtjxAKuJPxMAsHUIP4ZPGv0o5gyTA=="],
48
+
49
+ "ini": ["ini@6.0.0", "", {}, "sha512-IBTdIkzZNOpqm7q3dRqJvMaldXjDHWkEDfrwGEQTs5eaQMWV+djAhR+wahyNNMAa+qpbDUhBMVt4ZKNwpPm7xQ=="],
50
+
51
+ "isexe": ["isexe@2.0.0", "", {}, "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="],
52
+
53
+ "kubernetes-types": ["kubernetes-types@1.30.0", "", {}, "sha512-Dew1okvhM/SQcIa2rcgujNndZwU8VnSapDgdxlYoB84ZlpAD43U6KLAFqYo17ykSFGHNPrg0qry0bP+GJd9v7Q=="],
54
+
55
+ "msgpackr": ["msgpackr@1.11.12", "", { "optionalDependencies": { "msgpackr-extract": "^3.0.2" } }, "sha512-RBdJ1Un7yGlXWajrkxcSa93nvQ0w4zBf60c0yYv7YtBelP8H2FA7XsfBbMHtXKXUMUxH7zV3Zuozh+kUQWhHvg=="],
56
+
57
+ "msgpackr-extract": ["msgpackr-extract@3.0.4", "", { "dependencies": { "node-gyp-build-optional-packages": "5.2.2" }, "optionalDependencies": { "@msgpackr-extract/msgpackr-extract-darwin-arm64": "3.0.4", "@msgpackr-extract/msgpackr-extract-darwin-x64": "3.0.4", "@msgpackr-extract/msgpackr-extract-linux-arm": "3.0.4", "@msgpackr-extract/msgpackr-extract-linux-arm64": "3.0.4", "@msgpackr-extract/msgpackr-extract-linux-x64": "3.0.4", "@msgpackr-extract/msgpackr-extract-win32-x64": "3.0.4" }, "bin": { "download-msgpackr-prebuilds": "bin/download-prebuilds.js" } }, "sha512-4kmO/MdyUIkLIvTPr8VHLil4AtoKIoniWPIEk5+CDy0xnWC84azhSFmuJ7PxZdsYtiP5kEeQsORAVIeMgxT+Hw=="],
58
+
59
+ "multipasta": ["multipasta@0.2.7", "", {}, "sha512-KPA58d68KgGil15oDqXjkUBEBYc00XvbPj5/X+dyzeo/lWm9Nc25pQRlf1D+gv4OpK7NM0J1odrbu9JNNGvynA=="],
60
+
61
+ "node-gyp-build-optional-packages": ["node-gyp-build-optional-packages@5.2.2", "", { "dependencies": { "detect-libc": "^2.0.1" }, "bin": { "node-gyp-build-optional-packages": "bin.js", "node-gyp-build-optional-packages-optional": "optional.js", "node-gyp-build-optional-packages-test": "build-test.js" } }, "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw=="],
62
+
63
+ "path-key": ["path-key@3.1.1", "", {}, "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q=="],
64
+
65
+ "pure-rand": ["pure-rand@8.4.0", "", {}, "sha512-IoM8YF/jY0hiugFo/wOWqfmarlE6J0wc6fDK1PhftMk7MGhVZl88sZimmqBBFomLOCSmcCCpsfj7wXASCpvK9A=="],
66
+
67
+ "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="],
68
+
69
+ "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="],
70
+
71
+ "toml": ["toml@4.1.1", "", {}, "sha512-EBJnVBr3dTXdA89WVFoAIPUqkBjxPMwRqsfuo1r240tKFHXv3zgca4+NJib/h6TyvGF7vOawz0jGuryJCdNHrw=="],
72
+
73
+ "typescript": ["typescript@6.0.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-y2TvuxSZPDyQakkFRPZHKFm+KKVqIisdg9/CZwm9ftvKXLP8NRWj38/ODjNbr43SsoXqNuAisEf1GdCxqWcdBw=="],
74
+
75
+ "undici-types": ["undici-types@7.24.6", "", {}, "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg=="],
76
+
77
+ "uuid": ["uuid@13.0.2", "", { "bin": { "uuid": "dist-node/bin/uuid" } }, "sha512-vzi9uRZ926x4XV73S/4qQaTwPXM2JBj6/6lI/byHH1jOpCzb0zDbfytgA9LcN/hzb2l7WQSQnxITOVx5un/wGw=="],
78
+
79
+ "which": ["which@2.0.2", "", { "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "./bin/node-which" } }, "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA=="],
80
+
81
+ "yaml": ["yaml@2.9.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA=="],
82
+
83
+ "zod": ["zod@4.1.8", "", {}, "sha512-5R1P+WwQqmmMIEACyzSvo4JXHY5WiAFHRMg+zBZKgKS+Q1viRa0C1hmUKtHltoIFKtIdki3pRxkmpP74jnNYHQ=="],
84
+ }
85
+ }