Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- Added a `pi` provider for routing review, fix, revalidate, and agent map through the [pi coding agent](https://pi.dev) in non-interactive print mode, thanks @danielmarbach.
- Added explicit Codex reasoning effort selection via `--reasoning-effort`, `CLAWPATCH_REASONING_EFFORT`, and provider config, with `doctor` reporting the active setting.
- Added `--skip-git-repo-check` for Codex-backed map, review, fix, and revalidate commands so initialized non-Git roots can run Codex, thanks @im-zayan.
- Added `CLAWPATCH_CODEX_SANDBOX` for overriding Codex provider sandbox mode when the host already provides isolation, thanks @IAMSamuelRodda.
- Added deterministic Express, Fastify, and Hono route mapping for Node projects, thanks @rohitjavvadi.
- Fixed provider commands with relative `--root` paths by canonicalizing explicit roots before invoking Codex or other providers.
- Added first-pass Elixir Mix/Phoenix mapping for project metadata, contexts, Phoenix web slices, runtime config, Ecto migrations, project scripts, ExUnit tests, and Mix validation defaults, thanks @tears-mysthrala.
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,11 @@ Provider calls use `codex exec` with strict JSON schemas. Review and revalidate
run read-only; fix planning runs with workspace-write because Codex may edit the
working tree during the explicit fix command.

Set `CLAWPATCH_CODEX_SANDBOX` to override the Codex sandbox passed by
Clawpatch. Use any Codex sandbox mode, or `bypass`/`none` to pass
`--dangerously-bypass-approvals-and-sandbox` when the host environment already
provides isolation.

Supported provider names today:

- `codex`: local Codex CLI
Expand Down
49 changes: 48 additions & 1 deletion src/provider.test.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { describe, expect, it } from "vitest";
import { afterEach, describe, expect, it } from "vitest";
import { ClawpatchError } from "./errors.js";
import { __testing, extractJson, providerByName } from "./provider.js";
import { reviewOutputSchema } from "./types.js";

// eslint-disable-next-line no-underscore-dangle
const {
addCodexSandboxArgs,
addCodexModelArgs,
acpxFailureMessage,
extractAcpxJson,
Expand Down Expand Up @@ -127,6 +128,52 @@ describe("parseCodexJson", () => {
});

describe("Codex provider args", () => {
const originalCodexSandbox = process.env["CLAWPATCH_CODEX_SANDBOX"];

afterEach(() => {
if (originalCodexSandbox === undefined) {
delete process.env["CLAWPATCH_CODEX_SANDBOX"];
} else {
process.env["CLAWPATCH_CODEX_SANDBOX"] = originalCodexSandbox;
}
});

it("uses the requested Codex sandbox by default", () => {
delete process.env["CLAWPATCH_CODEX_SANDBOX"];
const args = ["exec"];

addCodexSandboxArgs(args, "read-only");

expect(args).toEqual(["exec", "--sandbox", "read-only"]);
});

it("allows Codex sandbox mode to be overridden by environment", () => {
process.env["CLAWPATCH_CODEX_SANDBOX"] = " danger-full-access ";
const args = ["exec"];

addCodexSandboxArgs(args, "read-only");

expect(args).toEqual(["exec", "--sandbox", "danger-full-access"]);
});

it("ignores blank Codex sandbox overrides", () => {
process.env["CLAWPATCH_CODEX_SANDBOX"] = " ";
const args = ["exec"];

addCodexSandboxArgs(args, "read-only");

expect(args).toEqual(["exec", "--sandbox", "read-only"]);
});

it("can bypass Codex sandboxing when the host already provides isolation", () => {
process.env["CLAWPATCH_CODEX_SANDBOX"] = " none ";
const args = ["exec"];

addCodexSandboxArgs(args, "read-only");

expect(args).toEqual(["exec", "--dangerously-bypass-approvals-and-sandbox"]);
});

it("passes model and reasoning effort through explicit CLI config", () => {
const args = ["exec"];

Expand Down
13 changes: 11 additions & 2 deletions src/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -452,13 +452,12 @@ async function runCodexJson(
"exec",
"--cd",
root,
"--sandbox",
sandbox,
"--output-schema",
schemaPath,
"--output-last-message",
outputPath,
];
addCodexSandboxArgs(args, sandbox);
addCodexModelArgs(args, options);
args.push("-");
const result = await runCommandArgs("codex", args, root, prompt);
Expand All @@ -479,6 +478,15 @@ async function runCodexJson(
}
}

function addCodexSandboxArgs(args: string[], sandbox: string): void {
const override = process.env["CLAWPATCH_CODEX_SANDBOX"]?.trim();
if (override === "bypass" || override === "none") {
args.push("--dangerously-bypass-approvals-and-sandbox");
return;
}
args.push("--sandbox", override && override.length > 0 ? override : sandbox);
}

function addCodexModelArgs(args: string[], options: ProviderOptions): void {
if (options.skipGitRepoCheck) {
args.push("--skip-git-repo-check");
Expand Down Expand Up @@ -974,6 +982,7 @@ function acpxTimeoutMs(): number {
export const __testing = {
acpxFailureMessage,
addCodexModelArgs,
addCodexSandboxArgs,
extractAcpxJson,
extractOpencodeJson,
parseAcpxAgent,
Expand Down