@john-ezra/openralph 0.1.1 → 0.1.2

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/AGENTS.md CHANGED
@@ -8,7 +8,7 @@ OpenRalph is a light opencode plugin that implements the Ralph workflow from Cla
8
8
  - Preserve Ralph's central mechanism: one fresh top-level opencode run per loop iteration.
9
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
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.
11
+ - Safety strategy is the user's responsibility. OpenRalph provides only lightweight guardrails and default Dockerized loop execution with explicit host-mode opt-out.
12
12
  - Avoid complex modes, safety matrices, Podman requirements, or heavy process abstractions.
13
13
 
14
14
  ## Ralph Phases
@@ -38,7 +38,7 @@ The server plugin should inject these commands only for authorized loop child pr
38
38
  - Never use `--continue` for child runs.
39
39
  - Always pass `--dir <project-root>` to child runs.
40
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.
41
+ - Docker mode is enabled by default; host plan/build commands launch one Docker container and the full loop runs inside it unless `--no-docker` or `docker.enabled: false` is used.
42
42
  - Docker mode runs the container `openralph plan` or `openralph build` CLI entrypoint, never public prompt command replay.
43
43
  - Container loops set `OPENRALPH_IN_DOCKER=1` and require token-backed Docker attestation before running.
44
44
  - Docker mode disables project OpenCode config and injects config that loads only image-bundled OpenRalph.
@@ -71,9 +71,9 @@ Plugin options:
71
71
 
72
72
  ```json
73
73
  {
74
- "defineModel": "heavy-model",
75
- "planModel": "cheap-model",
76
- "buildModel": "cheap-model",
74
+ "defineModel": "provider/heavy-model",
75
+ "planModel": "provider/cheap-model",
76
+ "buildModel": "provider/cheap-model",
77
77
  "docker": {
78
78
  "enabled": true,
79
79
  "image": "openralph:local",
@@ -112,7 +112,7 @@ Use tags only after a successful build iteration with a new commit and clean wor
112
112
 
113
113
  ## Safety Posture
114
114
 
115
- OpenRalph v1 supports optional Dockerized execution for Plan and Build.
115
+ OpenRalph v1 defaults to Dockerized execution for Plan and Build, with explicit host-mode opt-out.
116
116
 
117
117
  Rationale:
118
118
 
package/CHANGELOG.md CHANGED
@@ -4,6 +4,25 @@ All notable changes to OpenRalph will be documented in this file.
4
4
 
5
5
  The format is based on Keep a Changelog, and this project uses semantic versioning.
6
6
 
7
+ ## [Unreleased]
8
+
9
+ ## [0.1.2] - 2026-06-04
10
+
11
+ ### Changed
12
+
13
+ - Docker mode is now the default for Plan and Build; host mode requires `--no-docker` or `docker.enabled: false`.
14
+ - Missing default Docker images now fail before container launch with build and host-mode opt-out guidance.
15
+
16
+ ### Fixed
17
+
18
+ - Normalized the CLI bin path so npm preserves the `openralph` executable during publish.
19
+
20
+ ## [0.1.1] - 2026-06-04
21
+
22
+ ### Fixed
23
+
24
+ - Kept opencode plugin type definitions out of runtime dependencies.
25
+
7
26
  ## [0.1.0] - 2026-06-04
8
27
 
9
28
  ### Added
package/README.md CHANGED
@@ -16,8 +16,9 @@ The normal install path is opencode's built-in plugin installer:
16
16
  2. Run `Install plugin` from the command palette/plugins UI.
17
17
  3. Enter `@john-ezra/openralph` at the `npm package name` prompt.
18
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`.
19
+ 5. Build the default Docker image with `bunx @john-ezra/openralph docker build`.
20
+ 6. Restart opencode if needed.
21
+ 7. Run `/ralph`.
21
22
 
22
23
  CLI equivalent for non-TUI users:
23
24
 
@@ -80,11 +81,11 @@ TUI plugin in `tui.json`:
80
81
 
81
82
  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
 
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
+ 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 enabled with image `openralph:local` and `.env*` masking enabled.
84
85
 
85
86
  ## Docker Mode
86
87
 
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
+ Docker mode is the default for Plan and Build. 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. To intentionally run on the host, pass `--no-docker` for that run or set `"docker": { "enabled": false }` in plugin options.
88
89
 
89
90
  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
 
@@ -134,7 +135,7 @@ Restart opencode after installing or changing `opencode.json`, `tui.json`, or pl
134
135
 
135
136
  OpenRalph Plan and Build child iterations run `opencode run --dangerously-skip-permissions`. Treat the agent's actions as untrusted.
136
137
 
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
+ Host mode runs those child iterations directly on your machine with inherited environment variables, host filesystem access, and unrestricted network access. Use `--no-docker` or `"docker": { "enabled": false }` only when you intentionally want that behavior.
138
139
 
139
140
  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
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@john-ezra/openralph",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "type": "module",
5
5
  "description": "Light opencode plugin for the Ralph workflow.",
6
6
  "license": "MIT",
@@ -13,7 +13,7 @@
13
13
  "./package.json": "./package.json"
14
14
  },
15
15
  "bin": {
16
- "openralph": "./bin/openralph"
16
+ "openralph": "bin/openralph"
17
17
  },
18
18
  "engines": {
19
19
  "bun": ">=1.2.0"
package/src/args.ts CHANGED
@@ -112,7 +112,7 @@ export function formatLoopArgsForReplay(args: ParsedLoopArgs): string {
112
112
 
113
113
  export function resolveDockerOptions(options: OpenRalphOptions): ResolvedDockerOptions {
114
114
  return {
115
- enabled: options.docker?.enabled ?? false,
115
+ enabled: options.docker?.enabled ?? true,
116
116
  image: options.docker?.image ?? DEFAULT_DOCKER_IMAGE,
117
117
  maskEnv: options.docker?.maskEnv ?? true,
118
118
  }
package/src/docker.ts CHANGED
@@ -187,6 +187,15 @@ export async function buildLocalDockerImage(input: BuildLocalDockerImageInput =
187
187
  }).result
188
188
  }
189
189
 
190
+ export async function dockerImageExists(image: string, cwd = process.cwd()): Promise<boolean> {
191
+ const result = await startCommand("docker", ["image", "inspect", image], {
192
+ cwd,
193
+ streamOutput: false,
194
+ captureOutput: false,
195
+ }).result
196
+ return result.exitCode === 0
197
+ }
198
+
190
199
  export function buildDockerArgs(input: BuildDockerArgsInput): string[] {
191
200
  const configContent = buildContainerConfig(input.options, input.docker, input.imagePluginPath)
192
201
  const args = [
package/src/launcher.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { formatLoopArgsForReplay, parseLoopArgs, resolveDockerOptions, validateOptions, type LoopPhase, type OpenRalphOptions, type ParsedLoopArgs } from "./args.ts"
2
- import { CONTAINER_WORKSPACE, runDockerLoop } from "./docker.ts"
2
+ import { CONTAINER_WORKSPACE, dockerImageExists as defaultDockerImageExists, runDockerLoop } from "./docker.ts"
3
3
  import { commandExists as defaultCommandExists, type CommandOutputEvent, type CommandResult } from "./exec.ts"
4
4
  import { requireGitContext } from "./git.ts"
5
5
  import { formatSummary, runLoop, type LoopSummary } from "./loop.ts"
@@ -32,6 +32,7 @@ export interface RunLauncherDeps {
32
32
  runDockerLoop?: typeof runDockerLoop
33
33
  runLoop?: typeof runLoop
34
34
  commandExists?: typeof defaultCommandExists
35
+ dockerImageExists?: typeof defaultDockerImageExists
35
36
  trust?: TrustDeps
36
37
  }
37
38
 
@@ -55,6 +56,10 @@ export async function runOpenRalphLauncher(input: RunLauncherInput, deps: RunLau
55
56
  await preflightCommands(mode, deps.commandExists ?? defaultCommandExists)
56
57
 
57
58
  if (mode === "docker-host-launch") {
59
+ const docker = resolveDockerOptions(input.options)
60
+ const imageExists = await (deps.dockerImageExists ?? defaultDockerImageExists)(docker.image, input.cwd)
61
+ if (!imageExists) throw new Error(formatMissingDockerImage(input.phase, parsed, docker.image))
62
+
58
63
  const git = await (deps.requireGitContext ?? requireGitContext)(input.cwd)
59
64
  const result = await (deps.runDockerLoop ?? runDockerLoop)({
60
65
  phase: input.phase,
@@ -192,7 +197,7 @@ function formatMissingCommands(commands: string[]): string {
192
197
  const hints: Record<string, string> = {
193
198
  git: "Install git and ensure it is on PATH.",
194
199
  opencode: "Install opencode (https://opencode.ai) and ensure it is on PATH.",
195
- docker: "Install Docker and ensure the docker executable is on PATH.",
200
+ docker: "Install Docker and ensure the docker executable is on PATH, or run this loop with --no-docker to opt into host mode.",
196
201
  }
197
202
 
198
203
  return [
@@ -201,9 +206,22 @@ function formatMissingCommands(commands: string[]): string {
201
206
  ].join("\n")
202
207
  }
203
208
 
209
+ function formatMissingDockerImage(phase: LoopPhase, parsed: ParsedLoopArgs, image: string): string {
210
+ return [
211
+ `Docker image ${image} was not found.`,
212
+ "",
213
+ "OpenRalph defaults to Docker mode for safer loop execution and Docker runs with --pull=never.",
214
+ "Build the local image with:",
215
+ " bunx @john-ezra/openralph docker build",
216
+ "",
217
+ "If you intentionally want to run this loop on the host, rerun with:",
218
+ ` ${noDockerCommand(phase, parsed)}`,
219
+ ].join("\n")
220
+ }
221
+
204
222
  function noDockerCommand(phase: LoopPhase, parsed: ParsedLoopArgs): string {
205
223
  const replayArgs = formatLoopArgsForReplay(parsed)
206
- return `/ralph-${phase}${replayArgs ? ` ${replayArgs}` : ""} --no-docker`
224
+ return `openralph ${phase}${replayArgs ? ` ${replayArgs}` : ""} --no-docker`
207
225
  }
208
226
 
209
227
  function commandOutput(result: CommandResult): string {