Skip to content

Commit 6440741

Browse files
committed
Add explicit Codex full-access mode
1 parent 308682a commit 6440741

10 files changed

Lines changed: 211 additions & 21 deletions

File tree

.claude-plugin/plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "codex-subagents",
33
"version": "0.1.0",
4-
"description": "Launch OpenAI Codex agents, Spark agents, and parallel Codex subagents from Claude Code through a daemonless read-only MCP server.",
4+
"description": "Launch OpenAI Codex agents, Spark agents, and parallel Codex subagents from Claude Code through a daemonless MCP server with read-only defaults and explicit full-access mode.",
55
"author": {
66
"name": "xuio"
77
},

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@
44

55
- Initial Claude Code plugin for launching Codex agents through a daemonless stdio MCP server.
66
- Added read-only defaults, non-interactive approvals, Codex desktop binary resolution, and per-call `project_dir`.
7+
- Added explicit full-access mode via `dangerously_bypass_approvals_and_sandbox`.
78
- Added single-agent, parallel-agent, Spark preset, and nested Codex subagent support.
89
- Added unit, MCP smoke, reliability, runtime, desktop Claude Code, and opt-in live Claude/Codex validation scripts.

README.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@
44

55
Claude Code plugin that exposes OpenAI Codex agents through a daemonless stdio MCP server.
66

7-
The plugin lets Claude Code launch one Codex agent or several Codex agents in parallel. It is designed for read-only delegation by default: codebase exploration, review, planning, risk checks, documentation mapping, and other sidecar work where Claude should collect independent Codex results without giving those agents write access.
7+
The plugin lets Claude Code launch one Codex agent or several Codex agents in parallel. It is designed for read-only delegation by default: codebase exploration, review, planning, risk checks, documentation mapping, and other sidecar work where Claude should collect independent Codex results without giving those agents write access. When explicitly requested, Claude can also launch Codex with the same full local capabilities as normal non-sandbox Codex.
88

99
## Defaults
1010

1111
- Codex binary: prefers `/Applications/Codex.app/Contents/Resources/codex` when the Codex desktop app is installed, then falls back to configured overrides and `codex` on `PATH`.
1212
- Sandbox: `read-only`.
1313
- Approvals: non-interactive `approval_policy="never"`.
14+
- Full local access: opt in per call with `dangerously_bypass_approvals_and_sandbox: true`, which maps to Codex's `--dangerously-bypass-approvals-and-sandbox` flag and allows DNS/network access plus unrestricted file and git writes.
1415
- Service tier: omitted by default so Codex uses its normal account/default service tier. Pass `service_tier` only when you explicitly want one.
1516
- Transport: stdio MCP, launched by Claude Code for the active session. No daemon is required.
1617
- Prompt delivery: stdin, not command-line arguments.
@@ -45,6 +46,18 @@ To let a Codex agent spawn its own Codex subagents, pass:
4546

4647
Custom subagents are passed to Codex as `agents.<name>...` config overrides and also materialized in a temporary Codex home for the duration of one run. The target project is not modified, and the default sandbox remains `read-only`.
4748

49+
## Full Access Mode
50+
51+
By default, all tools run Codex with `--sandbox read-only`. If the user explicitly asks Codex to edit files, use network/DNS, run git writes, install packages, or otherwise behave like an unrestricted local Codex run, pass:
52+
53+
```json
54+
{
55+
"dangerously_bypass_approvals_and_sandbox": true
56+
}
57+
```
58+
59+
This uses Codex's `--dangerously-bypass-approvals-and-sandbox` flag. It bypasses all sandboxing and approval prompts for that Codex process, so keep it request-scoped and do not set it as a default.
60+
4861
## Structured Output And MCP Config
4962

5063
Pass `output_contract` when Claude needs machine-readable Codex results:
@@ -136,7 +149,7 @@ After startup, ask Claude to use Codex subagents, or invoke the plugin skill:
136149

137150
`codex_doctor` runs installation and safety diagnostics without invoking a model.
138151

139-
Each agent accepts model, reasoning effort, sandbox, project directory, timeout, isolated Codex home, and output-size controls. Pass `project_dir` when Claude Code wants Codex to inspect the same repository or subdirectory Claude is currently working in. If `project_dir` is omitted, the server uses `CLAUDE_PROJECT_DIR` when Claude Code provides it. Omit model to use Codex's configured default or the plugin's optional configured default model.
152+
Each agent accepts model, reasoning effort, sandbox, full-access bypass, project directory, timeout, isolated Codex home, and output-size controls. Pass `project_dir` when Claude Code wants Codex to inspect the same repository or subdirectory Claude is currently working in. If `project_dir` is omitted, the server uses `CLAUDE_PROJECT_DIR` when Claude Code provides it. Omit model to use Codex's configured default or the plugin's optional configured default model.
140153

141154
Prefer `start_agent_run` or `start_agents_run` for work that may run longer than a normal MCP request. The async job API keeps Claude responsive, supports cancellation, and avoids request failures caused by long-running Codex subprocesses.
142155

SECURITY.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ This plugin launches Codex from Claude Code through a local stdio MCP server. Th
77
- Prompts are sent over stdin instead of command-line arguments.
88
- Custom nested subagents are written to a temporary Codex home and cleaned up after the run.
99

10+
Full local access is available only when a tool call explicitly sets `dangerously_bypass_approvals_and_sandbox: true`. That passes Codex's `--dangerously-bypass-approvals-and-sandbox` flag, bypassing all sandboxing and approval prompts for that process. Do not enable it for routine review or exploration.
11+
1012
## Reporting A Vulnerability
1113

1214
Please report security issues through GitHub Security Advisories for this repository. If advisories are not available, open an issue with a minimal description and avoid posting secrets, tokens, private logs, or sensitive project contents.

dist/index.js

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21720,6 +21720,7 @@ function tomlString(value) {
2172021720
function buildCodexExecArgs(options, outputPath, env = process.env) {
2172121721
const { model, reasoningEffort, reasoningSummary } = validateRunConfiguration(options, env);
2172221722
const sandbox = options.sandbox ?? "read-only";
21723+
const bypassSandbox = options.dangerouslyBypassApprovalsAndSandbox ?? false;
2172321724
const ephemeral = options.ephemeral ?? true;
2172421725
const resume = Boolean(options.resumeSessionId || options.resumeLast);
2172521726
const args = resume ? [
@@ -21737,15 +21738,18 @@ function buildCodexExecArgs(options, outputPath, env = process.env) {
2173721738
"--json",
2173821739
"--color",
2173921740
"never",
21740-
"--sandbox",
21741-
sandbox,
2174221741
"-c",
2174321742
`approval_policy=${tomlString("never")}`,
2174421743
"-c",
2174521744
`model_reasoning_effort=${tomlString(reasoningEffort)}`,
2174621745
"--output-last-message",
2174721746
outputPath
2174821747
];
21748+
if (bypassSandbox) {
21749+
args.push("--dangerously-bypass-approvals-and-sandbox");
21750+
} else if (!resume) {
21751+
args.push("--sandbox", sandbox);
21752+
}
2174921753
if (model) args.push("--model", model);
2175021754
if (!resume && options.profile) args.push("--profile", options.profile);
2175121755
if (!resume && options.cwd) args.push("--cd", options.cwd);
@@ -21795,6 +21799,9 @@ function validationFailureResult(options) {
2179521799
modelPreset: options.runOptions.modelPreset,
2179621800
reasoningEffort,
2179721801
sandbox: options.runOptions.sandbox ?? "read-only",
21802+
dangerouslyBypassApprovalsAndSandbox: Boolean(
21803+
options.runOptions.dangerouslyBypassApprovalsAndSandbox
21804+
),
2179821805
serviceTier: options.runOptions.serviceTier,
2179921806
exitCode: null,
2180021807
signal: null,
@@ -21833,6 +21840,9 @@ function baseFailureResult(options) {
2183321840
modelPreset: options.runOptions.modelPreset,
2183421841
reasoningEffort: options.runOptions.reasoningEffort ?? defaultReasoningEffort(options.env),
2183521842
sandbox: options.runOptions.sandbox ?? "read-only",
21843+
dangerouslyBypassApprovalsAndSandbox: Boolean(
21844+
options.runOptions.dangerouslyBypassApprovalsAndSandbox
21845+
),
2183621846
serviceTier: options.runOptions.serviceTier,
2183721847
exitCode: options.exitCode ?? null,
2183821848
signal: options.signal ?? null,
@@ -22132,6 +22142,9 @@ async function runAgent(options) {
2213222142
modelPreset: options.modelPreset,
2213322143
reasoningEffort: options.reasoningEffort ?? defaultReasoningEffort(childEnv),
2213422144
sandbox: options.sandbox ?? "read-only",
22145+
dangerouslyBypassApprovalsAndSandbox: Boolean(
22146+
options.dangerouslyBypassApprovalsAndSandbox
22147+
),
2213522148
serviceTier: options.serviceTier,
2213622149
exitCode,
2213722150
signal,
@@ -22672,6 +22685,7 @@ var usageGuide = [
2267222685
"",
2267322686
"Default operating rules:",
2267422687
"- Keep sandbox read-only unless the user explicitly asks for a different sandbox.",
22688+
"- If the user explicitly asks for non-sandbox/full local capabilities, set dangerously_bypass_approvals_and_sandbox true. This maps to Codex's --dangerously-bypass-approvals-and-sandbox flag and allows DNS/network plus unrestricted file and git writes.",
2267522689
"- Approvals are non-interactive; do not expect Codex to ask permission.",
2267622690
'- Prefer model_preset "spark" for responsive focused checks, small reviews, UI iteration, and sidecar analysis.',
2267722691
'- Use reasoning_effort "medium" by default, "low" for simple checks, and "high" or "xhigh" only for difficult analysis. Do not use "minimal"; Codex currently auto-attaches web_search and the API rejects that tool with minimal reasoning.',
@@ -22739,6 +22753,9 @@ var commonInputSchema = {
2273922753
"Codex model reasoning effort. Prefer medium by default, low for simple checks, high/xhigh only for difficult analysis. `minimal` is rejected because Codex currently auto-attaches web_search, which the API does not allow with minimal reasoning."
2274022754
),
2274122755
sandbox: sandboxModeSchema.default("read-only").describe("Codex sandbox mode. Keep read-only unless the user explicitly asks otherwise."),
22756+
dangerously_bypass_approvals_and_sandbox: external_exports.boolean().default(false).describe(
22757+
"Bypass all Codex sandboxing and approval prompts with Codex's --dangerously-bypass-approvals-and-sandbox flag. This gives Codex normal local capabilities such as DNS/network access and unrestricted file/git writes. Only set when the user explicitly asks for non-sandbox/full-access execution."
22758+
),
2274222759
service_tier: serviceTierSchema.optional().describe(
2274322760
"Optional Codex service tier. Omit by default; only set this when the user explicitly asks for a service tier."
2274422761
),
@@ -22848,6 +22865,7 @@ function toRunOptions(args) {
2284822865
modelPreset: args.model_preset,
2284922866
reasoningEffort: args.reasoning_effort,
2285022867
sandbox: args.sandbox,
22868+
dangerouslyBypassApprovalsAndSandbox: args.dangerously_bypass_approvals_and_sandbox,
2285122869
serviceTier: args.service_tier,
2285222870
modelVerbosity: args.model_verbosity,
2285322871
reasoningSummary: args.reasoning_summary,
@@ -22892,6 +22910,7 @@ function toParallelRunOptions(args) {
2289222910
modelPreset: agent.model_preset ?? args.model_preset,
2289322911
reasoningEffort: agent.reasoning_effort ?? args.reasoning_effort,
2289422912
sandbox: agent.sandbox ?? args.sandbox,
22913+
dangerouslyBypassApprovalsAndSandbox: agent.dangerously_bypass_approvals_and_sandbox ?? args.dangerously_bypass_approvals_and_sandbox,
2289522914
serviceTier: agent.service_tier ?? args.service_tier,
2289622915
modelVerbosity: agent.model_verbosity ?? args.model_verbosity,
2289722916
reasoningSummary: agent.reasoning_summary ?? args.reasoning_summary,
@@ -22977,7 +22996,7 @@ server.registerTool(
2297722996
"run_agent",
2297822997
{
2297922998
title: "Run one Codex agent",
22980-
description: "Launch one OpenAI Codex agent via codex exec. Use automatically when the user asks Claude to use Codex, ask Codex, get a Codex second opinion, run a Codex subagent, use Codex Spark, or delegate one read-only analysis task. Defaults to the Codex desktop app binary when installed, read-only sandbox, Codex's normal service tier, and non-interactive approvals.",
22999+
description: "Launch one OpenAI Codex agent via codex exec. Use automatically when the user asks Claude to use Codex, ask Codex, get a Codex second opinion, run a Codex subagent, use Codex Spark, or delegate one read-only analysis task. Defaults to the Codex desktop app binary when installed, read-only sandbox, Codex's normal service tier, and non-interactive approvals. For explicit non-sandbox/full-access requests, set dangerously_bypass_approvals_and_sandbox true.",
2298123000
inputSchema: {
2298223001
prompt: external_exports.string().min(1).describe(
2298323002
"Concrete instructions for the Codex agent. Include scope, read-only expectation, desired output shape, and file/line reference requirements when reviewing code."
@@ -23043,6 +23062,7 @@ var parallelAgentSchema = external_exports.object({
2304323062
model_preset: commonInputSchema.model_preset,
2304423063
reasoning_effort: commonInputSchema.reasoning_effort,
2304523064
sandbox: commonInputSchema.sandbox.optional(),
23065+
dangerously_bypass_approvals_and_sandbox: commonInputSchema.dangerously_bypass_approvals_and_sandbox.optional(),
2304623066
service_tier: commonInputSchema.service_tier.optional(),
2304723067
model_verbosity: commonInputSchema.model_verbosity,
2304823068
reasoning_summary: commonInputSchema.reasoning_summary,
@@ -23073,7 +23093,7 @@ server.registerTool(
2307323093
"run_agents",
2307423094
{
2307523095
title: "Run parallel Codex agents",
23076-
description: "Launch multiple independent OpenAI Codex agents concurrently and return one structured result per agent. Use automatically when the user asks for parallel Codex agents, multiple Codex subagents, broad review by independent agents, or several concurrent Codex workstreams. Split work by clear ownership, pass project_dir, keep defaults read-only, and use max_parallel to bound concurrency.",
23096+
description: "Launch multiple independent OpenAI Codex agents concurrently and return one structured result per agent. Use automatically when the user asks for parallel Codex agents, multiple Codex subagents, broad review by independent agents, or several concurrent Codex workstreams. Split work by clear ownership, pass project_dir, keep defaults read-only, and use max_parallel to bound concurrency. For explicit non-sandbox/full-access requests, set dangerously_bypass_approvals_and_sandbox true.",
2307723097
inputSchema: {
2307823098
agents: external_exports.array(parallelAgentSchema).min(1).max(12).describe(
2307923099
"Independent Codex agent tasks. Use names like api, tests, security, docs, performance, or ui when helpful."
@@ -23385,6 +23405,7 @@ server.registerTool(
2338523405
defaultModel: defaultModel(),
2338623406
defaultReasoningEffort: defaultReasoningEffort(),
2338723407
defaultSandbox: "read-only",
23408+
fullAccessFlag: "dangerously_bypass_approvals_and_sandbox",
2338823409
defaultServiceTier: "codex-default",
2338923410
modelPresets: {
2339023411
codex: "gpt-5.3-codex",
@@ -23452,6 +23473,7 @@ server.registerTool(
2345223473
ok: defaultReasoningEffort() !== "minimal",
2345323474
detail: {
2345423475
sandbox: "read-only",
23476+
dangerouslyBypassApprovalsAndSandbox: false,
2345523477
approvalPolicy: "never",
2345623478
defaultModel: defaultModel(),
2345723479
defaultReasoningEffort: defaultReasoningEffort(),
@@ -23465,6 +23487,8 @@ server.registerTool(
2346523487
supported: {
2346623488
modelPresets,
2346723489
reasoningEfforts,
23490+
sandboxModes,
23491+
fullAccessFlag: "dangerously_bypass_approvals_and_sandbox",
2346823492
outputContracts,
2346923493
mcpConfigPolicies
2347023494
}
@@ -23475,7 +23499,7 @@ server.registerPrompt(
2347523499
"codex_agent",
2347623500
{
2347723501
title: "Delegate to one Codex agent",
23478-
description: "Prompt Claude to launch one read-only Codex agent through this MCP server.",
23502+
description: "Prompt Claude to launch one Codex agent through this MCP server; read-only by default.",
2347923503
argsSchema: {
2348023504
prompt: external_exports.string().describe("Task for the Codex agent."),
2348123505
model: external_exports.string().optional().describe("Optional Codex model."),
@@ -23491,7 +23515,8 @@ server.registerPrompt(
2349123515
type: "text",
2349223516
text: [
2349323517
"Use the codex-subagents MCP tool `run_agent` for this task.",
23494-
"Keep the sandbox read-only unless I explicitly say otherwise.",
23518+
"Keep the sandbox read-only unless I explicitly ask for another sandbox or full non-sandbox access.",
23519+
"For full non-sandbox access, set dangerously_bypass_approvals_and_sandbox true.",
2349523520
model ? `Use model ${model}.` : "Use the configured Codex model default.",
2349623521
model_preset ? `Use model_preset ${model_preset}.` : "",
2349723522
reasoning_effort ? `Use reasoning_effort ${reasoning_effort}.` : "Use reasoning_effort medium unless the task clearly needs more.",
@@ -23507,7 +23532,7 @@ server.registerPrompt(
2350723532
"codex_parallel",
2350823533
{
2350923534
title: "Delegate to parallel Codex agents",
23510-
description: "Prompt Claude to split independent work across multiple read-only Codex agents through this MCP server.",
23535+
description: "Prompt Claude to split independent work across multiple Codex agents through this MCP server; read-only by default.",
2351123536
argsSchema: {
2351223537
prompt: external_exports.string().describe("Parallel delegation request."),
2351323538
max_parallel: external_exports.string().optional().describe("Optional max parallelism."),
@@ -23522,7 +23547,8 @@ server.registerPrompt(
2352223547
type: "text",
2352323548
text: [
2352423549
"Use the codex-subagents MCP tool `run_agents` for this task.",
23525-
"Create one agent object per independent workstream and run them read-only.",
23550+
"Create one agent object per independent workstream and run them read-only unless I explicitly ask for full non-sandbox access.",
23551+
"For full non-sandbox access, set dangerously_bypass_approvals_and_sandbox true.",
2352623552
max_parallel ? `Use max_parallel ${max_parallel}.` : "Use max_parallel 4 unless fewer agents are needed.",
2352723553
model_preset ? `Use model_preset ${model_preset} unless an agent needs a different model.` : "",
2352823554
"Ask each Codex agent for concise findings with file paths and line references when relevant.",

0 commit comments

Comments
 (0)