{"id":"d7058a23-6e78-4574-9b9a-7e8233028027","entityType":"agent","slug":"clawhub-psyb0t-codexbox","name":"codexbox","canonicalUrl":"https://www.xpersona.co/agent/clawhub-psyb0t-codexbox","canonicalPath":"/agent/clawhub-psyb0t-codexbox","generatedAt":"2026-10-10T06:42:29.923Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T03:09:29.550Z","emptyReason":null},"description":"Install, configure, or run Codex through the codexbox wrapper, or connect to its HTTP, MCP, Telegram, or cron surfaces.","descriptionLabel":"Source description","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.7K downloads reported by the source. Last updated 10/10/2026.","installCommand":"clawhub skill install s17fq93tmpky791n7516jcn08n83sfn2:codexbox","sourceUrl":"https://clawhub.ai/psyb0t/codexbox","homepage":"https://clawhub.ai/psyb0t/skills/codexbox","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/psyb0t/codexbox","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/psyb0t/skills/codexbox","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":65,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"codexbox technical dossier on Xpersona with agent coverage, OPENCLEW support, and live trust metadata."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-10T03:09:29.550Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T03:09:29.550Z","emptyReason":null},"stars":null,"forks":null,"downloads":1747,"packageName":null,"latestVersion":"0.7.0","tractionLabel":"1.7K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T03:09:29.550Z","emptyReason":null},"lastUpdatedAt":"2026-10-10T03:09:29.550Z","lastCrawledAt":"2026-10-10T03:09:29.550Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-11T03:09:29.550Z","lastVerifiedAt":null,"highlights":[{"version":"0.7.0","createdAt":"2026-10-07T17:22:41.115Z","changelog":"codexbox 0.7.0 - Documentation updates in SKILL.md, including revised instructions and clarifications. - Minor corrections to server endpoint documentation (e.g., `/mcp/` endpoint path). - Removed obsolete file: skill-card.md. - No core functionality changes.","fileCount":4,"zipByteSize":14136},{"version":"0.6.5","createdAt":"2026-09-23T20:13:37.751Z","changelog":"- Removed the file: skill-card.md. - No user-facing feature or functional changes. This update only removes documentation.","fileCount":4,"zipByteSize":13488},{"version":"0.6.4","createdAt":"2026-09-23T19:23:49.852Z","changelog":"- Removed the file: skill-card.md. - No functional or user-facing changes; documentation and main functionality remain unchanged.","fileCount":4,"zipByteSize":13521},{"version":"0.6.3","createdAt":"2026-09-14T11:50:58.174Z","changelog":"codexbox 0.6.3 — wrapper-first model; server now requires explicit user intent - Reworked execution model to require the codexbox wrapper for all interactive and one-shot commands; stop assembling custom docker run invocations. - API, MCP, and related server modes now only start if invoked via the wrapper with explicit `CODEXBOX_ENV_*` environment variables. - Updated install/config instructions and removed the standalone skill-card.md file. - Improved multi-agent and sibling image execution guidance; wrappers coordinate command invocation and state. - Multiple clarifications and reduced duplication in documentation.","fileCount":4,"zipByteSize":13637},{"version":"0.6.2","createdAt":"2026-09-14T00:18:58.020Z","changelog":"codexbox 0.6.2 - Removed the file \"skill-card.md\". - No user-facing feature or behavior changes.","fileCount":4,"zipByteSize":12974},{"version":"0.6.1","createdAt":"2026-09-13T10:26:30.662Z","changelog":"codexbox 0.6.1 - Setup instructions updated in references/setup.md. - Removed the skill-card.md file for a leaner package.","fileCount":4,"zipByteSize":13029},{"version":"0.6.0","createdAt":"2026-09-13T08:14:54.384Z","changelog":"- Removed the file skill-card.md. - No breaking changes to APIs or user-facing features in this version.","fileCount":4,"zipByteSize":12858},{"version":"0.5.11","createdAt":"2026-09-13T02:47:04.925Z","changelog":"- Removed the sample file skill-card.md. - No user-facing functionality or documentation changes.","fileCount":4,"zipByteSize":12870}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s17fq93tmpky791n7516jcn08n83sfn2:codexbox","setupComplexity":"low","setupSteps":["Install using `clawhub skill install s17fq93tmpky791n7516jcn08n83sfn2:codexbox` in an isolated environment before connecting it to live workloads.","No published capability contract is available yet, so validate auth and request/response behavior manually.","Review the upstream CLAWHUB listing at https://clawhub.ai/psyb0t/codexbox before using production credentials."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-psyb0t-codexbox/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-psyb0t-codexbox/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-psyb0t-codexbox/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-psyb0t-codexbox/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-psyb0t-codexbox/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-psyb0t-codexbox/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-10T06:42:29.917Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-psyb0t-codexbox/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-psyb0t-codexbox/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-psyb0t-codexbox/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-psyb0t-codexbox/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T03:09:29.550Z","emptyReason":null},"readme":"Skill: codexbox\n\nOwner: psyb0t\n\nSummary: Install, configure, or run Codex through the codexbox wrapper, or connect to its HTTP, MCP, Telegram, or cron surfaces.\n\nTags: latest:0.7.0\n\nVersion history:\n\nv0.7.0 | 2026-10-07T17:22:41.115Z | auto\n\ncodexbox 0.7.0\n\n- Documentation updates in SKILL.md, including revised instructions and clarifications.\n- Minor corrections to server endpoint documentation (e.g., `/mcp/` endpoint path).\n- Removed obsolete file: skill-card.md.\n- No core functionality changes.\n\nv0.6.5 | 2026-09-23T20:13:37.751Z | auto\n\n- Removed the file: skill-card.md.\n- No user-facing feature or functional changes. This update only removes documentation.\n\nv0.6.4 | 2026-09-23T19:23:49.852Z | auto\n\n- Removed the file: skill-card.md.\n- No functional or user-facing changes; documentation and main functionality remain unchanged.\n\nv0.6.3 | 2026-09-14T11:50:58.174Z | auto\n\ncodexbox 0.6.3 — wrapper-first model; server now requires explicit user intent\n\n- Reworked execution model to require the codexbox wrapper for all interactive and one-shot commands; stop assembling custom docker run invocations.\n- API, MCP, and related server modes now only start if invoked via the wrapper with explicit `CODEXBOX_ENV_*` environment variables.\n- Updated install/config instructions and removed the standalone skill-card.md file.\n- Improved multi-agent and sibling image execution guidance; wrappers coordinate command invocation and state.\n- Multiple clarifications and reduced duplication in documentation.\n\nv0.6.2 | 2026-09-14T00:18:58.020Z | auto\n\ncodexbox 0.6.2\n\n- Removed the file \"skill-card.md\".\n- No user-facing feature or behavior changes.\n\nv0.6.1 | 2026-09-13T10:26:30.662Z | auto\n\ncodexbox 0.6.1\n\n- Setup instructions updated in references/setup.md.\n- Removed the skill-card.md file for a leaner package.\n\nv0.6.0 | 2026-09-13T08:14:54.384Z | auto\n\n- Removed the file skill-card.md.\n- No breaking changes to APIs or user-facing features in this version.\n\nv0.5.11 | 2026-09-13T02:47:04.925Z | auto\n\n- Removed the sample file skill-card.md.\n- No user-facing functionality or documentation changes.\n\nv0.5.9 | 2026-09-04T15:22:43.804Z | auto\n\n- Removed the skill description file skill-card.md.\n- No changes to functionality or user-facing features.\n- Documentation and configuration remain unchanged.\n\nv0.5.8 | 2026-08-13T17:42:58.675Z | auto\n\ncodexbox v0.5.8\n\n- No file or SKILL.md content changes detected in this release.\n- No user-visible features or fixes in this version.\n- Functionality and documentation remain unchanged from previous version.\n\nv0.5.7 | 2026-08-13T12:55:05.757Z | auto\n\ncodexbox 0.5.7\n\n- Minor documentation updates in SKILL.md and references/setup.md for clarity and programmatic usage details.\n- Improved description of default behavior for programmatic runs and workspace pinning in API mode.\n- Removed deprecated skill-card.md file.\n\nv0.5.5 | 2026-08-10T19:13:19.973Z | auto\n\n- Removed the skill-card.md file.\n- No user-facing feature or behavior changes; this update is limited to documentation file cleanup.\n\nv0.5.4 | 2026-08-09T15:30:17.096Z | auto\n\n- Removed the file: skill-card.md.\n- No feature or behavior changes; this is a documentation cleanup only.\n\nv0.5.3 | 2026-08-01T21:33:23.765Z | auto\n\n- Removed the file: skill-card.md\n- No feature or behavioral changes; cleanup only.\n\nv0.5.2 | 2026-07-31T10:42:34.776Z | auto\n\n- Removed the file skill-card.md.\n- No changes to functionality or documentation except file cleanup.\n\nv0.5.1 | 2026-07-29T23:26:25.940Z | auto\n\ncodexbox 0.5.1\n\n- Updated setup instructions in references/setup.md for clarity and current practice.\n- Removed the skill-card.md file.\n- No breaking changes to core functionality.\n\nv0.5.0 | 2026-07-29T22:59:44.623Z | auto\n\ncodexbox 0.5.0\n\n- Updated setup instructions in references/setup.md for improved installation and configuration guidance.\n- Removed outdated skill-card.md file.\n- No functional changes to API, CLI, or Codex adapter behavior.\n\nv0.4.9 | 2026-07-28T01:12:46.252Z | auto\n\ncodexbox 0.4.9\n\n- Removed the file `skill-card.md` from the project.\n- No other visible changes to functionality or documentation.\n\nv0.4.6 | 2026-07-27T16:20:15.504Z | auto\n\ncodexbox 0.4.6\n\n- Removed the file skill-card.md.\n- No other functional or documentation changes.\n\nv0.4.5 | 2026-07-27T14:25:03.074Z | auto\n\n- Removed the sample file skill-card.md.\n- No user functionality or interface changes; package contents slimmed.\n- No impact on deployment or usage.\n\nv0.4.4 | 2026-07-26T13:13:03.375Z | auto\n\ncodexbox 0.4.4\n\n- Removed the sample file skill-card.md.\n- No user-facing functionality or documentation changes.\n\nv0.4.3 | 2026-07-26T10:29:23.309Z | auto\n\n- Removed the sample file skill-card.md.\n- No other user-facing changes in this release.\n\nv0.4.2 | 2026-07-26T03:31:54.993Z | auto\n\ncodexbox 0.4.2\n\n- Clarified security and authentication guidance for HTTP REST and MCP server modes, emphasizing the need to set per-mode tokens before exposing ports.\n- Improved and condensed documentation about file deletion safety and installer script risks.\n- Updated references/setup.md and SKILL.md for better security clarity.\n- Removed the outdated skill-card.md file.\n\nv0.4.1 | 2026-07-26T02:22:14.605Z | auto\n\ncodexbox 0.4.1\n\n- Added explicit security & safety warnings to documentation, including authentication requirements for API and MCP surfaces.\n- Clarified that omitting `CODEXBOX_API_MODE_TOKEN` or `CODEXBOX_MCP_MODE_TOKEN` leaves the respective APIs unauthenticated and unsafe for untrusted networks.\n- Documented the destructive nature of file deletion endpoints, strongly warning agents/users.\n- Removed the `skill-card.md` file.\n- Improved installation advice, recommending local inspection of installer scripts.\n\nv0.4.0 | 2026-07-25T22:58:18.308Z | auto\n\ncodexbox 0.4.0 introduces OpenAI-compatible API, MCP server, Telegram, and cron scheduler modes for Codex.\n\n- Adds API mode: run Codex via HTTP REST (synchronous/async runs, file operations, liveness, `/openai/v1/chat/completions` endpoint).\n- Supports OpenAI-compatible streaming completions and client-executed tools/tool_choice via `/openai/v1/chat/completions`.\n- Adds MCP server (mounted at `/mcp` in API mode, sidecar-capable), Telegram bot integration, and cron scheduling for unattended runs.\n- New bearer-token auth layer per surface (`CODEXBOX_API_MODE_TOKEN`, `CODEXBOX_MCP_MODE_TOKEN`) in addition to OpenAI API key or ChatGPT login.\n- Clarifies configuration and mode selection; describes workspace isolation, per-workspace run serialization, and endpoint usages.\n- Enhanced documentation on features, supported workflows, and known limitations.\n\nArchive index:\n\nArchive v0.7.0: 4 files, 14136 bytes\n\nFiles: references/setup.md (12415b), skill-card.md (1944b), SKILL.md (19265b), _meta.json (127b)\n\nFile v0.7.0:SKILL.md\n\n---\nname: codexbox\ndescription: \"Install, configure, or run Codex through the codexbox wrapper, or connect to its HTTP, MCP, Telegram, or cron surfaces.\"\nhomepage: https://github.com/psyb0t/docker-codexbox\nuser-invocable: true\nmetadata:\n  { \"openclaw\": { \"emoji\": \"🧑‍💻\", \"primaryEnv\": \"CODEXBOX_URL\", \"requires\": { \"bins\": [\"docker\", \"curl\"] } } }\n---\n\n# codexbox\n\n[OpenAI Codex CLI](https://github.com/openai/codex) inside an [aicodebox](https://github.com/psyb0t/docker-aicodebox) container, put on the network. codexbox is aicodebox's `codex` adapter — the HTTP/MCP/Telegram/cron surfaces are aicodebox's, the argv/JSON-event translation is codexbox's.\n\nFor installation and configuration, see [references/setup.md](references/setup.md).\n\n## Agent execution\n\nUse `codexbox` when it is on `PATH`. Run it from the workspace the user\nnamed. Do not assemble a new `docker run` command for routine interactive or\none-shot work. The wrapper owns the workspace mount, `~/.codex`, SSH state,\nimage selection, and session lifecycle.\n\n```bash\ncodexbox                                      # interactive Codex TUI\ncodexbox exec \"inspect this workspace\"        # one-shot work\nprintf '%s\\n' \"summarize README.md\" | codexbox exec -\nCODEXBOX_FULL=1 codexbox exec \"run the full suite\"\n```\n\nFor a wrapper-started server, prefix container variables with\n`CODEXBOX_ENV_`. For example,\n`CODEXBOX_ENV_CODEXBOX_API_MODE=1 codexbox` passes\n`CODEXBOX_API_MODE=1` into the container. Bare `CODEXBOX_API_MODE` is not\nforwarded and does not start the server.\n\nStart a local API and MCP server only when the user asks for one. Authenticate\nCodex with `codexbox login --device-auth` or `CODEXBOX_ENV_OPENAI_API_KEY`,\nthen set the actual model identifiers and distinct bearer tokens:\n\n```bash\nCODEXBOX_ENV_CODEXBOX_API_MODE=1 \\\nCODEXBOX_ENV_CODEXBOX_MCP_MODE=1 \\\nCODEXBOX_ENV_CODEXBOX_AVAILABLE_MODELS=your-model-id \\\nCODEXBOX_ENV_CODEXBOX_API_MODE_TOKEN=your-api-token \\\nCODEXBOX_ENV_CODEXBOX_MCP_MODE_TOKEN=your-mcp-token \\\ncodexbox\n```\n\nUse an HTTP or MCP endpoint only when the user asks for a service or provides\nan already-running remote URL. MCP plugins connect to a server. They do not\nreplace the local wrapper.\n\nIf `codexbox`, `claudebox`, and `pibox` were installed in the same command\ndirectory, a box can invoke a sibling command directly. The parent wrapper\npasses the real host paths and the sibling wrapper file. Do not set\n`AICODEBOX_HOST_*`, copy wrapper files, or manually mount another box's state\ndirectory. If the sibling command is absent, ask the user to install it or to\nchoose another approach.\n\n## Security & safety\n\n- **Set the mode tokens before exposing a port.** `CODEXBOX_API_MODE_TOKEN` (REST) and `CODEXBOX_MCP_MODE_TOKEN` (MCP) each default to no auth when unset, leaving that surface open to anyone who can reach it — run-execution plus full workspace file access. The two are independent (the MCP token has no fallback to the API token), so set whichever mode(s) you enable, and bind to loopback / behind an authenticating proxy. Per-mode detail: [HTTP REST API mode](#http-rest-api-mode), [MCP server mode](#mcp-server-mode).\n- **File deletion has no undo** — the run/file tools include a remove operation; only delete files the current task created, only when the user asked, and don't touch another caller's data on a shared workspace.\n- **The one-line installer pipes a remote script into `bash`.** Piping a remote script straight into bash executes unreviewed remote code as you. Prefer download → inspect → run (shown in [references/setup.md](references/setup.md)) unless you already trust the source and channel.\n\n## When To Use\n\n- Drive Codex from a script/CI job via `POST /run` instead of a terminal session.\n- Point an OpenAI-SDK client at Codex via `/openai/v1/chat/completions` (drop-in base-URL swap).\n- Wire Codex into an MCP-aware agent (Claude Code, another OpenClaw agent, Cursor) as a tool-calling backend.\n- Run Codex from Telegram on a phone, or on a cron schedule with no human in the loop.\n- Manage workspace files (upload/download/list/delete) over HTTP without a shell.\n\n## When NOT To Use\n\n- Need `--append-system-prompt` exact CLI semantics — codex has no such flag; codexbox maps `appendSystemPrompt` to `-c developer_instructions=...` (a developer-role message), not a raw prompt prepend.\n- Need per-tool allow/deny lists — codex has no name-based built-in tool allowlist. `toolsAllowlist` is accepted for cross-adapter API compatibility but logged and ignored. `noTools` is the only lever (drops shell/exec + web_search, forces the sandbox read-only).\n- Need codex's own MCP client/server support (`[mcp_servers.*]` in `config.toml`, `codex mcp-server` stdio) — that's a different, unrelated surface from the MCP mode documented here (which is aicodebox's file-ops + prompt-running MCP surface, not codex's).\n- Multiple concurrent runs against the *same* workspace — the API/OAI/MCP surfaces all serialize per-workspace; a second run against a busy workspace gets 409.\n\n## Shell mode\n\nThe default. `codexbox` (installed wrapper) or raw `docker run` drop you into `codex`'s interactive TUI, or run codex subcommands directly. No env flag — this is the base behavior with no `*_MODE` var set.\n\n```bash\nexport OPENAI_API_KEY=sk-...\ncodexbox                       # interactive TUI, continues the last session for this dir\ncodexbox --no-continue         # same, but starts a brand-new session\ncodexbox login --device-auth   # ChatGPT-subscription OAuth login\ncodexbox stop                  # stop this dir's running container(s)\n```\n\nThe wrapper mounts `$PWD` as the workspace, persists `~/.codex`, forwards `\"$@\"` straight to the image — any `codex` subcommand works (`codexbox mcp ...`, `codexbox doctor`, etc.). The sandbox-bypass flag is injected inside the container automatically.\n\n## One-shot exec mode\n\n`codex exec` (or `codexbox exec` through the wrapper) — single prompt in, output to your terminal, no TUI.\n\n```bash\ncodexbox exec \"fix the failing test in ./app\"\necho \"summarize README.md\" | codexbox exec -     # prompt via stdin\n```\n\nRaw Docker equivalent:\n\n```bash\ndocker run --rm \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD:/workspace\" \\\n  -v \"$PWD/.codex:/home/aicode/.codex\" \\\n  psyb0t/codexbox:latest \\\n  exec \"say HELLO\"\n```\n\n## API mode\n\n`CODEXBOX_API_MODE=1`. FastAPI server on `:8080` (override `CODEXBOX_API_MODE_PORT`). **Requires** `CODEXBOX_AVAILABLE_MODELS=<csv>` — API mode refuses to boot without it (codex has no hardcoded model slug to fall back to).\n\n```bash\ndocker run -d --name codexbox-api \\\n  -e CODEXBOX_API_MODE=1 \\\n  -e CODEXBOX_API_MODE_TOKEN=your-secret \\\n  -e CODEXBOX_AVAILABLE_MODELS=gpt-5.1-codex,gpt-5.1-codex-mini \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD:/workspace\" \\\n  -p 8080:8080 \\\n  psyb0t/codexbox:latest\n```\n\nWith `CODEXBOX_API_MODE_TOKEN` unset the API surface is unauthenticated — anyone who can reach `:8080` gets run-execution plus full workspace file access. Set the token and bind to loopback / behind an authenticating proxy before exposing it beyond localhost.\n\n| Method | Path | What it does |\n|--------|------|---------------|\n| `GET` | `/healthz` | liveness — `{ok, adapter}` |\n| `GET` | `/status` | in-flight runs + busy workspaces |\n| `POST` | `/run` | sync agent run → `{runId, workspace, exitCode, text, ...}` |\n| `GET` | `/run/result?runId=<id>` | poll an async run |\n| `DELETE` | `/run/{run_id}` | cancel an in-flight run |\n| `GET` | `/files` | list the workspace root |\n| `GET` | `/files/{path}` | list a sub-directory, or stream a file's bytes |\n| `PUT` | `/files/{path}` | upload — raw request body becomes the file contents; parent dirs auto-created |\n| `DELETE` | `/files/{path}` | delete a file (refuses directories — 400) |\n| `POST` | `/openai/v1/chat/completions` | OpenAI-compatible chat endpoint (see below) |\n| `GET` | `/openai/v1/models` | model list from `CODEXBOX_AVAILABLE_MODELS` |\n| `POST` | `/mcp/` | MCP server, mounted only when `CODEXBOX_MCP_MODE=1` (see MCP mode) |\n\n`DELETE /files/{path}` removes a workspace file (no undo). Confirm the target path first and only remove files the current task created — see [Security & safety](#security--safety).\n\n`POST /run` body: `prompt` (required), `workspace`, `model`, `systemPrompt`, `appendSystemPrompt`, `jsonSchema`, `noContinue`, `resume`, `timeoutSeconds`, `thinking`, `noTools`, `toolsAllowlist`, `includeRaw`, `async`, `fireAndForget`. With `jsonSchema` set, the response adds `json`, `events`, `sessionId`, `usage`, `attempts` — codex has native `--output-schema` enforcement, so `jsonSchema` maps straight onto it (no self-correction retries needed, unlike adapters without native schema support).\n\nDefault programmatic runs continue the exact top-level Codex `exec` root\npinned to the canonical workspace. The first run creates the pin; existing\nworkspaces migrate their newest top-level `exec` rollout. Newer subagent\nrollouts are deliberately excluded because Codex rejects direct turns on\nmulti-agent children. Explicit `resume` re-pins the confirmed thread;\n`noContinue` is ephemeral and leaves the workspace pin unchanged.\n\n```bash\ncurl -s http://localhost:8080/run \\\n  --oauth2-bearer \"$CODEXBOX_API_MODE_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"prompt\": \"say HELLO\", \"workspace\": \"/workspace\"}'\n```\n\nAsync: set `\"async\": true`, poll `GET /run/result?runId=<id>` until `status != \"running\"`.\n\nAll `/files/*` paths are resolved against the workspace root with traversal checking — `..` segments that escape the root return 400.\n\n```bash\ncurl -sS -X PUT --oauth2-bearer \"$CODEXBOX_API_MODE_TOKEN\" \\\n  --data-binary @local.txt http://localhost:8080/files/notes/hello.txt\n\ncurl -sS --oauth2-bearer \"$CODEXBOX_API_MODE_TOKEN\" \\\n  http://localhost:8080/files/notes/hello.txt\n```\n\n## OpenAI-compatible endpoint\n\n`POST /openai/v1/chat/completions` (mounted under API mode, same port/token). Point any OpenAI SDK's base URL at `http://host:8080/openai/v1` and call it like the real API.\n\n- **Streaming**: `\"stream\": true` — real incremental SSE for plain chat. When `tools`/`tool_choice` or a schema constraint is also set, the full answer is computed first, then replayed as a single-shot SSE stream (tool-call/schema turns can't be streamed token-by-token).\n- **Tools**: OpenAI-style `tools` / `tool_choice` in the request body. codex runs its own tools internally, so client-executed tool calling is bridged — codexbox injects an \"emit `{\"tool_calls\":[...]}` and stop\" protocol into the system prompt and parses codex's textual output back into OpenAI `tool_calls`. Stateless: resend full history each round-trip, same as the standard OpenAI tool loop.\n- **`response_format`**: `{\"type\":\"text\"}` (default), `{\"type\":\"json_object\"}` (force parseable JSON, no schema), or `{\"type\":\"json_schema\",\"json_schema\":{\"name\",\"schema\",\"strict?\"}}` (schema-constrained — same native `--output-schema` path as `/run`'s `jsonSchema`). Composable with `tools`: a tool-call turn isn't schema-checked, only the final non-tool answer is.\n- Custom headers (`x-aicodebox-*` prefix, `x-claude-*` accepted as aliases for workspace/continue/append-system-prompt) cover what the OpenAI wire format has no field for: `x-aicodebox-workspace`, `x-aicodebox-continue`, `x-aicodebox-resume`, `x-aicodebox-json-schema` (fallback if `response_format` isn't set), `x-aicodebox-no-tools`, `x-aicodebox-tools-allowlist`, `x-aicodebox-timeout-seconds`, `x-aicodebox-extra-args`.\n\n```bash\ncurl -s http://localhost:8080/openai/v1/chat/completions \\\n  --oauth2-bearer \"$CODEXBOX_API_MODE_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n        \"model\": \"gpt-5.1-codex\",\n        \"messages\": [{\"role\": \"user\", \"content\": \"say HELLO\"}],\n        \"stream\": false\n      }'\n```\n\n## MCP mode\n\n`CODEXBOX_MCP_MODE=1`. Exposes the aicodebox base's own MCP surface — file ops + prompt running as tools: `run_prompt`, `list_files`, `read_file`, `write_file`, `delete_file`. This is separate from codex's own MCP client/server support (`config.toml` `[mcp_servers.*]`, `codex mcp-server` stdio) — neither of those is wired up by codexbox.\n\nCoexists with any foreground mode:\n\n| Foreground | MCP placement |\n|---|---|\n| API mode (`CODEXBOX_API_MODE=1`) | mounted at `/mcp/` on the API port — no extra process |\n| Telegram / Cron / shell-only | sidecar uvicorn on `CODEXBOX_MCP_MODE_PORT` (default `8081`), served at the process root |\n\nThe slashless `/mcp` spelling reaches the same API-mounted handler without a redirect.\n\nAuth: `CODEXBOX_MCP_MODE_TOKEN=<token>` — bearer in `Authorization: Bearer ...`, or `?apiToken=...` for clients that can't set headers. Empty = no auth. **No fallback to `API_MODE_TOKEN`** — MCP has its own bearer, checked independently.\n\nWith `CODEXBOX_MCP_MODE_TOKEN` unset the MCP surface (`run_prompt`, `list_files`, `read_file`, `write_file`, `delete_file`) is unauthenticated — anyone who can reach `/mcp/` or the sidecar port gets run-execution plus full workspace file access. This surface has its own bearer; setting `CODEXBOX_API_MODE_TOKEN` does not protect it. Set the token and bind to loopback / behind an authenticating proxy before exposing it beyond localhost.\n\nMCP keeps DNS rebinding protection enabled. Loopback hosts and origins work by default; allow a reverse proxy's exact `Host` and browser `Origin` with `CODEXBOX_MCP_MODE_ALLOWED_HOSTS` and `CODEXBOX_MCP_MODE_ALLOWED_ORIGINS` before exposing MCP through it.\n\n```bash\ndocker run -d --name codexbox-api \\\n  -e CODEXBOX_API_MODE=1 -e CODEXBOX_API_MODE_TOKEN=your-secret \\\n  -e CODEXBOX_MCP_MODE=1 -e CODEXBOX_MCP_MODE_TOKEN=your-mcp-secret \\\n  -e CODEXBOX_AVAILABLE_MODELS=gpt-5.1-codex \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD:/workspace\" -p 8080:8080 \\\n  psyb0t/codexbox:latest\n```\n\nWire into an MCP-aware client:\n\n```bash\nclaude mcp add --transport http codexbox http://localhost:8080/mcp/ \\\n  --header \"Authorization: Bearer your-mcp-secret\"\n```\n\n## Telegram mode\n\n`CODEXBOX_TELEGRAM_MODE=1` + `CODEXBOX_TELEGRAM_MODE_TOKEN=<token-from-BotFather>`.\n\n```bash\ndocker run -d --name codexbox-tg \\\n  -e CODEXBOX_TELEGRAM_MODE=1 \\\n  -e CODEXBOX_TELEGRAM_MODE_TOKEN=123456:ABC-your-bot-token \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD:/workspace\" \\\n  -v \"$HOME/.aicodebox:/home/aicode/.aicodebox\" \\\n  psyb0t/codexbox:latest\n```\n\n- Text in → codex runs → Markdown→HTML rendered response back.\n- File uploads land in the chat's workspace. `[SEND_FILE: path]` in codex's output delivers workspace files as Telegram attachments.\n- Per-chat overrides: `/model`, `/effort` (codex's `model_reasoning_effort` levels), `/system_prompt`, `/append_system_prompt`. Persisted to `CODEXBOX_TELEGRAM_MODE_OVERRIDES`.\n- `/cancel` kills the in-flight run, `/reload` re-reads config, `/config` dumps merged settings, `/fetch <path>` downloads a file.\n\nAccess control + per-chat config lives in a YAML file (`CODEXBOX_TELEGRAM_MODE_CONFIG`, default `~/.aicodebox/telegram.yml`):\n\n```yaml\nallowed_chats: [-100123, 42]\ndefault:\n  model: gpt-5.1-codex\n  workspace: shared\nchats:\n  -100123:\n    workspace: alpha\n    allowed_users: [10, 20]\n```\n\n## Cron mode\n\n`CODEXBOX_CRON_MODE=1` + `CODEXBOX_CRON_MODE_FILE=/path/to/cron.yaml`. 6-field cron schedules via croniter. Each job fires codex non-interactively with the given instruction. Runs together with Telegram mode (cron in-thread inside the telegram process) when both are enabled; otherwise it's its own foreground process.\n\nVia the `codexbox` wrapper (host-side trigger vars, translated into the container-side `CODEXBOX_CRON_MODE*` vars automatically):\n\n```bash\nCODEXBOX_MODE_CRON=1 CODEXBOX_MODE_CRON_FILE=/path/cron.yaml codexbox\n```\n\nRaw Docker:\n\n```bash\ndocker run -d --name codexbox-cron \\\n  -e CODEXBOX_CRON_MODE=1 \\\n  -e CODEXBOX_CRON_MODE_FILE=/cron/jobs.yaml \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD/cron.yaml:/cron/jobs.yaml:ro\" \\\n  -v \"$PWD:/workspace\" \\\n  psyb0t/codexbox:latest\n```\n\n```yaml\njobs:\n  - name: morning-standup\n    schedule: \"0 0 9 * * 1-5\"\n    instruction: |\n      Summarize what changed in /workspace since yesterday.\n      Be brief. One paragraph max.\n    workspace: myproject\n    telegram_chat_id: -100123\n    model: gpt-5.1-codex\n    thinking: low\n```\n\n`CODEXBOX_CRON_MODE_HISTORY_DIR` (default `$HOME/.aicodebox/cron`) is the whole cron state root. Each run gets a history dir at `<root>/history/<workspace>/<timestamp>-<job>/` with `meta.json`, `stdout.log`, `stderr.log`, `result.txt` (plus `telegram.json` when telegram is also configured — the next run's prompt gets a \"prior run\" hint automatically). A per-job summary jsonl lands at `<root>/<job>.jsonl`. Set a job's `telegram_chat_id` to `0` to opt it out of an inherited root-level notification target; a successful job with an explicit `telegram_chat_id` still posts a notice even when its result text is empty.\n\n## Auth\n\nTwo independent auth layers:\n\n**1. Surface auth** (who can call the HTTP/MCP endpoints): `CODEXBOX_API_MODE_TOKEN` gates `/run`, `/files/*`, `/openai/v1/*`; `CODEXBOX_MCP_MODE_TOKEN` gates `/mcp/` (its own bearer, no fallback to the API token). Empty = no auth on that surface.\n\n**2. codex's own upstream auth** (how codex talks to OpenAI): pick one —\n  - `OPENAI_API_KEY` — seeded into `$CODEX_HOME/auth.json` on every boot; safe to always set (never overwrites an existing ChatGPT-subscription login).\n  - ChatGPT subscription — one-time `codexbox login --device-auth` with `~/.codex` bind-mounted so the OAuth login survives container recreation. Bills against Plus/Pro/Team instead of API usage; the `*-codex`/`*-codex-mini` model slugs are rejected on a subscription account (400) — use the `gpt-5.6-*` family instead.\n\n## Typical Workflows\n\n**Fire a one-off prompt from a script:**\n\n```bash\ncurl -s http://localhost:8080/run \\\n  -H \"Authorization: Bearer $CODEXBOX_TOKEN\" -H \"Content-Type: application/json\" \\\n  -d '{\"prompt\": \"list every TODO in /workspace\", \"workspace\": \"/workspace\"}' | jq -r .text\n```\n\n**Drop-in OpenAI SDK swap:**\n\n```python\nfrom openai import OpenAI\nclient = OpenAI(base_url=\"http://localhost:8080/openai/v1\", api_key=\"your-secret\")\nresp = client.chat.completions.create(\n    model=\"gpt-5.1-codex\",\n    messages=[{\"role\": \"user\", \"content\": \"say HELLO\"}],\n)\nprint(resp.choices[0].message.content)\n```\n\n**Schema-constrained extraction:**\n\n```bash\ncurl -s http://localhost:8080/run \\\n  -H \"Authorization: Bearer $CODEXBOX_TOKEN\" -H \"Content-Type: application/json\" \\\n  -d '{\n        \"prompt\": \"extract the version + license from README.md\",\n        \"workspace\": \"/workspace\",\n        \"jsonSchema\": {\"type\": \"object\", \"properties\": {\"version\": {\"type\": \"string\"}, \"license\": {\"type\": \"string\"}}, \"required\": [\"version\", \"license\"]}\n      }' | jq .json\n```\n\n**Async run + poll:**\n\n```bash\nrun_id=$(curl -s http://localhost:8080/run -H \"Authorization: Bearer $CODEXBOX_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"prompt\": \"run the full test suite and summarize failures\", \"async\": true}' | jq -r .runId)\n\ncurl -s \"http://localhost:8080/run/result?runId=$run_id\" -H \"Authorization: Bearer $CODEXBOX_TOKEN\" | jq\n```\n\n**Cancel a stuck run:**\n\n```bash\ncurl -s -X DELETE \"http://localhost:8080/run/$run_id\" -H \"Authorization: Bearer $CODEXBOX_TOKEN\"\n```\n\nFile v0.7.0:_meta.json\n\n{\n  \"ownerId\": \"kn79dhvmpjng4rp2jjk8k0v5xx80ccbk\",\n  \"slug\": \"codexbox\",\n  \"version\": \"0.7.0\",\n  \"publishedAt\": 1791393761115\n}\n\nFile v0.7.0:references/setup.md\n\n# codexbox setup\n\nSee [SKILL.md](../SKILL.md#security--safety) for the full destructive-operation and unauthenticated-surface warnings before running any mode that binds a port.\n\n## Requirements\n\n- Docker\n- Codex auth: `OPENAI_API_KEY` (pay-as-you-go) or a ChatGPT Plus/Pro/Team subscription (`codexbox login --device-auth`)\n- Optional: SSH key for git-over-SSH inside the container (the installer generates one)\n\nFor ordinary agent work, use the installed `codexbox` command from the target\nworkspace. Do not replace it with a hand-written Docker invocation. The\nwrapper handles the workspace, state, SSH, image, and nested launch context.\n\n## Quick Install (wrapper)\n\nThe one-liner installer pulls the image, creates persistent Codex/SSH dirs, and installs the `codexbox` wrapper on `PATH`.\n\n**Recommended: download, inspect, then run.** Piping a remote script straight into bash executes unreviewed remote code as you. Download it, read it, then run it:\n\n```bash\ncurl -fsSL -o install.sh https://raw.githubusercontent.com/psyb0t/docker-codexbox/master/install.sh\nless install.sh          # read it before running anything\nbash install.sh          # minimal image — default\n# CODEXBOX_FULL=1 bash install.sh        # full image — every development tool pre-installed\n# bash install.sh codex                  # custom command name\n```\n\n`CODEXBOX_FULL=1` must be set before `install.sh` runs — the installer needs it in `bash`'s environment. The choice is baked into the installed wrapper; you don't need to set it again afterward.\n\n### Install from a local checkout\n\nFrom this repository, build and install without pulling a published codexbox\nimage:\n\n```bash\nmake install       # minimal image\nmake install-full  # full image\n\n# wrapper only — no build or pull; select full when needed\nmake install-wrapper\nCODEXBOX_FULL=1 make install-wrapper\n```\n\nThe installer-only `CODEXBOX_SRC_LOCAL=true` flag skips `docker pull` and\nrequires the selected local image to already exist. `make install-wrapper`\nuses that existing image without rebuilding it.\n\n**Verify:** `codexbox --version` should print the codex CLI version.\n\n```bash\ncodexbox                                  # interactive\ncodexbox exec \"inspect this workspace\"    # one-shot\nCODEXBOX_FULL=1 codexbox exec \"run tests\" # temporary full image\n```\n\nFor a wrapper-started server, use `CODEXBOX_ENV_` before every variable that\nmust reach the container. For example,\n`CODEXBOX_ENV_CODEXBOX_API_MODE=1 codexbox` starts API mode.\n\n### Sibling boxes\n\nInstall `codexbox`, `claudebox`, and `pibox` in the same command directory,\nnormally `/usr/local/bin`, to make the sibling commands available inside a\nbox. The parent mounts only the wrapper files read-only. A sibling wrapper then\nruns through the host Docker daemon and mounts its own host data directory.\n\n## Image Variants\n\n| Image | Tag | Contents |\n|---|---|---|\n| Minimal (default) | `psyb0t/codexbox:latest` | Codex, Node.js, Python, `uv`, Docker, Git, `jq`, `curl` |\n| Full | `psyb0t/codexbox:latest-full` | Everything in minimal + Go, gopls/Delve/golangci-lint/staticcheck/gofumpt, Python lint/type/test tooling, JS/TS lint/format/framework CLIs, GitHub CLI, Terraform, kubectl, Helm, build tools (CMake/ClangFormat/Valgrind/GDB/strace/ltrace), Postgres/MySQL/SQLite/Redis clients, editors/shell tools |\n\n`CODEXBOX_FULL` is binary: unset or `0` selects minimal, `1` selects full — any other value fails. `CODEXBOX_IMAGE` is the highest-priority explicit override if you want a specific tag regardless of `CODEXBOX_FULL`.\n\n## Manual Docker Use\n\nUse raw Docker only for an explicitly requested container deployment. Use the\nwrapper for interactive, one-shot, and local service runs. All direct Docker\nshapes for service deployment are in [../SKILL.md](../SKILL.md).\n\nMinimal foreground-mode boilerplate:\n\n```bash\ndocker run -d --name codexbox \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD:/workspace\" \\\n  -v \"$HOME/.codex:/home/aicode/.codex\" \\\n  <mode env vars here> \\\n  -p <port>:<port> \\\n  psyb0t/codexbox:latest\n```\n\n## Environment Variable Reference\n\n### Wrapper-only (host-side, read by `wrapper.sh`, not passed into the container as-is)\n\n| Var | Default | What it does |\n|---|---|---|\n| `OPENAI_API_KEY` | — | Forwarded into the container; seeds `auth.json` on boot |\n| `OPENAI_BASE_URL` | — | Point codex at an OpenAI-compatible endpoint instead of the default API |\n| `CODEXBOX_IMAGE` | installed image | Override the image the wrapper runs |\n| `CODEXBOX_FULL` | installed choice (`0` initially) | `0` forces minimal, `1` forces full |\n| `CODEXBOX_DATA_DIR` | `~/.codex` | Host dir mounted as `CODEX_HOME` (auth + config + sessions + per-workspace root-session pins) |\n| `CODEXBOX_SSH_DIR` | `~/.ssh/codexbox` | SSH key dir mounted into the container |\n| `CODEXBOX_MAX_MEM` | `10g` | Per-container memory limit |\n| `CODEXBOX_CONTAINER_NAME` | derived from `$PWD` | Override the per-workspace container name |\n| `CODEXBOX_ENV_*` | — | Forward arbitrary env into the container (prefix stripped: `CODEXBOX_ENV_FOO=bar` → `FOO=bar` inside) |\n| `CODEXBOX_MOUNT_*` | — | Mount extra host dirs (`/host:/container`, or a bare path for same-path-both-sides) |\n| `CODEXBOX_MODE_CRON` / `CODEXBOX_MODE_CRON_FILE` | — | Wrapper trigger: starts the cron scheduler as a long-running background container instead of the interactive one. Translated internally to `CODEXBOX_CRON_MODE` / `CODEXBOX_CRON_MODE_FILE` inside the container. |\n\n### Container-side mode flags\n\nNaming convention: `CODEXBOX_<MODE>_MODE=1` is the on/off flag, `CODEXBOX_<MODE>_MODE_<KNOB>=...` is its config.\n\n| Var | Default | What it does |\n|---|---|---|\n| `CODEXBOX_API_MODE` | `0` | Boot the HTTP API server (foreground) |\n| `CODEXBOX_TELEGRAM_MODE` | `0` | Boot the Telegram bot (foreground) |\n| `CODEXBOX_CRON_MODE` | `0` | Boot the cron scheduler (foreground; in-thread when telegram is also on) |\n| `CODEXBOX_MCP_MODE` | `0` | Expose MCP — mounted at `/mcp/` in API mode, or as a standalone sidecar elsewhere |\n\nForeground modes (API/Telegram/Cron) are mutually exclusive, except Telegram+Cron together (cron runs in-thread inside the telegram process). API wins if set alongside anything else. MCP mode is independent — it coexists with whatever foreground mode is running, or with none at all (shell-only + MCP sidecar).\n\n### API mode config\n\n| Var | Default | What it does |\n|---|---|---|\n| `CODEXBOX_API_MODE_PORT` | `8080` | Port the API server binds to |\n| `CODEXBOX_API_MODE_TOKEN` | empty | Bearer token for the API surface (`/run`, `/files/*`, `/openai/v1/*`). Empty = no auth |\n\nWith `CODEXBOX_API_MODE_TOKEN` unset the API surface (`/run`, `/files/*`, `/openai/v1/*`) is unauthenticated — anyone who can reach it gets run-execution and full workspace file access. Set the token and bind to loopback / behind an authenticating proxy before exposing it beyond localhost.\n\n### Telegram mode config\n\n| Var | Default | What it does |\n|---|---|---|\n| `CODEXBOX_TELEGRAM_MODE_TOKEN` | — | Bot token from @BotFather |\n| `CODEXBOX_TELEGRAM_MODE_CONFIG` | `~/.aicodebox/telegram.yml` | Path to the telegram config YAML |\n| `CODEXBOX_TELEGRAM_MODE_OVERRIDES` | `~/.aicodebox/telegram_overrides.json` | Per-chat override store (model/effort/system prompts) |\n\n### Cron mode config\n\n| Var | Default | What it does |\n|---|---|---|\n| `CODEXBOX_CRON_MODE_FILE` | — | Path to the cron YAML |\n| `CODEXBOX_CRON_MODE_HISTORY_DIR` | `~/.aicodebox/cron` | Cron state root. Run history lands under `<root>/history/<workspace>/<timestamp>-<job>/` (`meta.json`, `stdout.log`, `stderr.log`, `result.txt`, `telegram.json`), per-job summaries at `<root>/<job>.jsonl`, and the telegram reply inbox at `<root>/telegram_messages.json` |\n\n### MCP mode config\n\n| Var | Default | What it does |\n|---|---|---|\n| `CODEXBOX_MCP_MODE_PORT` | `8081` | Port the sidecar MCP server binds to (ignored when mounted inside API mode) |\n| `CODEXBOX_MCP_MODE_TOKEN` | empty | Bearer token for MCP. Empty = no auth. No fallback to `API_MODE_TOKEN` |\n| `CODEXBOX_MCP_MODE_ALLOWED_HOSTS` | loopback hosts | Comma-separated MCP `Host` allowlist. Add each reverse-proxy host name |\n| `CODEXBOX_MCP_MODE_ALLOWED_ORIGINS` | loopback HTTP origins | Comma-separated MCP browser Origin allowlist. Add each reverse-proxy origin |\n\nWith `CODEXBOX_MCP_MODE_TOKEN` unset the MCP surface (`run_prompt`, `list_files`, `read_file`, `write_file`, `delete_file`) is unauthenticated — anyone who can reach it gets full workspace file access. This surface has its own bearer; setting `CODEXBOX_API_MODE_TOKEN` does not protect it. Set the token and bind to loopback / behind an authenticating proxy before exposing it beyond localhost.\n\nMCP also keeps DNS rebinding protection enabled. Loopback hosts and origins work by default; a reverse proxy, tunnel, or public DNS name needs its exact `CODEXBOX_MCP_MODE_ALLOWED_HOSTS` and browser `CODEXBOX_MCP_MODE_ALLOWED_ORIGINS` values added before MCP is reachable through it.\n\n### Workspace & runtime\n\n| Var | Default | What it does |\n|---|---|---|\n| `CODEXBOX_WORKSPACE` | `/workspace` | Root workspace dir inside the container |\n| `CODEXBOX_CONTAINER_NAME` | `aicodebox` | Scopes per-container state files (auth, etc.) |\n| `CODEXBOX_AVAILABLE_MODELS` | — | **Required for API mode.** CSV list returned by `/openai/v1/models` and shown in the Telegram `/model` picker |\n| `CODEXBOX_AVAILABLE_EFFORTS` | `none,minimal,low,medium,high,xhigh,max` | Override the effort/reasoning list shown by the Telegram `/effort` picker |\n| `CODEXBOX_MODEL` | — | Default model passed to codex when a caller doesn't specify one |\n\nEvery `CODEXBOX_X` name above also works as `AICODEBOX_X` (the base image's native naming) — the entrypoint translates `CODEXBOX_X` to `AICODEBOX_X` when only the codexbox-prefixed one is set. If both are set, `AICODEBOX_X` wins.\n\n### Init scripts and user bin\n\n`$HOME/.aicodebox/bin` is on `PATH` ahead of everything else, for codex, for init scripts, and for `docker exec` shells. `$HOME/.aicodebox/init.d/*.sh` run once per container, after the image's own `/aicodebox-init.d/*.sh`, as `aicode` with passwordless sudo; a failing script is logged and the rest still run. Init now runs once per container rather than once per bind-mounted state directory, so scripts placed there need to tolerate re-running on every new container.\n\n## Ports\n\n| Port | Default var | Service |\n|---|---|---|\n| 8080 | `CODEXBOX_API_MODE_PORT` | HTTP API (`/run`, `/files`, `/openai/v1/*`) + MCP mounted at `/mcp/` when `CODEXBOX_MCP_MODE=1` |\n| 8081 | `CODEXBOX_MCP_MODE_PORT` | Standalone MCP sidecar — only when MCP mode is on and API mode is not |\n\nNo port is exposed by default in Telegram-only or cron-only or shell-only deployments (they're outbound-only / no HTTP surface unless MCP mode is also enabled).\n\n## Auth Setup\n\n### API key\n\n```bash\ndocker run --rm \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD/.codex:/home/aicode/.codex\" \\\n  psyb0t/codexbox:latest \\\n  exec \"say HELLO\"\n```\n\nSeeded into `$CODEX_HOME/auth.json` on every boot (`codex login --with-api-key` under the hood). Safe to leave set permanently — it never overwrites an existing ChatGPT-subscription login.\n\n### ChatGPT subscription\n\n```bash\ndocker run -it \\\n  -v \"$HOME/.codex:/home/aicode/.codex\" \\\n  psyb0t/codexbox:latest \\\n  login --device-auth\n```\n\nPrints a URL + short code for one-time browser approval. `~/.codex` **must** be bind-mounted or the login is lost when the container is removed. Every later run against the same bind-mounted `~/.codex` reuses it, no `OPENAI_API_KEY` needed. `codex login status` reports the active mode; `codex logout` clears it.\n\n## Management\n\n```bash\ncodexbox stop              # stop this dir's running container(s)\ncodexbox clear-session      # drop saved codex sessions (keeps auth + config)\ndocker logs -f codexbox-api # tail logs for a manually-run named container\ndocker pull psyb0t/codexbox:latest   # update\n```\n\n## Development / Testing\n\nRequires `psyb0t/docker-aicodebox` checked out next to this repo (`../docker-aicodebox`).\n\n```bash\nmake help              # list targets\nmake build-base        # build aicodebox-base from ../docker-aicodebox\nmake build              # build codexbox:local on top of it\nmake build-full         # build + tag the full toolchain variant\nmake test               # run the full e2e suite (needs .env.test — OPENAI_API_KEY, optional Telegram creds)\n```\n\nFile v0.7.0:skill-card.md\n\n## Description:\n\nInstall, configure, or run Codex through the codexbox wrapper, or connect to its HTTP, MCP, Telegram, or cron surfaces.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[psyb0t](https://clawhub.ai/user/psyb0t)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and engineers use codexbox to run Codex in a container for interactive or automated workspace tasks, or to connect it to HTTP, MCP, Telegram, and scheduled workflows.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Exposed API or MCP endpoints may allow unauthenticated execution and workspace file access.\n\nMitigation: Set separate API and MCP bearer tokens and bind services to loopback or use an authenticating proxy.\n\nRisk: File deletion can permanently remove workspace data.\n\nMitigation: Review the target before deletion and only remove files the user has authorized.\n\nRisk: Remote installers and container images run code in the user's environment.\n\nMitigation: Inspect or pin the installer and Docker image before use.\n\n## Reference(s):\n\n- [codexbox on ClawHub](https://clawhub.ai/psyb0t/skills/codexbox)\n- [codexbox setup guide](references/setup.md)\n- [codexbox project documentation](https://github.com/psyb0t/docker-codexbox)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Markdown, Code, Shell commands, Configuration instructions]\n\n**Output Format:** [Plain text, Markdown, code, shell commands, or structured API responses]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Output depends on the requested Codex task and interface.]\n\n## Skill Version(s):\n\n0.7.0 (source: ClawHub release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v0.6.5: 4 files, 13488 bytes\n\nFiles: references/setup.md (11205b), skill-card.md (2282b), SKILL.md (18568b), _meta.json (127b)\n\nFile v0.6.5:SKILL.md\n\n---\nname: codexbox\ndescription: \"Install, configure, or run Codex through the codexbox wrapper, or connect to its HTTP, MCP, Telegram, or cron surfaces.\"\nhomepage: https://github.com/psyb0t/docker-codexbox\nuser-invocable: true\nmetadata:\n  { \"openclaw\": { \"emoji\": \"🧑‍💻\", \"primaryEnv\": \"CODEXBOX_URL\", \"requires\": { \"bins\": [\"docker\", \"curl\"] } } }\n---\n\n# codexbox\n\n[OpenAI Codex CLI](https://github.com/openai/codex) inside an [aicodebox](https://github.com/psyb0t/docker-aicodebox) container, put on the network. codexbox is aicodebox's `codex` adapter — the HTTP/MCP/Telegram/cron surfaces are aicodebox's, the argv/JSON-event translation is codexbox's.\n\nFor installation and configuration, see [references/setup.md](references/setup.md).\n\n## Agent execution\n\nUse `codexbox` when it is on `PATH`. Run it from the workspace the user\nnamed. Do not assemble a new `docker run` command for routine interactive or\none-shot work. The wrapper owns the workspace mount, `~/.codex`, SSH state,\nimage selection, and session lifecycle.\n\n```bash\ncodexbox                                      # interactive Codex TUI\ncodexbox exec \"inspect this workspace\"        # one-shot work\nprintf '%s\\n' \"summarize README.md\" | codexbox exec -\nCODEXBOX_FULL=1 codexbox exec \"run the full suite\"\n```\n\nFor a wrapper-started server, prefix container variables with\n`CODEXBOX_ENV_`. For example,\n`CODEXBOX_ENV_CODEXBOX_API_MODE=1 codexbox` passes\n`CODEXBOX_API_MODE=1` into the container. Bare `CODEXBOX_API_MODE` is not\nforwarded and does not start the server.\n\nStart a local API and MCP server only when the user asks for one. Authenticate\nCodex with `codexbox login --device-auth` or `CODEXBOX_ENV_OPENAI_API_KEY`,\nthen set the actual model identifiers and distinct bearer tokens:\n\n```bash\nCODEXBOX_ENV_CODEXBOX_API_MODE=1 \\\nCODEXBOX_ENV_CODEXBOX_MCP_MODE=1 \\\nCODEXBOX_ENV_CODEXBOX_AVAILABLE_MODELS=your-model-id \\\nCODEXBOX_ENV_CODEXBOX_API_MODE_TOKEN=your-api-token \\\nCODEXBOX_ENV_CODEXBOX_MCP_MODE_TOKEN=your-mcp-token \\\ncodexbox\n```\n\nUse an HTTP or MCP endpoint only when the user asks for a service or provides\nan already-running remote URL. MCP plugins connect to a server. They do not\nreplace the local wrapper.\n\nIf `codexbox`, `claudebox`, and `pibox` were installed in the same command\ndirectory, a box can invoke a sibling command directly. The parent wrapper\npasses the real host paths and the sibling wrapper file. Do not set\n`AICODEBOX_HOST_*`, copy wrapper files, or manually mount another box's state\ndirectory. If the sibling command is absent, ask the user to install it or to\nchoose another approach.\n\n## Security & safety\n\n- **Set the mode tokens before exposing a port.** `CODEXBOX_API_MODE_TOKEN` (REST) and `CODEXBOX_MCP_MODE_TOKEN` (MCP) each default to no auth when unset, leaving that surface open to anyone who can reach it — run-execution plus full workspace file access. The two are independent (the MCP token has no fallback to the API token), so set whichever mode(s) you enable, and bind to loopback / behind an authenticating proxy. Per-mode detail: [HTTP REST API mode](#http-rest-api-mode), [MCP server mode](#mcp-server-mode).\n- **File deletion has no undo** — the run/file tools include a remove operation; only delete files the current task created, only when the user asked, and don't touch another caller's data on a shared workspace.\n- **The one-line installer pipes a remote script into `bash`.** Piping a remote script straight into bash executes unreviewed remote code as you. Prefer download → inspect → run (shown in [references/setup.md](references/setup.md)) unless you already trust the source and channel.\n\n## When To Use\n\n- Drive Codex from a script/CI job via `POST /run` instead of a terminal session.\n- Point an OpenAI-SDK client at Codex via `/openai/v1/chat/completions` (drop-in base-URL swap).\n- Wire Codex into an MCP-aware agent (Claude Code, another OpenClaw agent, Cursor) as a tool-calling backend.\n- Run Codex from Telegram on a phone, or on a cron schedule with no human in the loop.\n- Manage workspace files (upload/download/list/delete) over HTTP without a shell.\n\n## When NOT To Use\n\n- Need `--append-system-prompt` exact CLI semantics — codex has no such flag; codexbox maps `appendSystemPrompt` to `-c developer_instructions=...` (a developer-role message), not a raw prompt prepend.\n- Need per-tool allow/deny lists — codex has no name-based built-in tool allowlist. `toolsAllowlist` is accepted for cross-adapter API compatibility but logged and ignored. `noTools` is the only lever (drops shell/exec + web_search, forces the sandbox read-only).\n- Need codex's own MCP client/server support (`[mcp_servers.*]` in `config.toml`, `codex mcp-server` stdio) — that's a different, unrelated surface from the MCP mode documented here (which is aicodebox's file-ops + prompt-running MCP surface, not codex's).\n- Multiple concurrent runs against the *same* workspace — the API/OAI/MCP surfaces all serialize per-workspace; a second run against a busy workspace gets 409.\n\n## Shell mode\n\nThe default. `codexbox` (installed wrapper) or raw `docker run` drop you into `codex`'s interactive TUI, or run codex subcommands directly. No env flag — this is the base behavior with no `*_MODE` var set.\n\n```bash\nexport OPENAI_API_KEY=sk-...\ncodexbox                       # interactive TUI, continues the last session for this dir\ncodexbox --no-continue         # same, but starts a brand-new session\ncodexbox login --device-auth   # ChatGPT-subscription OAuth login\ncodexbox stop                  # stop this dir's running container(s)\n```\n\nThe wrapper mounts `$PWD` as the workspace, persists `~/.codex`, forwards `\"$@\"` straight to the image — any `codex` subcommand works (`codexbox mcp ...`, `codexbox doctor`, etc.). The sandbox-bypass flag is injected inside the container automatically.\n\n## One-shot exec mode\n\n`codex exec` (or `codexbox exec` through the wrapper) — single prompt in, output to your terminal, no TUI.\n\n```bash\ncodexbox exec \"fix the failing test in ./app\"\necho \"summarize README.md\" | codexbox exec -     # prompt via stdin\n```\n\nRaw Docker equivalent:\n\n```bash\ndocker run --rm \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD:/workspace\" \\\n  -v \"$PWD/.codex:/home/aicode/.codex\" \\\n  psyb0t/codexbox:latest \\\n  exec \"say HELLO\"\n```\n\n## API mode\n\n`CODEXBOX_API_MODE=1`. FastAPI server on `:8080` (override `CODEXBOX_API_MODE_PORT`). **Requires** `CODEXBOX_AVAILABLE_MODELS=<csv>` — API mode refuses to boot without it (codex has no hardcoded model slug to fall back to).\n\n```bash\ndocker run -d --name codexbox-api \\\n  -e CODEXBOX_API_MODE=1 \\\n  -e CODEXBOX_API_MODE_TOKEN=your-secret \\\n  -e CODEXBOX_AVAILABLE_MODELS=gpt-5.1-codex,gpt-5.1-codex-mini \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD:/workspace\" \\\n  -p 8080:8080 \\\n  psyb0t/codexbox:latest\n```\n\nWith `CODEXBOX_API_MODE_TOKEN` unset the API surface is unauthenticated — anyone who can reach `:8080` gets run-execution plus full workspace file access. Set the token and bind to loopback / behind an authenticating proxy before exposing it beyond localhost.\n\n| Method | Path | What it does |\n|--------|------|---------------|\n| `GET` | `/healthz` | liveness — `{ok, adapter}` |\n| `GET` | `/status` | in-flight runs + busy workspaces |\n| `POST` | `/run` | sync agent run → `{runId, workspace, exitCode, text, ...}` |\n| `GET` | `/run/result?runId=<id>` | poll an async run |\n| `DELETE` | `/run/{run_id}` | cancel an in-flight run |\n| `GET` | `/files` | list the workspace root |\n| `GET` | `/files/{path}` | list a sub-directory, or stream a file's bytes |\n| `PUT` | `/files/{path}` | upload — raw request body becomes the file contents; parent dirs auto-created |\n| `DELETE` | `/files/{path}` | delete a file (refuses directories — 400) |\n| `POST` | `/openai/v1/chat/completions` | OpenAI-compatible chat endpoint (see below) |\n| `GET` | `/openai/v1/models` | model list from `CODEXBOX_AVAILABLE_MODELS` |\n| `POST` | `/mcp` | MCP server, mounted only when `CODEXBOX_MCP_MODE=1` (see MCP mode) |\n\n`DELETE /files/{path}` removes a workspace file (no undo). Confirm the target path first and only remove files the current task created — see [Security & safety](#security--safety).\n\n`POST /run` body: `prompt` (required), `workspace`, `model`, `systemPrompt`, `appendSystemPrompt`, `jsonSchema`, `noContinue`, `resume`, `timeoutSeconds`, `thinking`, `noTools`, `toolsAllowlist`, `includeRaw`, `async`, `fireAndForget`. With `jsonSchema` set, the response adds `json`, `events`, `sessionId`, `usage`, `attempts` — codex has native `--output-schema` enforcement, so `jsonSchema` maps straight onto it (no self-correction retries needed, unlike adapters without native schema support).\n\nDefault programmatic runs continue the exact top-level Codex `exec` root\npinned to the canonical workspace. The first run creates the pin; existing\nworkspaces migrate their newest top-level `exec` rollout. Newer subagent\nrollouts are deliberately excluded because Codex rejects direct turns on\nmulti-agent children. Explicit `resume` re-pins the confirmed thread;\n`noContinue` is ephemeral and leaves the workspace pin unchanged.\n\n```bash\ncurl -s http://localhost:8080/run \\\n  --oauth2-bearer \"$CODEXBOX_API_MODE_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"prompt\": \"say HELLO\", \"workspace\": \"/workspace\"}'\n```\n\nAsync: set `\"async\": true`, poll `GET /run/result?runId=<id>` until `status != \"running\"`.\n\nAll `/files/*` paths are resolved against the workspace root with traversal checking — `..` segments that escape the root return 400.\n\n```bash\ncurl -sS -X PUT --oauth2-bearer \"$CODEXBOX_API_MODE_TOKEN\" \\\n  --data-binary @local.txt http://localhost:8080/files/notes/hello.txt\n\ncurl -sS --oauth2-bearer \"$CODEXBOX_API_MODE_TOKEN\" \\\n  http://localhost:8080/files/notes/hello.txt\n```\n\n## OpenAI-compatible endpoint\n\n`POST /openai/v1/chat/completions` (mounted under API mode, same port/token). Point any OpenAI SDK's base URL at `http://host:8080/openai/v1` and call it like the real API.\n\n- **Streaming**: `\"stream\": true` — real incremental SSE for plain chat. When `tools`/`tool_choice` or a schema constraint is also set, the full answer is computed first, then replayed as a single-shot SSE stream (tool-call/schema turns can't be streamed token-by-token).\n- **Tools**: OpenAI-style `tools` / `tool_choice` in the request body. codex runs its own tools internally, so client-executed tool calling is bridged — codexbox injects an \"emit `{\"tool_calls\":[...]}` and stop\" protocol into the system prompt and parses codex's textual output back into OpenAI `tool_calls`. Stateless: resend full history each round-trip, same as the standard OpenAI tool loop.\n- **`response_format`**: `{\"type\":\"text\"}` (default), `{\"type\":\"json_object\"}` (force parseable JSON, no schema), or `{\"type\":\"json_schema\",\"json_schema\":{\"name\",\"schema\",\"strict?\"}}` (schema-constrained — same native `--output-schema` path as `/run`'s `jsonSchema`). Composable with `tools`: a tool-call turn isn't schema-checked, only the final non-tool answer is.\n- Custom headers (`x-aicodebox-*` prefix, `x-claude-*` accepted as aliases for workspace/continue/append-system-prompt) cover what the OpenAI wire format has no field for: `x-aicodebox-workspace`, `x-aicodebox-continue`, `x-aicodebox-resume`, `x-aicodebox-json-schema` (fallback if `response_format` isn't set), `x-aicodebox-no-tools`, `x-aicodebox-tools-allowlist`, `x-aicodebox-timeout-seconds`, `x-aicodebox-extra-args`.\n\n```bash\ncurl -s http://localhost:8080/openai/v1/chat/completions \\\n  --oauth2-bearer \"$CODEXBOX_API_MODE_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n        \"model\": \"gpt-5.1-codex\",\n        \"messages\": [{\"role\": \"user\", \"content\": \"say HELLO\"}],\n        \"stream\": false\n      }'\n```\n\n## MCP mode\n\n`CODEXBOX_MCP_MODE=1`. Exposes the aicodebox base's own MCP surface — file ops + prompt running as tools: `run_prompt`, `list_files`, `read_file`, `write_file`, `delete_file`. This is separate from codex's own MCP client/server support (`config.toml` `[mcp_servers.*]`, `codex mcp-server` stdio) — neither of those is wired up by codexbox.\n\nCoexists with any foreground mode:\n\n| Foreground | MCP placement |\n|---|---|\n| API mode (`CODEXBOX_API_MODE=1`) | mounted at `/mcp` on the API port — no extra process |\n| Telegram / Cron / shell-only | sidecar uvicorn on `CODEXBOX_MCP_MODE_PORT` (default `8081`), served at the process root |\n\nAuth: `CODEXBOX_MCP_MODE_TOKEN=<token>` — bearer in `Authorization: Bearer ...`, or `?apiToken=...` for clients that can't set headers. Empty = no auth. **No fallback to `API_MODE_TOKEN`** — MCP has its own bearer, checked independently.\n\nWith `CODEXBOX_MCP_MODE_TOKEN` unset the MCP surface (`run_prompt`, `list_files`, `read_file`, `write_file`, `delete_file`) is unauthenticated — anyone who can reach `/mcp` or the sidecar port gets run-execution plus full workspace file access. This surface has its own bearer; setting `CODEXBOX_API_MODE_TOKEN` does not protect it. Set the token and bind to loopback / behind an authenticating proxy before exposing it beyond localhost.\n\n```bash\ndocker run -d --name codexbox-api \\\n  -e CODEXBOX_API_MODE=1 -e CODEXBOX_API_MODE_TOKEN=your-secret \\\n  -e CODEXBOX_MCP_MODE=1 -e CODEXBOX_MCP_MODE_TOKEN=your-mcp-secret \\\n  -e CODEXBOX_AVAILABLE_MODELS=gpt-5.1-codex \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD:/workspace\" -p 8080:8080 \\\n  psyb0t/codexbox:latest\n```\n\nWire into an MCP-aware client:\n\n```bash\nclaude mcp add --transport http codexbox http://localhost:8080/mcp \\\n  --header \"Authorization: Bearer your-mcp-secret\"\n```\n\n## Telegram mode\n\n`CODEXBOX_TELEGRAM_MODE=1` + `CODEXBOX_TELEGRAM_MODE_TOKEN=<token-from-BotFather>`.\n\n```bash\ndocker run -d --name codexbox-tg \\\n  -e CODEXBOX_TELEGRAM_MODE=1 \\\n  -e CODEXBOX_TELEGRAM_MODE_TOKEN=123456:ABC-your-bot-token \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD:/workspace\" \\\n  -v \"$HOME/.aicodebox:/home/aicode/.aicodebox\" \\\n  psyb0t/codexbox:latest\n```\n\n- Text in → codex runs → Markdown→HTML rendered response back.\n- File uploads land in the chat's workspace. `[SEND_FILE: path]` in codex's output delivers workspace files as Telegram attachments.\n- Per-chat overrides: `/model`, `/effort` (codex's `model_reasoning_effort` levels), `/system_prompt`, `/append_system_prompt`. Persisted to `CODEXBOX_TELEGRAM_MODE_OVERRIDES`.\n- `/cancel` kills the in-flight run, `/reload` re-reads config, `/config` dumps merged settings, `/fetch <path>` downloads a file.\n\nAccess control + per-chat config lives in a YAML file (`CODEXBOX_TELEGRAM_MODE_CONFIG`, default `~/.aicodebox/telegram.yml`):\n\n```yaml\nallowed_chats: [-100123, 42]\ndefault:\n  model: gpt-5.1-codex\n  workspace: shared\nchats:\n  -100123:\n    workspace: alpha\n    allowed_users: [10, 20]\n```\n\n## Cron mode\n\n`CODEXBOX_CRON_MODE=1` + `CODEXBOX_CRON_MODE_FILE=/path/to/cron.yaml`. 6-field cron schedules via croniter. Each job fires codex non-interactively with the given instruction. Runs together with Telegram mode (cron in-thread inside the telegram process) when both are enabled; otherwise it's its own foreground process.\n\nVia the `codexbox` wrapper (host-side trigger vars, translated into the container-side `CODEXBOX_CRON_MODE*` vars automatically):\n\n```bash\nCODEXBOX_MODE_CRON=1 CODEXBOX_MODE_CRON_FILE=/path/cron.yaml codexbox\n```\n\nRaw Docker:\n\n```bash\ndocker run -d --name codexbox-cron \\\n  -e CODEXBOX_CRON_MODE=1 \\\n  -e CODEXBOX_CRON_MODE_FILE=/cron/jobs.yaml \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD/cron.yaml:/cron/jobs.yaml:ro\" \\\n  -v \"$PWD:/workspace\" \\\n  psyb0t/codexbox:latest\n```\n\n```yaml\njobs:\n  - name: morning-standup\n    schedule: \"0 0 9 * * 1-5\"\n    instruction: |\n      Summarize what changed in /workspace since yesterday.\n      Be brief. One paragraph max.\n    workspace: myproject\n    telegram_chat_id: -100123\n    model: gpt-5.1-codex\n    thinking: low\n```\n\nEach run gets a history dir at `CODEXBOX_CRON_MODE_HISTORY_DIR/<workspace>/<timestamp>-<job>/` with `meta.json`, `stdout.log`, `stderr.log`, `result.txt` (plus `telegram.json` when telegram is also configured — the next run's prompt gets a \"prior run\" hint automatically).\n\n## Auth\n\nTwo independent auth layers:\n\n**1. Surface auth** (who can call the HTTP/MCP endpoints): `CODEXBOX_API_MODE_TOKEN` gates `/run`, `/files/*`, `/openai/v1/*`; `CODEXBOX_MCP_MODE_TOKEN` gates `/mcp` (its own bearer, no fallback to the API token). Empty = no auth on that surface.\n\n**2. codex's own upstream auth** (how codex talks to OpenAI): pick one —\n  - `OPENAI_API_KEY` — seeded into `$CODEX_HOME/auth.json` on every boot; safe to always set (never overwrites an existing ChatGPT-subscription login).\n  - ChatGPT subscription — one-time `codexbox login --device-auth` with `~/.codex` bind-mounted so the OAuth login survives container recreation. Bills against Plus/Pro/Team instead of API usage; the `*-codex`/`*-codex-mini` model slugs are rejected on a subscription account (400) — use the `gpt-5.6-*` family instead.\n\n## Typical Workflows\n\n**Fire a one-off prompt from a script:**\n\n```bash\ncurl -s http://localhost:8080/run \\\n  -H \"Authorization: Bearer $CODEXBOX_TOKEN\" -H \"Content-Type: application/json\" \\\n  -d '{\"prompt\": \"list every TODO in /workspace\", \"workspace\": \"/workspace\"}' | jq -r .text\n```\n\n**Drop-in OpenAI SDK swap:**\n\n```python\nfrom openai import OpenAI\nclient = OpenAI(base_url=\"http://localhost:8080/openai/v1\", api_key=\"your-secret\")\nresp = client.chat.completions.create(\n    model=\"gpt-5.1-codex\",\n    messages=[{\"role\": \"user\", \"content\": \"say HELLO\"}],\n)\nprint(resp.choices[0].message.content)\n```\n\n**Schema-constrained extraction:**\n\n```bash\ncurl -s http://localhost:8080/run \\\n  -H \"Authorization: Bearer $CODEXBOX_TOKEN\" -H \"Content-Type: application/json\" \\\n  -d '{\n        \"prompt\": \"extract the version + license from README.md\",\n        \"workspace\": \"/workspace\",\n        \"jsonSchema\": {\"type\": \"object\", \"properties\": {\"version\": {\"type\": \"string\"}, \"license\": {\"type\": \"string\"}}, \"required\": [\"version\", \"license\"]}\n      }' | jq .json\n```\n\n**Async run + poll:**\n\n```bash\nrun_id=$(curl -s http://localhost:8080/run -H \"Authorization: Bearer $CODEXBOX_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"prompt\": \"run the full test suite and summarize failures\", \"async\": true}' | jq -r .runId)\n\ncurl -s \"http://localhost:8080/run/result?runId=$run_id\" -H \"Authorization: Bearer $CODEXBOX_TOKEN\" | jq\n```\n\n**Cancel a stuck run:**\n\n```bash\ncurl -s -X DELETE \"http://localhost:8080/run/$run_id\" -H \"Authorization: Bearer $CODEXBOX_TOKEN\"\n```\n\nFile v0.6.5:_meta.json\n\n{\n  \"ownerId\": \"kn79dhvmpjng4rp2jjk8k0v5xx80ccbk\",\n  \"slug\": \"codexbox\",\n  \"version\": \"0.6.5\",\n  \"publishedAt\": 1790194417751\n}\n\nFile v0.6.5:references/setup.md\n\n# codexbox setup\n\nSee [SKILL.md](../SKILL.md#security--safety) for the full destructive-operation and unauthenticated-surface warnings before running any mode that binds a port.\n\n## Requirements\n\n- Docker\n- Codex auth: `OPENAI_API_KEY` (pay-as-you-go) or a ChatGPT Plus/Pro/Team subscription (`codexbox login --device-auth`)\n- Optional: SSH key for git-over-SSH inside the container (the installer generates one)\n\nFor ordinary agent work, use the installed `codexbox` command from the target\nworkspace. Do not replace it with a hand-written Docker invocation. The\nwrapper handles the workspace, state, SSH, image, and nested launch context.\n\n## Quick Install (wrapper)\n\nThe one-liner installer pulls the image, creates persistent Codex/SSH dirs, and installs the `codexbox` wrapper on `PATH`.\n\n**Recommended: download, inspect, then run.** Piping a remote script straight into bash executes unreviewed remote code as you. Download it, read it, then run it:\n\n```bash\ncurl -fsSL -o install.sh https://raw.githubusercontent.com/psyb0t/docker-codexbox/master/install.sh\nless install.sh          # read it before running anything\nbash install.sh          # minimal image — default\n# CODEXBOX_FULL=1 bash install.sh        # full image — every development tool pre-installed\n# bash install.sh codex                  # custom command name\n```\n\n`CODEXBOX_FULL=1` must be set before `install.sh` runs — the installer needs it in `bash`'s environment. The choice is baked into the installed wrapper; you don't need to set it again afterward.\n\n### Install from a local checkout\n\nFrom this repository, build and install without pulling a published codexbox\nimage:\n\n```bash\nmake install       # minimal image\nmake install-full  # full image\n\n# wrapper only — no build or pull; select full when needed\nmake install-wrapper\nCODEXBOX_FULL=1 make install-wrapper\n```\n\nThe installer-only `CODEXBOX_SRC_LOCAL=true` flag skips `docker pull` and\nrequires the selected local image to already exist. `make install-wrapper`\nuses that existing image without rebuilding it.\n\n**Verify:** `codexbox --version` should print the codex CLI version.\n\n```bash\ncodexbox                                  # interactive\ncodexbox exec \"inspect this workspace\"    # one-shot\nCODEXBOX_FULL=1 codexbox exec \"run tests\" # temporary full image\n```\n\nFor a wrapper-started server, use `CODEXBOX_ENV_` before every variable that\nmust reach the container. For example,\n`CODEXBOX_ENV_CODEXBOX_API_MODE=1 codexbox` starts API mode.\n\n### Sibling boxes\n\nInstall `codexbox`, `claudebox`, and `pibox` in the same command directory,\nnormally `/usr/local/bin`, to make the sibling commands available inside a\nbox. The parent mounts only the wrapper files read-only. A sibling wrapper then\nruns through the host Docker daemon and mounts its own host data directory.\n\n## Image Variants\n\n| Image | Tag | Contents |\n|---|---|---|\n| Minimal (default) | `psyb0t/codexbox:latest` | Codex, Node.js, Python, `uv`, Docker, Git, `jq`, `curl` |\n| Full | `psyb0t/codexbox:latest-full` | Everything in minimal + Go, gopls/Delve/golangci-lint/staticcheck/gofumpt, Python lint/type/test tooling, JS/TS lint/format/framework CLIs, GitHub CLI, Terraform, kubectl, Helm, build tools (CMake/ClangFormat/Valgrind/GDB/strace/ltrace), Postgres/MySQL/SQLite/Redis clients, editors/shell tools |\n\n`CODEXBOX_FULL` is binary: unset or `0` selects minimal, `1` selects full — any other value fails. `CODEXBOX_IMAGE` is the highest-priority explicit override if you want a specific tag regardless of `CODEXBOX_FULL`.\n\n## Manual Docker Use\n\nUse raw Docker only for an explicitly requested container deployment. Use the\nwrapper for interactive, one-shot, and local service runs. All direct Docker\nshapes for service deployment are in [../SKILL.md](../SKILL.md).\n\nMinimal foreground-mode boilerplate:\n\n```bash\ndocker run -d --name codexbox \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD:/workspace\" \\\n  -v \"$HOME/.codex:/home/aicode/.codex\" \\\n  <mode env vars here> \\\n  -p <port>:<port> \\\n  psyb0t/codexbox:latest\n```\n\n## Environment Variable Reference\n\n### Wrapper-only (host-side, read by `wrapper.sh`, not passed into the container as-is)\n\n| Var | Default | What it does |\n|---|---|---|\n| `OPENAI_API_KEY` | — | Forwarded into the container; seeds `auth.json` on boot |\n| `OPENAI_BASE_URL` | — | Point codex at an OpenAI-compatible endpoint instead of the default API |\n| `CODEXBOX_IMAGE` | installed image | Override the image the wrapper runs |\n| `CODEXBOX_FULL` | installed choice (`0` initially) | `0` forces minimal, `1` forces full |\n| `CODEXBOX_DATA_DIR` | `~/.codex` | Host dir mounted as `CODEX_HOME` (auth + config + sessions + per-workspace root-session pins) |\n| `CODEXBOX_SSH_DIR` | `~/.ssh/codexbox` | SSH key dir mounted into the container |\n| `CODEXBOX_MAX_MEM` | `10g` | Per-container memory limit |\n| `CODEXBOX_CONTAINER_NAME` | derived from `$PWD` | Override the per-workspace container name |\n| `CODEXBOX_ENV_*` | — | Forward arbitrary env into the container (prefix stripped: `CODEXBOX_ENV_FOO=bar` → `FOO=bar` inside) |\n| `CODEXBOX_MOUNT_*` | — | Mount extra host dirs (`/host:/container`, or a bare path for same-path-both-sides) |\n| `CODEXBOX_MODE_CRON` / `CODEXBOX_MODE_CRON_FILE` | — | Wrapper trigger: starts the cron scheduler as a long-running background container instead of the interactive one. Translated internally to `CODEXBOX_CRON_MODE` / `CODEXBOX_CRON_MODE_FILE` inside the container. |\n\n### Container-side mode flags\n\nNaming convention: `CODEXBOX_<MODE>_MODE=1` is the on/off flag, `CODEXBOX_<MODE>_MODE_<KNOB>=...` is its config.\n\n| Var | Default | What it does |\n|---|---|---|\n| `CODEXBOX_API_MODE` | `0` | Boot the HTTP API server (foreground) |\n| `CODEXBOX_TELEGRAM_MODE` | `0` | Boot the Telegram bot (foreground) |\n| `CODEXBOX_CRON_MODE` | `0` | Boot the cron scheduler (foreground; in-thread when telegram is also on) |\n| `CODEXBOX_MCP_MODE` | `0` | Expose MCP — mounted at `/mcp` in API mode, or as a standalone sidecar elsewhere |\n\nForeground modes (API/Telegram/Cron) are mutually exclusive, except Telegram+Cron together (cron runs in-thread inside the telegram process). API wins if set alongside anything else. MCP mode is independent — it coexists with whatever foreground mode is running, or with none at all (shell-only + MCP sidecar).\n\n### API mode config\n\n| Var | Default | What it does |\n|---|---|---|\n| `CODEXBOX_API_MODE_PORT` | `8080` | Port the API server binds to |\n| `CODEXBOX_API_MODE_TOKEN` | empty | Bearer token for the API surface (`/run`, `/files/*`, `/openai/v1/*`). Empty = no auth |\n\nWith `CODEXBOX_API_MODE_TOKEN` unset the API surface (`/run`, `/files/*`, `/openai/v1/*`) is unauthenticated — anyone who can reach it gets run-execution and full workspace file access. Set the token and bind to loopback / behind an authenticating proxy before exposing it beyond localhost.\n\n### Telegram mode config\n\n| Var | Default | What it does |\n|---|---|---|\n| `CODEXBOX_TELEGRAM_MODE_TOKEN` | — | Bot token from @BotFather |\n| `CODEXBOX_TELEGRAM_MODE_CONFIG` | `~/.aicodebox/telegram.yml` | Path to the telegram config YAML |\n| `CODEXBOX_TELEGRAM_MODE_OVERRIDES` | `~/.aicodebox/telegram_overrides.json` | Per-chat override store (model/effort/system prompts) |\n\n### Cron mode config\n\n| Var | Default | What it does |\n|---|---|---|\n| `CODEXBOX_CRON_MODE_FILE` | — | Path to the cron YAML |\n| `CODEXBOX_CRON_MODE_HISTORY_DIR` | `~/.aicodebox/cron/history` | Where cron writes per-run history dirs (`meta.json`, `stdout.log`, `stderr.log`, `result.txt`, `telegram.json`) |\n\n### MCP mode config\n\n| Var | Default | What it does |\n|---|---|---|\n| `CODEXBOX_MCP_MODE_PORT` | `8081` | Port the sidecar MCP server binds to (ignored when mounted inside API mode) |\n| `CODEXBOX_MCP_MODE_TOKEN` | empty | Bearer token for MCP. Empty = no auth. No fallback to `API_MODE_TOKEN` |\n\nWith `CODEXBOX_MCP_MODE_TOKEN` unset the MCP surface (`run_prompt`, `list_files`, `read_file`, `write_file`, `delete_file`) is unauthenticated — anyone who can reach it gets full workspace file access. This surface has its own bearer; setting `CODEXBOX_API_MODE_TOKEN` does not protect it. Set the token and bind to loopback / behind an authenticating proxy before exposing it beyond localhost.\n\n### Workspace & runtime\n\n| Var | Default | What it does |\n|---|---|---|\n| `CODEXBOX_WORKSPACE` | `/workspace` | Root workspace dir inside the container |\n| `CODEXBOX_CONTAINER_NAME` | `aicodebox` | Scopes per-container state files (auth, etc.) |\n| `CODEXBOX_AVAILABLE_MODELS` | — | **Required for API mode.** CSV list returned by `/openai/v1/models` and shown in the Telegram `/model` picker |\n| `CODEXBOX_AVAILABLE_EFFORTS` | `none,minimal,low,medium,high,xhigh,max` | Override the effort/reasoning list shown by the Telegram `/effort` picker |\n| `CODEXBOX_MODEL` | — | Default model passed to codex when a caller doesn't specify one |\n\nEvery `CODEXBOX_X` name above also works as `AICODEBOX_X` (the base image's native naming) — the entrypoint translates `CODEXBOX_X` to `AICODEBOX_X` when only the codexbox-prefixed one is set. If both are set, `AICODEBOX_X` wins.\n\n## Ports\n\n| Port | Default var | Service |\n|---|---|---|\n| 8080 | `CODEXBOX_API_MODE_PORT` | HTTP API (`/run`, `/files`, `/openai/v1/*`) + MCP mounted at `/mcp` when `CODEXBOX_MCP_MODE=1` |\n| 8081 | `CODEXBOX_MCP_MODE_PORT` | Standalone MCP sidecar — only when MCP mode is on and API mode is not |\n\nNo port is exposed by default in Telegram-only or cron-only or shell-only deployments (they're outbound-only / no HTTP surface unless MCP mode is also enabled).\n\n## Auth Setup\n\n### API key\n\n```bash\ndocker run --rm \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD/.codex:/home/aicode/.codex\" \\\n  psyb0t/codexbox:latest \\\n  exec \"say HELLO\"\n```\n\nSeeded into `$CODEX_HOME/auth.json` on every boot (`codex login --with-api-key` under the hood). Safe to leave set permanently — it never overwrites an existing ChatGPT-subscription login.\n\n### ChatGPT subscription\n\n```bash\ndocker run -it \\\n  -v \"$HOME/.codex:/home/aicode/.codex\" \\\n  psyb0t/codexbox:latest \\\n  login --device-auth\n```\n\nPrints a URL + short code for one-time browser approval. `~/.codex` **must** be bind-mounted or the login is lost when the container is removed. Every later run against the same bind-mounted `~/.codex` reuses it, no `OPENAI_API_KEY` needed. `codex login status` reports the active mode; `codex logout` clears it.\n\n## Management\n\n```bash\ncodexbox stop              # stop this dir's running container(s)\ncodexbox clear-session      # drop saved codex sessions (keeps auth + config)\ndocker logs -f codexbox-api # tail logs for a manually-run named container\ndocker pull psyb0t/codexbox:latest   # update\n```\n\n## Development / Testing\n\nRequires `psyb0t/docker-aicodebox` checked out next to this repo (`../docker-aicodebox`).\n\n```bash\nmake help              # list targets\nmake build-base        # build aicodebox-base from ../docker-aicodebox\nmake build              # build codexbox:local on top of it\nmake build-full         # build + tag the full toolchain variant\nmake test               # run the full e2e suite (needs .env.test — OPENAI_API_KEY, optional Telegram creds)\n```\n\nFile v0.6.5:skill-card.md\n\n## Description:\n\nInstall, configure, or run Codex through the codexbox wrapper, or connect to its HTTP, MCP, Telegram, or cron surfaces.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[psyb0t](https://clawhub.ai/user/psyb0t)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and engineers use codexbox to install and run Codex in Docker, expose it through HTTP, OpenAI-compatible, MCP, Telegram, or cron surfaces, and manage workspace files or automated runs when those modes are requested.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: API or MCP modes can expose agent execution and workspace file access if reachable without authentication.\n\nMitigation: Set distinct API and MCP bearer tokens before publishing any port, and prefer loopback binding or an authenticated proxy.\n\nRisk: The Dockerized service has access to the mounted workspace and Codex authentication state.\n\nMitigation: Use trusted workspaces, avoid unauthenticated shared deployments, and pin or review Docker images before use.\n\nRisk: The one-line installer executes a remote shell script.\n\nMitigation: Download and inspect the installer before running it unless the source and channel are already trusted.\n\nRisk: Workspace file deletion through exposed file tools has no undo.\n\nMitigation: Confirm target paths and delete only files that the current task created or the user explicitly asked to remove.\n\n## Reference(s):\n\n- [codexbox setup](references/setup.md)\n- [ClawHub skill page](https://clawhub.ai/psyb0t/skills/codexbox)\n\n## Skill Output:\n\n**Output Type(s):** [text, markdown, code, shell commands, configuration, guidance]\n\n**Output Format:** [Markdown guidance with inline shell commands, JSON, YAML, and code snippets]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May include Docker, HTTP API, OpenAI-compatible endpoint, MCP, Telegram, and cron configuration examples.]\n\n## Skill Version(s):\n\n0.6.5 (source: server release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v0.6.4: 4 files, 13521 bytes\n\nFiles: references/setup.md (11205b), skill-card.md (2402b), SKILL.md (18568b), _meta.json (127b)\n\nFile v0.6.4:SKILL.md\n\n---\nname: codexbox\ndescription: \"Install, configure, or run Codex through the codexbox wrapper, or connect to its HTTP, MCP, Telegram, or cron surfaces.\"\nhomepage: https://github.com/psyb0t/docker-codexbox\nuser-invocable: true\nmetadata:\n  { \"openclaw\": { \"emoji\": \"🧑‍💻\", \"primaryEnv\": \"CODEXBOX_URL\", \"requires\": { \"bins\": [\"docker\", \"curl\"] } } }\n---\n\n# codexbox\n\n[OpenAI Codex CLI](https://github.com/openai/codex) inside an [aicodebox](https://github.com/psyb0t/docker-aicodebox) container, put on the network. codexbox is aicodebox's `codex` adapter — the HTTP/MCP/Telegram/cron surfaces are aicodebox's, the argv/JSON-event translation is codexbox's.\n\nFor installation and configuration, see [references/setup.md](references/setup.md).\n\n## Agent execution\n\nUse `codexbox` when it is on `PATH`. Run it from the workspace the user\nnamed. Do not assemble a new `docker run` command for routine interactive or\none-shot work. The wrapper owns the workspace mount, `~/.codex`, SSH state,\nimage selection, and session lifecycle.\n\n```bash\ncodexbox                                      # interactive Codex TUI\ncodexbox exec \"inspect this workspace\"        # one-shot work\nprintf '%s\\n' \"summarize README.md\" | codexbox exec -\nCODEXBOX_FULL=1 codexbox exec \"run the full suite\"\n```\n\nFor a wrapper-started server, prefix container variables with\n`CODEXBOX_ENV_`. For example,\n`CODEXBOX_ENV_CODEXBOX_API_MODE=1 codexbox` passes\n`CODEXBOX_API_MODE=1` into the container. Bare `CODEXBOX_API_MODE` is not\nforwarded and does not start the server.\n\nStart a local API and MCP server only when the user asks for one. Authenticate\nCodex with `codexbox login --device-auth` or `CODEXBOX_ENV_OPENAI_API_KEY`,\nthen set the actual model identifiers and distinct bearer tokens:\n\n```bash\nCODEXBOX_ENV_CODEXBOX_API_MODE=1 \\\nCODEXBOX_ENV_CODEXBOX_MCP_MODE=1 \\\nCODEXBOX_ENV_CODEXBOX_AVAILABLE_MODELS=your-model-id \\\nCODEXBOX_ENV_CODEXBOX_API_MODE_TOKEN=your-api-token \\\nCODEXBOX_ENV_CODEXBOX_MCP_MODE_TOKEN=your-mcp-token \\\ncodexbox\n```\n\nUse an HTTP or MCP endpoint only when the user asks for a service or provides\nan already-running remote URL. MCP plugins connect to a server. They do not\nreplace the local wrapper.\n\nIf `codexbox`, `claudebox`, and `pibox` were installed in the same command\ndirectory, a box can invoke a sibling command directly. The parent wrapper\npasses the real host paths and the sibling wrapper file. Do not set\n`AICODEBOX_HOST_*`, copy wrapper files, or manually mount another box's state\ndirectory. If the sibling command is absent, ask the user to install it or to\nchoose another approach.\n\n## Security & safety\n\n- **Set the mode tokens before exposing a port.** `CODEXBOX_API_MODE_TOKEN` (REST) and `CODEXBOX_MCP_MODE_TOKEN` (MCP) each default to no auth when unset, leaving that surface open to anyone who can reach it — run-execution plus full workspace file access. The two are independent (the MCP token has no fallback to the API token), so set whichever mode(s) you enable, and bind to loopback / behind an authenticating proxy. Per-mode detail: [HTTP REST API mode](#http-rest-api-mode), [MCP server mode](#mcp-server-mode).\n- **File deletion has no undo** — the run/file tools include a remove operation; only delete files the current task created, only when the user asked, and don't touch another caller's data on a shared workspace.\n- **The one-line installer pipes a remote script into `bash`.** Piping a remote script straight into bash executes unreviewed remote code as you. Prefer download → inspect → run (shown in [references/setup.md](references/setup.md)) unless you already trust the source and channel.\n\n## When To Use\n\n- Drive Codex from a script/CI job via `POST /run` instead of a terminal session.\n- Point an OpenAI-SDK client at Codex via `/openai/v1/chat/completions` (drop-in base-URL swap).\n- Wire Codex into an MCP-aware agent (Claude Code, another OpenClaw agent, Cursor) as a tool-calling backend.\n- Run Codex from Telegram on a phone, or on a cron schedule with no human in the loop.\n- Manage workspace files (upload/download/list/delete) over HTTP without a shell.\n\n## When NOT To Use\n\n- Need `--append-system-prompt` exact CLI semantics — codex has no such flag; codexbox maps `appendSystemPrompt` to `-c developer_instructions=...` (a developer-role message), not a raw prompt prepend.\n- Need per-tool allow/deny lists — codex has no name-based built-in tool allowlist. `toolsAllowlist` is accepted for cross-adapter API compatibility but logged and ignored. `noTools` is the only lever (drops shell/exec + web_search, forces the sandbox read-only).\n- Need codex's own MCP client/server support (`[mcp_servers.*]` in `config.toml`, `codex mcp-server` stdio) — that's a different, unrelated surface from the MCP mode documented here (which is aicodebox's file-ops + prompt-running MCP surface, not codex's).\n- Multiple concurrent runs against the *same* workspace — the API/OAI/MCP surfaces all serialize per-workspace; a second run against a busy workspace gets 409.\n\n## Shell mode\n\nThe default. `codexbox` (installed wrapper) or raw `docker run` drop you into `codex`'s interactive TUI, or run codex subcommands directly. No env flag — this is the base behavior with no `*_MODE` var set.\n\n```bash\nexport OPENAI_API_KEY=sk-...\ncodexbox                       # interactive TUI, continues the last session for this dir\ncodexbox --no-continue         # same, but starts a brand-new session\ncodexbox login --device-auth   # ChatGPT-subscription OAuth login\ncodexbox stop                  # stop this dir's running container(s)\n```\n\nThe wrapper mounts `$PWD` as the workspace, persists `~/.codex`, forwards `\"$@\"` straight to the image — any `codex` subcommand works (`codexbox mcp ...`, `codexbox doctor`, etc.). The sandbox-bypass flag is injected inside the container automatically.\n\n## One-shot exec mode\n\n`codex exec` (or `codexbox exec` through the wrapper) — single prompt in, output to your terminal, no TUI.\n\n```bash\ncodexbox exec \"fix the failing test in ./app\"\necho \"summarize README.md\" | codexbox exec -     # prompt via stdin\n```\n\nRaw Docker equivalent:\n\n```bash\ndocker run --rm \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD:/workspace\" \\\n  -v \"$PWD/.codex:/home/aicode/.codex\" \\\n  psyb0t/codexbox:latest \\\n  exec \"say HELLO\"\n```\n\n## API mode\n\n`CODEXBOX_API_MODE=1`. FastAPI server on `:8080` (override `CODEXBOX_API_MODE_PORT`). **Requires** `CODEXBOX_AVAILABLE_MODELS=<csv>` — API mode refuses to boot without it (codex has no hardcoded model slug to fall back to).\n\n```bash\ndocker run -d --name codexbox-api \\\n  -e CODEXBOX_API_MODE=1 \\\n  -e CODEXBOX_API_MODE_TOKEN=your-secret \\\n  -e CODEXBOX_AVAILABLE_MODELS=gpt-5.1-codex,gpt-5.1-codex-mini \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD:/workspace\" \\\n  -p 8080:8080 \\\n  psyb0t/codexbox:latest\n```\n\nWith `CODEXBOX_API_MODE_TOKEN` unset the API surface is unauthenticated — anyone who can reach `:8080` gets run-execution plus full workspace file access. Set the token and bind to loopback / behind an authenticating proxy before exposing it beyond localhost.\n\n| Method | Path | What it does |\n|--------|------|---------------|\n| `GET` | `/healthz` | liveness — `{ok, adapter}` |\n| `GET` | `/status` | in-flight runs + busy workspaces |\n| `POST` | `/run` | sync agent run → `{runId, workspace, exitCode, text, ...}` |\n| `GET` | `/run/result?runId=<id>` | poll an async run |\n| `DELETE` | `/run/{run_id}` | cancel an in-flight run |\n| `GET` | `/files` | list the workspace root |\n| `GET` | `/files/{path}` | list a sub-directory, or stream a file's bytes |\n| `PUT` | `/files/{path}` | upload — raw request body becomes the file contents; parent dirs auto-created |\n| `DELETE` | `/files/{path}` | delete a file (refuses directories — 400) |\n| `POST` | `/openai/v1/chat/completions` | OpenAI-compatible chat endpoint (see below) |\n| `GET` | `/openai/v1/models` | model list from `CODEXBOX_AVAILABLE_MODELS` |\n| `POST` | `/mcp` | MCP server, mounted only when `CODEXBOX_MCP_MODE=1` (see MCP mode) |\n\n`DELETE /files/{path}` removes a workspace file (no undo). Confirm the target path first and only remove files the current task created — see [Security & safety](#security--safety).\n\n`POST /run` body: `prompt` (required), `workspace`, `model`, `systemPrompt`, `appendSystemPrompt`, `jsonSchema`, `noContinue`, `resume`, `timeoutSeconds`, `thinking`, `noTools`, `toolsAllowlist`, `includeRaw`, `async`, `fireAndForget`. With `jsonSchema` set, the response adds `json`, `events`, `sessionId`, `usage`, `attempts` — codex has native `--output-schema` enforcement, so `jsonSchema` maps straight onto it (no self-correction retries needed, unlike adapters without native schema support).\n\nDefault programmatic runs continue the exact top-level Codex `exec` root\npinned to the canonical workspace. The first run creates the pin; existing\nworkspaces migrate their newest top-level `exec` rollout. Newer subagent\nrollouts are deliberately excluded because Codex rejects direct turns on\nmulti-agent children. Explicit `resume` re-pins the confirmed thread;\n`noContinue` is ephemeral and leaves the workspace pin unchanged.\n\n```bash\ncurl -s http://localhost:8080/run \\\n  --oauth2-bearer \"$CODEXBOX_API_MODE_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"prompt\": \"say HELLO\", \"workspace\": \"/workspace\"}'\n```\n\nAsync: set `\"async\": true`, poll `GET /run/result?runId=<id>` until `status != \"running\"`.\n\nAll `/files/*` paths are resolved against the workspace root with traversal checking — `..` segments that escape the root return 400.\n\n```bash\ncurl -sS -X PUT --oauth2-bearer \"$CODEXBOX_API_MODE_TOKEN\" \\\n  --data-binary @local.txt http://localhost:8080/files/notes/hello.txt\n\ncurl -sS --oauth2-bearer \"$CODEXBOX_API_MODE_TOKEN\" \\\n  http://localhost:8080/files/notes/hello.txt\n```\n\n## OpenAI-compatible endpoint\n\n`POST /openai/v1/chat/completions` (mounted under API mode, same port/token). Point any OpenAI SDK's base URL at `http://host:8080/openai/v1` and call it like the real API.\n\n- **Streaming**: `\"stream\": true` — real incremental SSE for plain chat. When `tools`/`tool_choice` or a schema constraint is also set, the full answer is computed first, then replayed as a single-shot SSE stream (tool-call/schema turns can't be streamed token-by-token).\n- **Tools**: OpenAI-style `tools` / `tool_choice` in the request body. codex runs its own tools internally, so client-executed tool calling is bridged — codexbox injects an \"emit `{\"tool_calls\":[...]}` and stop\" protocol into the system prompt and parses codex's textual output back into OpenAI `tool_calls`. Stateless: resend full history each round-trip, same as the standard OpenAI tool loop.\n- **`response_format`**: `{\"type\":\"text\"}` (default), `{\"type\":\"json_object\"}` (force parseable JSON, no schema), or `{\"type\":\"json_schema\",\"json_schema\":{\"name\",\"schema\",\"strict?\"}}` (schema-constrained — same native `--output-schema` path as `/run`'s `jsonSchema`). Composable with `tools`: a tool-call turn isn't schema-checked, only the final non-tool answer is.\n- Custom headers (`x-aicodebox-*` prefix, `x-claude-*` accepted as aliases for workspace/continue/append-system-prompt) cover what the OpenAI wire format has no field for: `x-aicodebox-workspace`, `x-aicodebox-continue`, `x-aicodebox-resume`, `x-aicodebox-json-schema` (fallback if `response_format` isn't set), `x-aicodebox-no-tools`, `x-aicodebox-tools-allowlist`, `x-aicodebox-timeout-seconds`, `x-aicodebox-extra-args`.\n\n```bash\ncurl -s http://localhost:8080/openai/v1/chat/completions \\\n  --oauth2-bearer \"$CODEXBOX_API_MODE_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n        \"model\": \"gpt-5.1-codex\",\n        \"messages\": [{\"role\": \"user\", \"content\": \"say HELLO\"}],\n        \"stream\": false\n      }'\n```\n\n## MCP mode\n\n`CODEXBOX_MCP_MODE=1`. Exposes the aicodebox base's own MCP surface — file ops + prompt running as tools: `run_prompt`, `list_files`, `read_file`, `write_file`, `delete_file`. This is separate from codex's own MCP client/server support (`config.toml` `[mcp_servers.*]`, `codex mcp-server` stdio) — neither of those is wired up by codexbox.\n\nCoexists with any foreground mode:\n\n| Foreground | MCP placement |\n|---|---|\n| API mode (`CODEXBOX_API_MODE=1`) | mounted at `/mcp` on the API port — no extra process |\n| Telegram / Cron / shell-only | sidecar uvicorn on `CODEXBOX_MCP_MODE_PORT` (default `8081`), served at the process root |\n\nAuth: `CODEXBOX_MCP_MODE_TOKEN=<token>` — bearer in `Authorization: Bearer ...`, or `?apiToken=...` for clients that can't set headers. Empty = no auth. **No fallback to `API_MODE_TOKEN`** — MCP has its own bearer, checked independently.\n\nWith `CODEXBOX_MCP_MODE_TOKEN` unset the MCP surface (`run_prompt`, `list_files`, `read_file`, `write_file`, `delete_file`) is unauthenticated — anyone who can reach `/mcp` or the sidecar port gets run-execution plus full workspace file access. This surface has its own bearer; setting `CODEXBOX_API_MODE_TOKEN` does not protect it. Set the token and bind to loopback / behind an authenticating proxy before exposing it beyond localhost.\n\n```bash\ndocker run -d --name codexbox-api \\\n  -e CODEXBOX_API_MODE=1 -e CODEXBOX_API_MODE_TOKEN=your-secret \\\n  -e CODEXBOX_MCP_MODE=1 -e CODEXBOX_MCP_MODE_TOKEN=your-mcp-secret \\\n  -e CODEXBOX_AVAILABLE_MODELS=gpt-5.1-codex \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD:/workspace\" -p 8080:8080 \\\n  psyb0t/codexbox:latest\n```\n\nWire into an MCP-aware client:\n\n```bash\nclaude mcp add --transport http codexbox http://localhost:8080/mcp \\\n  --header \"Authorization: Bearer your-mcp-secret\"\n```\n\n## Telegram mode\n\n`CODEXBOX_TELEGRAM_MODE=1` + `CODEXBOX_TELEGRAM_MODE_TOKEN=<token-from-BotFather>`.\n\n```bash\ndocker run -d --name codexbox-tg \\\n  -e CODEXBOX_TELEGRAM_MODE=1 \\\n  -e CODEXBOX_TELEGRAM_MODE_TOKEN=123456:ABC-your-bot-token \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD:/workspace\" \\\n  -v \"$HOME/.aicodebox:/home/aicode/.aicodebox\" \\\n  psyb0t/codexbox:latest\n```\n\n- Text in → codex runs → Markdown→HTML rendered response back.\n- File uploads land in the chat's workspace. `[SEND_FILE: path]` in codex's output delivers workspace files as Telegram attachments.\n- Per-chat overrides: `/model`, `/effort` (codex's `model_reasoning_effort` levels), `/system_prompt`, `/append_system_prompt`. Persisted to `CODEXBOX_TELEGRAM_MODE_OVERRIDES`.\n- `/cancel` kills the in-flight run, `/reload` re-reads config, `/config` dumps merged settings, `/fetch <path>` downloads a file.\n\nAccess control + per-chat config lives in a YAML file (`CODEXBOX_TELEGRAM_MODE_CONFIG`, default `~/.aicodebox/telegram.yml`):\n\n```yaml\nallowed_chats: [-100123, 42]\ndefault:\n  model: gpt-5.1-codex\n  workspace: shared\nchats:\n  -100123:\n    workspace: alpha\n    allowed_users: [10, 20]\n```\n\n## Cron mode\n\n`CODEXBOX_CRON_MODE=1` + `CODEXBOX_CRON_MODE_FILE=/path/to/cron.yaml`. 6-field cron schedules via croniter. Each job fires codex non-interactively with the given instruction. Runs together with Telegram mode (cron in-thread inside the telegram process) when both are enabled; otherwise it's its own foreground process.\n\nVia the `codexbox` wrapper (host-side trigger vars, translated into the container-side `CODEXBOX_CRON_MODE*` vars automatically):\n\n```bash\nCODEXBOX_MODE_CRON=1 CODEXBOX_MODE_CRON_FILE=/path/cron.yaml codexbox\n```\n\nRaw Docker:\n\n```bash\ndocker run -d --name codexbox-cron \\\n  -e CODEXBOX_CRON_MODE=1 \\\n  -e CODEXBOX_CRON_MODE_FILE=/cron/jobs.yaml \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD/cron.yaml:/cron/jobs.yaml:ro\" \\\n  -v \"$PWD:/workspace\" \\\n  psyb0t/codexbox:latest\n```\n\n```yaml\njobs:\n  - name: morning-standup\n    schedule: \"0 0 9 * * 1-5\"\n    instruction: |\n      Summarize what changed in /workspace since yesterday.\n      Be brief. One paragraph max.\n    workspace: myproject\n    telegram_chat_id: -100123\n    model: gpt-5.1-codex\n    thinking: low\n```\n\nEach run gets a history dir at `CODEXBOX_CRON_MODE_HISTORY_DIR/<workspace>/<timestamp>-<job>/` with `meta.json`, `stdout.log`, `stderr.log`, `result.txt` (plus `telegram.json` when telegram is also configured — the next run's prompt gets a \"prior run\" hint automatically).\n\n## Auth\n\nTwo independent auth layers:\n\n**1. Surface auth** (who can call the HTTP/MCP endpoints): `CODEXBOX_API_MODE_TOKEN` gates `/run`, `/files/*`, `/openai/v1/*`; `CODEXBOX_MCP_MODE_TOKEN` gates `/mcp` (its own bearer, no fallback to the API token). Empty = no auth on that surface.\n\n**2. codex's own upstream auth** (how codex talks to OpenAI): pick one —\n  - `OPENAI_API_KEY` — seeded into `$CODEX_HOME/auth.json` on every boot; safe to always set (never overwrites an existing ChatGPT-subscription login).\n  - ChatGPT subscription — one-time `codexbox login --device-auth` with `~/.codex` bind-mounted so the OAuth login survives container recreation. Bills against Plus/Pro/Team instead of API usage; the `*-codex`/`*-codex-mini` model slugs are rejected on a subscription account (400) — use the `gpt-5.6-*` family instead.\n\n## Typical Workflows\n\n**Fire a one-off prompt from a script:**\n\n```bash\ncurl -s http://localhost:8080/run \\\n  -H \"Authorization: Bearer $CODEXBOX_TOKEN\" -H \"Content-Type: application/json\" \\\n  -d '{\"prompt\": \"list every TODO in /workspace\", \"workspace\": \"/workspace\"}' | jq -r .text\n```\n\n**Drop-in OpenAI SDK swap:**\n\n```python\nfrom openai import OpenAI\nclient = OpenAI(base_url=\"http://localhost:8080/openai/v1\", api_key=\"your-secret\")\nresp = client.chat.completions.create(\n    model=\"gpt-5.1-codex\",\n    messages=[{\"role\": \"user\", \"content\": \"say HELLO\"}],\n)\nprint(resp.choices[0].message.content)\n```\n\n**Schema-constrained extraction:**\n\n```bash\ncurl -s http://localhost:8080/run \\\n  -H \"Authorization: Bearer $CODEXBOX_TOKEN\" -H \"Content-Type: application/json\" \\\n  -d '{\n        \"prompt\": \"extract the version + license from README.md\",\n        \"workspace\": \"/workspace\",\n        \"jsonSchema\": {\"type\": \"object\", \"properties\": {\"version\": {\"type\": \"string\"}, \"license\": {\"type\": \"string\"}}, \"required\": [\"version\", \"license\"]}\n      }' | jq .json\n```\n\n**Async run + poll:**\n\n```bash\nrun_id=$(curl -s http://localhost:8080/run -H \"Authorization: Bearer $CODEXBOX_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"prompt\": \"run the full test suite and summarize failures\", \"async\": true}' | jq -r .runId)\n\ncurl -s \"http://localhost:8080/run/result?runId=$run_id\" -H \"Authorization: Bearer $CODEXBOX_TOKEN\" | jq\n```\n\n**Cancel a stuck run:**\n\n```bash\ncurl -s -X DELETE \"http://localhost:8080/run/$run_id\" -H \"Authorization: Bearer $CODEXBOX_TOKEN\"\n```\n\nFile v0.6.4:_meta.json\n\n{\n  \"ownerId\": \"kn79dhvmpjng4rp2jjk8k0v5xx80ccbk\",\n  \"slug\": \"codexbox\",\n  \"version\": \"0.6.4\",\n  \"publishedAt\": 1790191429852\n}\n\nFile v0.6.4:references/setup.md\n\n# codexbox setup\n\nSee [SKILL.md](../SKILL.md#security--safety) for the full destructive-operation and unauthenticated-surface warnings before running any mode that binds a port.\n\n## Requirements\n\n- Docker\n- Codex auth: `OPENAI_API_KEY` (pay-as-you-go) or a ChatGPT Plus/Pro/Team subscription (`codexbox login --device-auth`)\n- Optional: SSH key for git-over-SSH inside the container (the installer generates one)\n\nFor ordinary agent work, use the installed `codexbox` command from the target\nworkspace. Do not replace it with a hand-written Docker invocation. The\nwrapper handles the workspace, state, SSH, image, and nested launch context.\n\n## Quick Install (wrapper)\n\nThe one-liner installer pulls the image, creates persistent Codex/SSH dirs, and installs the `codexbox` wrapper on `PATH`.\n\n**Recommended: download, inspect, then run.** Piping a remote script straight into bash executes unreviewed remote code as you. Download it, read it, then run it:\n\n```bash\ncurl -fsSL -o install.sh https://raw.githubusercontent.com/psyb0t/docker-codexbox/master/install.sh\nless install.sh          # read it before running anything\nbash install.sh          # minimal image — default\n# CODEXBOX_FULL=1 bash install.sh        # full image — every development tool pre-installed\n# bash install.sh codex                  # custom command name\n```\n\n`CODEXBOX_FULL=1` must be set before `install.sh` runs — the installer needs it in `bash`'s environment. The choice is baked into the installed wrapper; you don't need to set it again afterward.\n\n### Install from a local checkout\n\nFrom this repository, build and install without pulling a published codexbox\nimage:\n\n```bash\nmake install       # minimal image\nmake install-full  # full image\n\n# wrapper only — no build or pull; select full when needed\nmake install-wrapper\nCODEXBOX_FULL=1 make install-wrapper\n```\n\nThe installer-only `CODEXBOX_SRC_LOCAL=true` flag skips `docker pull` and\nrequires the selected local image to already exist. `make install-wrapper`\nuses that existing image without rebuilding it.\n\n**Verify:** `codexbox --version` should print the codex CLI version.\n\n```bash\ncodexbox                                  # interactive\ncodexbox exec \"inspect this workspace\"    # one-shot\nCODEXBOX_FULL=1 codexbox exec \"run tests\" # temporary full image\n```\n\nFor a wrapper-started server, use `CODEXBOX_ENV_` before every variable that\nmust reach the container. For example,\n`CODEXBOX_ENV_CODEXBOX_API_MODE=1 codexbox` starts API mode.\n\n### Sibling boxes\n\nInstall `codexbox`, `claudebox`, and `pibox` in the same command directory,\nnormally `/usr/local/bin`, to make the sibling commands available inside a\nbox. The parent mounts only the wrapper files read-only. A sibling wrapper then\nruns through the host Docker daemon and mounts its own host data directory.\n\n## Image Variants\n\n| Image | Tag | Contents |\n|---|---|---|\n| Minimal (default) | `psyb0t/codexbox:latest` | Codex, Node.js, Python, `uv`, Docker, Git, `jq`, `curl` |\n| Full | `psyb0t/codexbox:latest-full` | Everything in minimal + Go, gopls/Delve/golangci-lint/staticcheck/gofumpt, Python lint/type/test tooling, JS/TS lint/format/framework CLIs, GitHub CLI, Terraform, kubectl, Helm, build tools (CMake/ClangFormat/Valgrind/GDB/strace/ltrace), Postgres/MySQL/SQLite/Redis clients, editors/shell tools |\n\n`CODEXBOX_FULL` is binary: unset or `0` selects minimal, `1` selects full — any other value fails. `CODEXBOX_IMAGE` is the highest-priority explicit override if you want a specific tag regardless of `CODEXBOX_FULL`.\n\n## Manual Docker Use\n\nUse raw Docker only for an explicitly requested container deployment. Use the\nwrapper for interactive, one-shot, and local service runs. All direct Docker\nshapes for service deployment are in [../SKILL.md](../SKILL.md).\n\nMinimal foreground-mode boilerplate:\n\n```bash\ndocker run -d --name codexbox \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD:/workspace\" \\\n  -v \"$HOME/.codex:/home/aicode/.codex\" \\\n  <mode env vars here> \\\n  -p <port>:<port> \\\n  psyb0t/codexbox:latest\n```\n\n## Environment Variable Reference\n\n### Wrapper-only (host-side, read by `wrapper.sh`, not passed into the container as-is)\n\n| Var | Default | What it does |\n|---|---|---|\n| `OPENAI_API_KEY` | — | Forwarded into the container; seeds `auth.json` on boot |\n| `OPENAI_BASE_URL` | — | Point codex at an OpenAI-compatible endpoint instead of the default API |\n| `CODEXBOX_IMAGE` | installed image | Override the image the wrapper runs |\n| `CODEXBOX_FULL` | installed choice (`0` initially) | `0` forces minimal, `1` forces full |\n| `CODEXBOX_DATA_DIR` | `~/.codex` | Host dir mounted as `CODEX_HOME` (auth + config + sessions + per-workspace root-session pins) |\n| `CODEXBOX_SSH_DIR` | `~/.ssh/codexbox` | SSH key dir mounted into the container |\n| `CODEXBOX_MAX_MEM` | `10g` | Per-container memory limit |\n| `CODEXBOX_CONTAINER_NAME` | derived from `$PWD` | Override the per-workspace container name |\n| `CODEXBOX_ENV_*` | — | Forward arbitrary env into the container (prefix stripped: `CODEXBOX_ENV_FOO=bar` → `FOO=bar` inside) |\n| `CODEXBOX_MOUNT_*` | — | Mount extra host dirs (`/host:/container`, or a bare path for same-path-both-sides) |\n| `CODEXBOX_MODE_CRON` / `CODEXBOX_MODE_CRON_FILE` | — | Wrapper trigger: starts the cron scheduler as a long-running background container instead of the interactive one. Translated internally to `CODEXBOX_CRON_MODE` / `CODEXBOX_CRON_MODE_FILE` inside the container. |\n\n### Container-side mode flags\n\nNaming convention: `CODEXBOX_<MODE>_MODE=1` is the on/off flag, `CODEXBOX_<MODE>_MODE_<KNOB>=...` is its config.\n\n| Var | Default | What it does |\n|---|---|---|\n| `CODEXBOX_API_MODE` | `0` | Boot the HTTP API server (foreground) |\n| `CODEXBOX_TELEGRAM_MODE` | `0` | Boot the Telegram bot (foreground) |\n| `CODEXBOX_CRON_MODE` | `0` | Boot the cron scheduler (foreground; in-thread when telegram is also on) |\n| `CODEXBOX_MCP_MODE` | `0` | Expose MCP — mounted at `/mcp` in API mode, or as a standalone sidecar elsewhere |\n\nForeground modes (API/Telegram/Cron) are mutually exclusive, except Telegram+Cron together (cron runs in-thread inside the telegram process). API wins if set alongside anything else. MCP mode is independent — it coexists with whatever foreground mode is running, or with none at all (shell-only + MCP sidecar).\n\n### API mode config\n\n| Var | Default | What it does |\n|---|---|---|\n| `CODEXBOX_API_MODE_PORT` | `8080` | Port the API server binds to |\n| `CODEXBOX_API_MODE_TOKEN` | empty | Bearer token for the API surface (`/run`, `/files/*`, `/openai/v1/*`). Empty = no auth |\n\nWith `CODEXBOX_API_MODE_TOKEN` unset the API surface (`/run`, `/files/*`, `/openai/v1/*`) is unauthenticated — anyone who can reach it gets run-execution and full workspace file access. Set the token and bind to loopback / behind an authenticating proxy before exposing it beyond localhost.\n\n### Telegram mode config\n\n| Var | Default | What it does |\n|---|---|---|\n| `CODEXBOX_TELEGRAM_MODE_TOKEN` | — | Bot token from @BotFather |\n| `CODEXBOX_TELEGRAM_MODE_CONFIG` | `~/.aicodebox/telegram.yml` | Path to the telegram config YAML |\n| `CODEXBOX_TELEGRAM_MODE_OVERRIDES` | `~/.aicodebox/telegram_overrides.json` | Per-chat override store (model/effort/system prompts) |\n\n### Cron mode config\n\n| Var | Default | What it does |\n|---|---|---|\n| `CODEXBOX_CRON_MODE_FILE` | — | Path to the cron YAML |\n| `CODEXBOX_CRON_MODE_HISTORY_DIR` | `~/.aicodebox/cron/history` | Where cron writes per-run history dirs (`meta.json`, `stdout.log`, `stderr.log`, `result.txt`, `telegram.json`) |\n\n### MCP mode config\n\n| Var | Default | What it does |\n|---|---|---|\n| `CODEXBOX_MCP_MODE_PORT` | `8081` | Port the sidecar MCP server binds to (ignored when mounted inside API mode) |\n| `CODEXBOX_MCP_MODE_TOKEN` | empty | Bearer token for MCP. Empty = no auth. No fallback to `API_MODE_TOKEN` |\n\nWith `CODEXBOX_MCP_MODE_TOKEN` unset the MCP surface (`run_prompt`, `list_files`, `read_file`, `write_file`, `delete_file`) is unauthenticated — anyone who can reach it gets full workspace file access. This surface has its own bearer; setting `CODEXBOX_API_MODE_TOKEN` does not protect it. Set the token and bind to loopback / behind an authenticating proxy before exposing it beyond localhost.\n\n### Workspace & runtime\n\n| Var | Default | What it does |\n|---|---|---|\n| `CODEXBOX_WORKSPACE` | `/workspace` | Root workspace dir inside the container |\n| `CODEXBOX_CONTAINER_NAME` | `aicodebox` | Scopes per-container state files (auth, etc.) |\n| `CODEXBOX_AVAILABLE_MODELS` | — | **Required for API mode.** CSV list returned by `/openai/v1/models` and shown in the Telegram `/model` picker |\n| `CODEXBOX_AVAILABLE_EFFORTS` | `none,minimal,low,medium,high,xhigh,max` | Override the effort/reasoning list shown by the Telegram `/effort` picker |\n| `CODEXBOX_MODEL` | — | Default model passed to codex when a caller doesn't specify one |\n\nEvery `CODEXBOX_X` name above also works as `AICODEBOX_X` (the base image's native naming) — the entrypoint translates `CODEXBOX_X` to `AICODEBOX_X` when only the codexbox-prefixed one is set. If both are set, `AICODEBOX_X` wins.\n\n## Ports\n\n| Port | Default var | Service |\n|---|---|---|\n| 8080 | `CODEXBOX_API_MODE_PORT` | HTTP API (`/run`, `/files`, `/openai/v1/*`) + MCP mounted at `/mcp` when `CODEXBOX_MCP_MODE=1` |\n| 8081 | `CODEXBOX_MCP_MODE_PORT` | Standalone MCP sidecar — only when MCP mode is on and API mode is not |\n\nNo port is exposed by default in Telegram-only or cron-only or shell-only deployments (they're outbound-only / no HTTP surface unless MCP mode is also enabled).\n\n## Auth Setup\n\n### API key\n\n```bash\ndocker run --rm \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD/.codex:/home/aicode/.codex\" \\\n  psyb0t/codexbox:latest \\\n  exec \"say HELLO\"\n```\n\nSeeded into `$CODEX_HOME/auth.json` on every boot (`codex login --with-api-key` under the hood). Safe to leave set permanently — it never overwrites an existing ChatGPT-subscription login.\n\n### ChatGPT subscription\n\n```bash\ndocker run -it \\\n  -v \"$HOME/.codex:/home/aicode/.codex\" \\\n  psyb0t/codexbox:latest \\\n  login --device-auth\n```\n\nPrints a URL + short code for one-time browser approval. `~/.codex` **must** be bind-mounted or the login is lost when the container is removed. Every later run against the same bind-mounted `~/.codex` reuses it, no `OPENAI_API_KEY` needed. `codex login status` reports the active mode; `codex logout` clears it.\n\n## Management\n\n```bash\ncodexbox stop              # stop this dir's running container(s)\ncodexbox clear-session      # drop saved codex sessions (keeps auth + config)\ndocker logs -f codexbox-api # tail logs for a manually-run named container\ndocker pull psyb0t/codexbox:latest   # update\n```\n\n## Development / Testing\n\nRequires `psyb0t/docker-aicodebox` checked out next to this repo (`../docker-aicodebox`).\n\n```bash\nmake help              # list targets\nmake build-base        # build aicodebox-base from ../docker-aicodebox\nmake build              # build codexbox:local on top of it\nmake build-full         # build + tag the full toolchain variant\nmake test               # run the full e2e suite (needs .env.test — OPENAI_API_KEY, optional Telegram creds)\n```\n\nFile v0.6.4:skill-card.md\n\n## Description:\n\nInstall, configure, or run Codex through the codexbox wrapper, or connect to its HTTP, MCP, Telegram, or cron surfaces.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[psyb0t](https://clawhub.ai/user/psyb0t)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and engineers use this skill to install and operate Codex through a containerized wrapper, including local CLI use and optional HTTP, MCP, Telegram, or cron control surfaces.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: HTTP or MCP surfaces can provide Codex run execution and workspace file access without authentication when their bearer tokens are unset.\n\nMitigation: Set distinct API and MCP bearer tokens before enabling those modes, and bind services to localhost or place them behind a trusted authenticating proxy or VPN.\n\nRisk: Workspace file-control operations can delete or expose sensitive project data.\n\nMitigation: Use dedicated workspaces with minimal sensitive data, confirm deletion targets, and avoid shared sensitive workspaces for remote control-plane deployments.\n\nRisk: The documented one-line installer and mutable container tags can execute or pull code that changed after review.\n\nMitigation: Download and inspect installer code before running it, and prefer pinned Docker image digests for reviewed deployments.\n\n## Reference(s):\n\n- [codexbox setup](references/setup.md)\n- [codexbox source project](https://github.com/psyb0t/docker-codexbox)\n- [OpenAI Codex CLI](https://github.com/openai/codex)\n- [aicodebox container base](https://github.com/psyb0t/docker-aicodebox)\n- [ClawHub skill page](https://clawhub.ai/psyb0t/skills/codexbox)\n\n## Skill Output:\n\n**Output Type(s):** [guidance, markdown, shell commands, configuration]\n\n**Output Format:** [Markdown with inline bash, curl, Python, and YAML examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Guidance may include container, HTTP, MCP, Telegram, cron, authentication, and workspace file-management instructions.]\n\n## Skill Version(s):\n\n0.6.4 (source: server release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v0.6.3: 4 files, 13637 bytes\n\nFiles: references/setup.md (11205b), skill-card.md (2617b), SKILL.md (18568b), _meta.json (127b)\n\nFile v0.6.3:SKILL.md\n\n---\nname: codexbox\ndescription: \"Install, configure, or run Codex through the codexbox wrapper, or connect to its HTTP, MCP, Telegram, or cron surfaces.\"\nhomepage: https://github.com/psyb0t/docker-codexbox\nuser-invocable: true\nmetadata:\n  { \"openclaw\": { \"emoji\": \"🧑‍💻\", \"primaryEnv\": \"CODEXBOX_URL\", \"requires\": { \"bins\": [\"docker\", \"curl\"] } } }\n---\n\n# codexbox\n\n[OpenAI Codex CLI](https://github.com/openai/codex) inside an [aicodebox](https://github.com/psyb0t/docker-aicodebox) container, put on the network. codexbox is aicodebox's `codex` adapter — the HTTP/MCP/Telegram/cron surfaces are aicodebox's, the argv/JSON-event translation is codexbox's.\n\nFor installation and configuration, see [references/setup.md](references/setup.md).\n\n## Agent execution\n\nUse `codexbox` when it is on `PATH`. Run it from the workspace the user\nnamed. Do not assemble a new `docker run` command for routine interactive or\none-shot work. The wrapper owns the workspace mount, `~/.codex`, SSH state,\nimage selection, and session lifecycle.\n\n```bash\ncodexbox                                      # interactive Codex TUI\ncodexbox exec \"inspect this workspace\"        # one-shot work\nprintf '%s\\n' \"summarize README.md\" | codexbox exec -\nCODEXBOX_FULL=1 codexbox exec \"run the full suite\"\n```\n\nFor a wrapper-started server, prefix container variables with\n`CODEXBOX_ENV_`. For example,\n`CODEXBOX_ENV_CODEXBOX_API_MODE=1 codexbox` passes\n`CODEXBOX_API_MODE=1` into the container. Bare `CODEXBOX_API_MODE` is not\nforwarded and does not start the server.\n\nStart a local API and MCP server only when the user asks for one. Authenticate\nCodex with `codexbox login --device-auth` or `CODEXBOX_ENV_OPENAI_API_KEY`,\nthen set the actual model identifiers and distinct bearer tokens:\n\n```bash\nCODEXBOX_ENV_CODEXBOX_API_MODE=1 \\\nCODEXBOX_ENV_CODEXBOX_MCP_MODE=1 \\\nCODEXBOX_ENV_CODEXBOX_AVAILABLE_MODELS=your-model-id \\\nCODEXBOX_ENV_CODEXBOX_API_MODE_TOKEN=your-api-token \\\nCODEXBOX_ENV_CODEXBOX_MCP_MODE_TOKEN=your-mcp-token \\\ncodexbox\n```\n\nUse an HTTP or MCP endpoint only when the user asks for a service or provides\nan already-running remote URL. MCP plugins connect to a server. They do not\nreplace the local wrapper.\n\nIf `codexbox`, `claudebox`, and `pibox` were installed in the same command\ndirectory, a box can invoke a sibling command directly. The parent wrapper\npasses the real host paths and the sibling wrapper file. Do not set\n`AICODEBOX_HOST_*`, copy wrapper files, or manually mount another box's state\ndirectory. If the sibling command is absent, ask the user to install it or to\nchoose another approach.\n\n## Security & safety\n\n- **Set the mode tokens before exposing a port.** `CODEXBOX_API_MODE_TOKEN` (REST) and `CODEXBOX_MCP_MODE_TOKEN` (MCP) each default to no auth when unset, leaving that surface open to anyone who can reach it — run-execution plus full workspace file access. The two are independent (the MCP token has no fallback to the API token), so set whichever mode(s) you enable, and bind to loopback / behind an authenticating proxy. Per-mode detail: [HTTP REST API mode](#http-rest-api-mode), [MCP server mode](#mcp-server-mode).\n- **File deletion has no undo** — the run/file tools include a remove operation; only delete files the current task created, only when the user asked, and don't touch another caller's data on a shared workspace.\n- **The one-line installer pipes a remote script into `bash`.** Piping a remote script straight into bash executes unreviewed remote code as you. Prefer download → inspect → run (shown in [references/setup.md](references/setup.md)) unless you already trust the source and channel.\n\n## When To Use\n\n- Drive Codex from a script/CI job via `POST /run` instead of a terminal session.\n- Point an OpenAI-SDK client at Codex via `/openai/v1/chat/completions` (drop-in base-URL swap).\n- Wire Codex into an MCP-aware agent (Claude Code, another OpenClaw agent, Cursor) as a tool-calling backend.\n- Run Codex from Telegram on a phone, or on a cron schedule with no human in the loop.\n- Manage workspace files (upload/download/list/delete) over HTTP without a shell.\n\n## When NOT To Use\n\n- Need `--append-system-prompt` exact CLI semantics — codex has no such flag; codexbox maps `appendSystemPrompt` to `-c developer_instructions=...` (a developer-role message), not a raw prompt prepend.\n- Need per-tool allow/deny lists — codex has no name-based built-in tool allowlist. `toolsAllowlist` is accepted for cross-adapter API compatibility but logged and ignored. `noTools` is the only lever (drops shell/exec + web_search, forces the sandbox read-only).\n- Need codex's own MCP client/server support (`[mcp_servers.*]` in `config.toml`, `codex mcp-server` stdio) — that's a different, unrelated surface from the MCP mode documented here (which is aicodebox's file-ops + prompt-running MCP surface, not codex's).\n- Multiple concurrent runs against the *same* workspace — the API/OAI/MCP surfaces all serialize per-workspace; a second run against a busy workspace gets 409.\n\n## Shell mode\n\nThe default. `codexbox` (installed wrapper) or raw `docker run` drop you into `codex`'s interactive TUI, or run codex subcommands directly. No env flag — this is the base behavior with no `*_MODE` var set.\n\n```bash\nexport OPENAI_API_KEY=sk-...\ncodexbox                       # interactive TUI, continues the last session for this dir\ncodexbox --no-continue         # same, but starts a brand-new session\ncodexbox login --device-auth   # ChatGPT-subscription OAuth login\ncodexbox stop                  # stop this dir's running container(s)\n```\n\nThe wrapper mounts `$PWD` as the workspace, persists `~/.codex`, forwards `\"$@\"` straight to the image — any `codex` subcommand works (`codexbox mcp ...`, `codexbox doctor`, etc.). The sandbox-bypass flag is injected inside the container automatically.\n\n## One-shot exec mode\n\n`codex exec` (or `codexbox exec` through the wrapper) — single prompt in, output to your terminal, no TUI.\n\n```bash\ncodexbox exec \"fix the failing test in ./app\"\necho \"summarize README.md\" | codexbox exec -     # prompt via stdin\n```\n\nRaw Docker equivalent:\n\n```bash\ndocker run --rm \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD:/workspace\" \\\n  -v \"$PWD/.codex:/home/aicode/.codex\" \\\n  psyb0t/codexbox:latest \\\n  exec \"say HELLO\"\n```\n\n## API mode\n\n`CODEXBOX_API_MODE=1`. FastAPI server on `:8080` (override `CODEXBOX_API_MODE_PORT`). **Requires** `CODEXBOX_AVAILABLE_MODELS=<csv>` — API mode refuses to boot without it (codex has no hardcoded model slug to fall back to).\n\n```bash\ndocker run -d --name codexbox-api \\\n  -e CODEXBOX_API_MODE=1 \\\n  -e CODEXBOX_API_MODE_TOKEN=your-secret \\\n  -e CODEXBOX_AVAILABLE_MODELS=gpt-5.1-codex,gpt-5.1-codex-mini \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD:/workspace\" \\\n  -p 8080:8080 \\\n  psyb0t/codexbox:latest\n```\n\nWith `CODEXBOX_API_MODE_TOKEN` unset the API surface is unauthenticated — anyone who can reach `:8080` gets run-execution plus full workspace file access. Set the token and bind to loopback / behind an authenticating proxy before exposing it beyond localhost.\n\n| Method | Path | What it does |\n|--------|------|---------------|\n| `GET` | `/healthz` | liveness — `{ok, adapter}` |\n| `GET` | `/status` | in-flight runs + busy workspaces |\n| `POST` | `/run` | sync agent run → `{runId, workspace, exitCode, text, ...}` |\n| `GET` | `/run/result?runId=<id>` | poll an async run |\n| `DELETE` | `/run/{run_id}` | cancel an in-flight run |\n| `GET` | `/files` | list the workspace root |\n| `GET` | `/files/{path}` | list a sub-directory, or stream a file's bytes |\n| `PUT` | `/files/{path}` | upload — raw request body becomes the file contents; parent dirs auto-created |\n| `DELETE` | `/files/{path}` | delete a file (refuses directories — 400) |\n| `POST` | `/openai/v1/chat/completions` | OpenAI-compatible chat endpoint (see below) |\n| `GET` | `/openai/v1/models` | model list from `CODEXBOX_AVAILABLE_MODELS` |\n| `POST` | `/mcp` | MCP server, mounted only when `CODEXBOX_MCP_MODE=1` (see MCP mode) |\n\n`DELETE /files/{path}` removes a workspace file (no undo). Confirm the target path first and only remove files the current task created — see [Security & safety](#security--safety).\n\n`POST /run` body: `prompt` (required), `workspace`, `model`, `systemPrompt`, `appendSystemPrompt`, `jsonSchema`, `noContinue`, `resume`, `timeoutSeconds`, `thinking`, `noTools`, `toolsAllowlist`, `includeRaw`, `async`, `fireAndForget`. With `jsonSchema` set, the response adds `json`, `events`, `sessionId`, `usage`, `attempts` — codex has native `--output-schema` enforcement, so `jsonSchema` maps straight onto it (no self-correction retries needed, unlike adapters without native schema support).\n\nDefault programmatic runs continue the exact top-level Codex `exec` root\npinned to the canonical workspace. The first run creates the pin; existing\nworkspaces migrate their newest top-level `exec` rollout. Newer subagent\nrollouts are deliberately excluded because Codex rejects direct turns on\nmulti-agent children. Explicit `resume` re-pins the confirmed thread;\n`noContinue` is ephemeral and leaves the workspace pin unchanged.\n\n```bash\ncurl -s http://localhost:8080/run \\\n  --oauth2-bearer \"$CODEXBOX_API_MODE_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"prompt\": \"say HELLO\", \"workspace\": \"/workspace\"}'\n```\n\nAsync: set `\"async\": true`, poll `GET /run/result?runId=<id>` until `status != \"running\"`.\n\nAll `/files/*` paths are resolved against the workspace root with traversal checking — `..` segments that escape the root return 400.\n\n```bash\ncurl -sS -X PUT --oauth2-bearer \"$CODEXBOX_API_MODE_TOKEN\" \\\n  --data-binary @local.txt http://localhost:8080/files/notes/hello.txt\n\ncurl -sS --oauth2-bearer \"$CODEXBOX_API_MODE_TOKEN\" \\\n  http://localhost:8080/files/notes/hello.txt\n```\n\n## OpenAI-compatible endpoint\n\n`POST /openai/v1/chat/completions` (mounted under API mode, same port/token). Point any OpenAI SDK's base URL at `http://host:8080/openai/v1` and call it like the real API.\n\n- **Streaming**: `\"stream\": true` — real incremental SSE for plain chat. When `tools`/`tool_choice` or a schema constraint is also set, the full answer is computed first, then replayed as a single-shot SSE stream (tool-call/schema turns can't be streamed token-by-token).\n- **Tools**: OpenAI-style `tools` / `tool_choice` in the request body. codex runs its own tools internally, so client-executed tool calling is bridged — codexbox injects an \"emit `{\"tool_calls\":[...]}` and stop\" protocol into the system prompt and parses codex's textual output back into OpenAI `tool_calls`. Stateless: resend full history each round-trip, same as the standard OpenAI tool loop.\n- **`response_format`**: `{\"type\":\"text\"}` (default), `{\"type\":\"json_object\"}` (force parseable JSON, no schema), or `{\"type\":\"json_schema\",\"json_schema\":{\"name\",\"schema\",\"strict?\"}}` (schema-constrained — same native `--output-schema` path as `/run`'s `jsonSchema`). Composable with `tools`: a tool-call turn isn't schema-checked, only the final non-tool answer is.\n- Custom headers (`x-aicodebox-*` prefix, `x-claude-*` accepted as aliases for workspace/continue/append-system-prompt) cover what the OpenAI wire format has no field for: `x-aicodebox-workspace`, `x-aicodebox-continue`, `x-aicodebox-resume`, `x-aicodebox-json-schema` (fallback if `response_format` isn't set), `x-aicodebox-no-tools`, `x-aicodebox-tools-allowlist`, `x-aicodebox-timeout-seconds`, `x-aicodebox-extra-args`.\n\n```bash\ncurl -s http://localhost:8080/openai/v1/chat/completions \\\n  --oauth2-bearer \"$CODEXBOX_API_MODE_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\n        \"model\": \"gpt-5.1-codex\",\n        \"messages\": [{\"role\": \"user\", \"content\": \"say HELLO\"}],\n        \"stream\": false\n      }'\n```\n\n## MCP mode\n\n`CODEXBOX_MCP_MODE=1`. Exposes the aicodebox base's own MCP surface — file ops + prompt running as tools: `run_prompt`, `list_files`, `read_file`, `write_file`, `delete_file`. This is separate from codex's own MCP client/server support (`config.toml` `[mcp_servers.*]`, `codex mcp-server` stdio) — neither of those is wired up by codexbox.\n\nCoexists with any foreground mode:\n\n| Foreground | MCP placement |\n|---|---|\n| API mode (`CODEXBOX_API_MODE=1`) | mounted at `/mcp` on the API port — no extra process |\n| Telegram / Cron / shell-only | sidecar uvicorn on `CODEXBOX_MCP_MODE_PORT` (default `8081`), served at the process root |\n\nAuth: `CODEXBOX_MCP_MODE_TOKEN=<token>` — bearer in `Authorization: Bearer ...`, or `?apiToken=...` for clients that can't set headers. Empty = no auth. **No fallback to `API_MODE_TOKEN`** — MCP has its own bearer, checked independently.\n\nWith `CODEXBOX_MCP_MODE_TOKEN` unset the MCP surface (`run_prompt`, `list_files`, `read_file`, `write_file`, `delete_file`) is unauthenticated — anyone who can reach `/mcp` or the sidecar port gets run-execution plus full workspace file access. This surface has its own bearer; setting `CODEXBOX_API_MODE_TOKEN` does not protect it. Set the token and bind to loopback / behind an authenticating proxy before exposing it beyond localhost.\n\n```bash\ndocker run -d --name codexbox-api \\\n  -e CODEXBOX_API_MODE=1 -e CODEXBOX_API_MODE_TOKEN=your-secret \\\n  -e CODEXBOX_MCP_MODE=1 -e CODEXBOX_MCP_MODE_TOKEN=your-mcp-secret \\\n  -e CODEXBOX_AVAILABLE_MODELS=gpt-5.1-codex \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD:/workspace\" -p 8080:8080 \\\n  psyb0t/codexbox:latest\n```\n\nWire into an MCP-aware client:\n\n```bash\nclaude mcp add --transport http codexbox http://localhost:8080/mcp \\\n  --header \"Authorization: Bearer your-mcp-secret\"\n```\n\n## Telegram mode\n\n`CODEXBOX_TELEGRAM_MODE=1` + `CODEXBOX_TELEGRAM_MODE_TOKEN=<token-from-BotFather>`.\n\n```bash\ndocker run -d --name codexbox-tg \\\n  -e CODEXBOX_TELEGRAM_MODE=1 \\\n  -e CODEXBOX_TELEGRAM_MODE_TOKEN=123456:ABC-your-bot-token \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD:/workspace\" \\\n  -v \"$HOME/.aicodebox:/home/aicode/.aicodebox\" \\\n  psyb0t/codexbox:latest\n```\n\n- Text in → codex runs → Markdown→HTML rendered response back.\n- File uploads land in the chat's workspace. `[SEND_FILE: path]` in codex's output delivers workspace files as Telegram attachments.\n- Per-chat overrides: `/model`, `/effort` (codex's `model_reasoning_effort` levels), `/system_prompt`, `/append_system_prompt`. Persisted to `CODEXBOX_TELEGRAM_MODE_OVERRIDES`.\n- `/cancel` kills the in-flight run, `/reload` re-reads config, `/config` dumps merged settings, `/fetch <path>` downloads a file.\n\nAccess control + per-chat config lives in a YAML file (`CODEXBOX_TELEGRAM_MODE_CONFIG`, default `~/.aicodebox/telegram.yml`):\n\n```yaml\nallowed_chats: [-100123, 42]\ndefault:\n  model: gpt-5.1-codex\n  workspace: shared\nchats:\n  -100123:\n    workspace: alpha\n    allowed_users: [10, 20]\n```\n\n## Cron mode\n\n`CODEXBOX_CRON_MODE=1` + `CODEXBOX_CRON_MODE_FILE=/path/to/cron.yaml`. 6-field cron schedules via croniter. Each job fires codex non-interactively with the given instruction. Runs together with Telegram mode (cron in-thread inside the telegram process) when both are enabled; otherwise it's its own foreground process.\n\nVia the `codexbox` wrapper (host-side trigger vars, translated into the container-side `CODEXBOX_CRON_MODE*` vars automatically):\n\n```bash\nCODEXBOX_MODE_CRON=1 CODEXBOX_MODE_CRON_FILE=/path/cron.yaml codexbox\n```\n\nRaw Docker:\n\n```bash\ndocker run -d --name codexbox-cron \\\n  -e CODEXBOX_CRON_MODE=1 \\\n  -e CODEXBOX_CRON_MODE_FILE=/cron/jobs.yaml \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD/cron.yaml:/cron/jobs.yaml:ro\" \\\n  -v \"$PWD:/workspace\" \\\n  psyb0t/codexbox:latest\n```\n\n```yaml\njobs:\n  - name: morning-standup\n    schedule: \"0 0 9 * * 1-5\"\n    instruction: |\n      Summarize what changed in /workspace since yesterday.\n      Be brief. One paragraph max.\n    workspace: myproject\n    telegram_chat_id: -100123\n    model: gpt-5.1-codex\n    thinking: low\n```\n\nEach run gets a history dir at `CODEXBOX_CRON_MODE_HISTORY_DIR/<workspace>/<timestamp>-<job>/` with `meta.json`, `stdout.log`, `stderr.log`, `result.txt` (plus `telegram.json` when telegram is also configured — the next run's prompt gets a \"prior run\" hint automatically).\n\n## Auth\n\nTwo independent auth layers:\n\n**1. Surface auth** (who can call the HTTP/MCP endpoints): `CODEXBOX_API_MODE_TOKEN` gates `/run`, `/files/*`, `/openai/v1/*`; `CODEXBOX_MCP_MODE_TOKEN` gates `/mcp` (its own bearer, no fallback to the API token). Empty = no auth on that surface.\n\n**2. codex's own upstream auth** (how codex talks to OpenAI): pick one —\n  - `OPENAI_API_KEY` — seeded into `$CODEX_HOME/auth.json` on every boot; safe to always set (never overwrites an existing ChatGPT-subscription login).\n  - ChatGPT subscription — one-time `codexbox login --device-auth` with `~/.codex` bind-mounted so the OAuth login survives container recreation. Bills against Plus/Pro/Team instead of API usage; the `*-codex`/`*-codex-mini` model slugs are rejected on a subscription account (400) — use the `gpt-5.6-*` family instead.\n\n## Typical Workflows\n\n**Fire a one-off prompt from a script:**\n\n```bash\ncurl -s http://localhost:8080/run \\\n  -H \"Authorization: Bearer $CODEXBOX_TOKEN\" -H \"Content-Type: application/json\" \\\n  -d '{\"prompt\": \"list every TODO in /workspace\", \"workspace\": \"/workspace\"}' | jq -r .text\n```\n\n**Drop-in OpenAI SDK swap:**\n\n```python\nfrom openai import OpenAI\nclient = OpenAI(base_url=\"http://localhost:8080/openai/v1\", api_key=\"your-secret\")\nresp = client.chat.completions.create(\n    model=\"gpt-5.1-codex\",\n    messages=[{\"role\": \"user\", \"content\": \"say HELLO\"}],\n)\nprint(resp.choices[0].message.content)\n```\n\n**Schema-constrained extraction:**\n\n```bash\ncurl -s http://localhost:8080/run \\\n  -H \"Authorization: Bearer $CODEXBOX_TOKEN\" -H \"Content-Type: application/json\" \\\n  -d '{\n        \"prompt\": \"extract the version + license from README.md\",\n        \"workspace\": \"/workspace\",\n        \"jsonSchema\": {\"type\": \"object\", \"properties\": {\"version\": {\"type\": \"string\"}, \"license\": {\"type\": \"string\"}}, \"required\": [\"version\", \"license\"]}\n      }' | jq .json\n```\n\n**Async run + poll:**\n\n```bash\nrun_id=$(curl -s http://localhost:8080/run -H \"Authorization: Bearer $CODEXBOX_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"prompt\": \"run the full test suite and summarize failures\", \"async\": true}' | jq -r .runId)\n\ncurl -s \"http://localhost:8080/run/result?runId=$run_id\" -H \"Authorization: Bearer $CODEXBOX_TOKEN\" | jq\n```\n\n**Cancel a stuck run:**\n\n```bash\ncurl -s -X DELETE \"http://localhost:8080/run/$run_id\" -H \"Authorization: Bearer $CODEXBOX_TOKEN\"\n```\n\nFile v0.6.3:_meta.json\n\n{\n  \"ownerId\": \"kn79dhvmpjng4rp2jjk8k0v5xx80ccbk\",\n  \"slug\": \"codexbox\",\n  \"version\": \"0.6.3\",\n  \"publishedAt\": 1789386658174\n}\n\nFile v0.6.3:references/setup.md\n\n# codexbox setup\n\nSee [SKILL.md](../SKILL.md#security--safety) for the full destructive-operation and unauthenticated-surface warnings before running any mode that binds a port.\n\n## Requirements\n\n- Docker\n- Codex auth: `OPENAI_API_KEY` (pay-as-you-go) or a ChatGPT Plus/Pro/Team subscription (`codexbox login --device-auth`)\n- Optional: SSH key for git-over-SSH inside the container (the installer generates one)\n\nFor ordinary agent work, use the installed `codexbox` command from the target\nworkspace. Do not replace it with a hand-written Docker invocation. The\nwrapper handles the workspace, state, SSH, image, and nested launch context.\n\n## Quick Install (wrapper)\n\nThe one-liner installer pulls the image, creates persistent Codex/SSH dirs, and installs the `codexbox` wrapper on `PATH`.\n\n**Recommended: download, inspect, then run.** Piping a remote script straight into bash executes unreviewed remote code as you. Download it, read it, then run it:\n\n```bash\ncurl -fsSL -o install.sh https://raw.githubusercontent.com/psyb0t/docker-codexbox/master/install.sh\nless install.sh          # read it before running anything\nbash install.sh          # minimal image — default\n# CODEXBOX_FULL=1 bash install.sh        # full image — every development tool pre-installed\n# bash install.sh codex                  # custom command name\n```\n\n`CODEXBOX_FULL=1` must be set before `install.sh` runs — the installer needs it in `bash`'s environment. The choice is baked into the installed wrapper; you don't need to set it again afterward.\n\n### Install from a local checkout\n\nFrom this repository, build and install without pulling a published codexbox\nimage:\n\n```bash\nmake install       # minimal image\nmake install-full  # full image\n\n# wrapper only — no build or pull; select full when needed\nmake install-wrapper\nCODEXBOX_FULL=1 make install-wrapper\n```\n\nThe installer-only `CODEXBOX_SRC_LOCAL=true` flag skips `docker pull` and\nrequires the selected local image to already exist. `make install-wrapper`\nuses that existing image without rebuilding it.\n\n**Verify:** `codexbox --version` should print the codex CLI version.\n\n```bash\ncodexbox                                  # interactive\ncodexbox exec \"inspect this workspace\"    # one-shot\nCODEXBOX_FULL=1 codexbox exec \"run tests\" # temporary full image\n```\n\nFor a wrapper-started server, use `CODEXBOX_ENV_` before every variable that\nmust reach the container. For example,\n`CODEXBOX_ENV_CODEXBOX_API_MODE=1 codexbox` starts API mode.\n\n### Sibling boxes\n\nInstall `codexbox`, `claudebox`, and `pibox` in the same command directory,\nnormally `/usr/local/bin`, to make the sibling commands available inside a\nbox. The parent mounts only the wrapper files read-only. A sibling wrapper then\nruns through the host Docker daemon and mounts its own host data directory.\n\n## Image Variants\n\n| Image | Tag | Contents |\n|---|---|---|\n| Minimal (default) | `psyb0t/codexbox:latest` | Codex, Node.js, Python, `uv`, Docker, Git, `jq`, `curl` |\n| Full | `psyb0t/codexbox:latest-full` | Everything in minimal + Go, gopls/Delve/golangci-lint/staticcheck/gofumpt, Python lint/type/test tooling, JS/TS lint/format/framework CLIs, GitHub CLI, Terraform, kubectl, Helm, build tools (CMake/ClangFormat/Valgrind/GDB/strace/ltrace), Postgres/MySQL/SQLite/Redis clients, editors/shell tools |\n\n`CODEXBOX_FULL` is binary: unset or `0` selects minimal, `1` selects full — any other value fails. `CODEXBOX_IMAGE` is the highest-priority explicit override if you want a specific tag regardless of `CODEXBOX_FULL`.\n\n## Manual Docker Use\n\nUse raw Docker only for an explicitly requested container deployment. Use the\nwrapper for interactive, one-shot, and local service runs. All direct Docker\nshapes for service deployment are in [../SKILL.md](../SKILL.md).\n\nMinimal foreground-mode boilerplate:\n\n```bash\ndocker run -d --name codexbox \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD:/workspace\" \\\n  -v \"$HOME/.codex:/home/aicode/.codex\" \\\n  <mode env vars here> \\\n  -p <port>:<port> \\\n  psyb0t/codexbox:latest\n```\n\n## Environment Variable Reference\n\n### Wrapper-only (host-side, read by `wrapper.sh`, not passed into the container as-is)\n\n| Var | Default | What it does |\n|---|---|---|\n| `OPENAI_API_KEY` | — | Forwarded into the container; seeds `auth.json` on boot |\n| `OPENAI_BASE_URL` | — | Point codex at an OpenAI-compatible endpoint instead of the default API |\n| `CODEXBOX_IMAGE` | installed image | Override the image the wrapper runs |\n| `CODEXBOX_FULL` | installed choice (`0` initially) | `0` forces minimal, `1` forces full |\n| `CODEXBOX_DATA_DIR` | `~/.codex` | Host dir mounted as `CODEX_HOME` (auth + config + sessions + per-workspace root-session pins) |\n| `CODEXBOX_SSH_DIR` | `~/.ssh/codexbox` | SSH key dir mounted into the container |\n| `CODEXBOX_MAX_MEM` | `10g` | Per-container memory limit |\n| `CODEXBOX_CONTAINER_NAME` | derived from `$PWD` | Override the per-workspace container name |\n| `CODEXBOX_ENV_*` | — | Forward arbitrary env into the container (prefix stripped: `CODEXBOX_ENV_FOO=bar` → `FOO=bar` inside) |\n| `CODEXBOX_MOUNT_*` | — | Mount extra host dirs (`/host:/container`, or a bare path for same-path-both-sides) |\n| `CODEXBOX_MODE_CRON` / `CODEXBOX_MODE_CRON_FILE` | — | Wrapper trigger: starts the cron scheduler as a long-running background container instead of the interactive one. Translated internally to `CODEXBOX_CRON_MODE` / `CODEXBOX_CRON_MODE_FILE` inside the container. |\n\n### Container-side mode flags\n\nNaming convention: `CODEXBOX_<MODE>_MODE=1` is the on/off flag, `CODEXBOX_<MODE>_MODE_<KNOB>=...` is its config.\n\n| Var | Default | What it does |\n|---|---|---|\n| `CODEXBOX_API_MODE` | `0` | Boot the HTTP API server (foreground) |\n| `CODEXBOX_TELEGRAM_MODE` | `0` | Boot the Telegram bot (foreground) |\n| `CODEXBOX_CRON_MODE` | `0` | Boot the cron scheduler (foreground; in-thread when telegram is also on) |\n| `CODEXBOX_MCP_MODE` | `0` | Expose MCP — mounted at `/mcp` in API mode, or as a standalone sidecar elsewhere |\n\nForeground modes (API/Telegram/Cron) are mutually exclusive, except Telegram+Cron together (cron runs in-thread inside the telegram process). API wins if set alongside anything else. MCP mode is independent — it coexists with whatever foreground mode is running, or with none at all (shell-only + MCP sidecar).\n\n### API mode config\n\n| Var | Default | What it does |\n|---|---|---|\n| `CODEXBOX_API_MODE_PORT` | `8080` | Port the API server binds to |\n| `CODEXBOX_API_MODE_TOKEN` | empty | Bearer token for the API surface (`/run`, `/files/*`, `/openai/v1/*`). Empty = no auth |\n\nWith `CODEXBOX_API_MODE_TOKEN` unset the API surface (`/run`, `/files/*`, `/openai/v1/*`) is unauthenticated — anyone who can reach it gets run-execution and full workspace file access. Set the token and bind to loopback / behind an authenticating proxy before exposing it beyond localhost.\n\n### Telegram mode config\n\n| Var | Default | What it does |\n|---|---|---|\n| `CODEXBOX_TELEGRAM_MODE_TOKEN` | — | Bot token from @BotFather |\n| `CODEXBOX_TELEGRAM_MODE_CONFIG` | `~/.aicodebox/telegram.yml` | Path to the telegram config YAML |\n| `CODEXBOX_TELEGRAM_MODE_OVERRIDES` | `~/.aicodebox/telegram_overrides.json` | Per-chat override store (model/effort/system prompts) |\n\n### Cron mode config\n\n| Var | Default | What it does |\n|---|---|---|\n| `CODEXBOX_CRON_MODE_FILE` | — | Path to the cron YAML |\n| `CODEXBOX_CRON_MODE_HISTORY_DIR` | `~/.aicodebox/cron/history` | Where cron writes per-run history dirs (`meta.json`, `stdout.log`, `stderr.log`, `result.txt`, `telegram.json`) |\n\n### MCP mode config\n\n| Var | Default | What it does |\n|---|---|---|\n| `CODEXBOX_MCP_MODE_PORT` | `8081` | Port the sidecar MCP server binds to (ignored when mounted inside API mode) |\n| `CODEXBOX_MCP_MODE_TOKEN` | empty | Bearer token for MCP. Empty = no auth. No fallback to `API_MODE_TOKEN` |\n\nWith `CODEXBOX_MCP_MODE_TOKEN` unset the MCP surface (`run_prompt`, `list_files`, `read_file`, `write_file`, `delete_file`) is unauthenticated — anyone who can reach it gets full workspace file access. This surface has its own bearer; setting `CODEXBOX_API_MODE_TOKEN` does not protect it. Set the token and bind to loopback / behind an authenticating proxy before exposing it beyond localhost.\n\n### Workspace & runtime\n\n| Var | Default | What it does |\n|---|---|---|\n| `CODEXBOX_WORKSPACE` | `/workspace` | Root workspace dir inside the container |\n| `CODEXBOX_CONTAINER_NAME` | `aicodebox` | Scopes per-container state files (auth, etc.) |\n| `CODEXBOX_AVAILABLE_MODELS` | — | **Required for API mode.** CSV list returned by `/openai/v1/models` and shown in the Telegram `/model` picker |\n| `CODEXBOX_AVAILABLE_EFFORTS` | `none,minimal,low,medium,high,xhigh,max` | Override the effort/reasoning list shown by the Telegram `/effort` picker |\n| `CODEXBOX_MODEL` | — | Default model passed to codex when a caller doesn't specify one |\n\nEvery `CODEXBOX_X` name above also works as `AICODEBOX_X` (the base image's native naming) — the entrypoint translates `CODEXBOX_X` to `AICODEBOX_X` when only the codexbox-prefixed one is set. If both are set, `AICODEBOX_X` wins.\n\n## Ports\n\n| Port | Default var | Service |\n|---|---|---|\n| 8080 | `CODEXBOX_API_MODE_PORT` | HTTP API (`/run`, `/files`, `/openai/v1/*`) + MCP mounted at `/mcp` when `CODEXBOX_MCP_MODE=1` |\n| 8081 | `CODEXBOX_MCP_MODE_PORT` | Standalone MCP sidecar — only when MCP mode is on and API mode is not |\n\nNo port is exposed by default in Telegram-only or cron-only or shell-only deployments (they're outbound-only / no HTTP surface unless MCP mode is also enabled).\n\n## Auth Setup\n\n### API key\n\n```bash\ndocker run --rm \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD/.codex:/home/aicode/.codex\" \\\n  psyb0t/codexbox:latest \\\n  exec \"say HELLO\"\n```\n\nSeeded into `$CODEX_HOME/auth.json` on every boot (`codex login --with-api-key` under the hood). Safe to leave set permanently — it never overwrites an existing ChatGPT-subscription login.\n\n### ChatGPT subscription\n\n```bash\ndocker run -it \\\n  -v \"$HOME/.codex:/home/aicode/.codex\" \\\n  psyb0t/codexbox:latest \\\n  login --device-auth\n```\n\nPrints a URL + short code for one-time browser approval. `~/.codex` **must** be bind-mounted or the login is lost when the container is removed. Every later run against the same bind-mounted `~/.codex` reuses it, no `OPENAI_API_KEY` needed. `codex login status` reports the active mode; `codex logout` clears it.\n\n## Management\n\n```bash\ncodexbox stop              # stop this dir's running container(s)\ncodexbox clear-session      # drop saved codex sessions (keeps auth + config)\ndocker logs -f codexbox-api # tail logs for a manually-run named container\ndocker pull psyb0t/codexbox:latest   # update\n```\n\n## Development / Testing\n\nRequires `psyb0t/docker-aicodebox` checked out next to this repo (`../docker-aicodebox`).\n\n```bash\nmake help              # list targets\nmake build-base        # build aicodebox-base from ../docker-aicodebox\nmake build              # build codexbox:local on top of it\nmake build-full         # build + tag the full toolchain variant\nmake test               # run the full e2e suite (needs .env.test — OPENAI_API_KEY, optional Telegram creds)\n```\n\nFile v0.6.3:skill-card.md\n\n## Description:\n\nInstall, configure, or run Codex through the codexbox wrapper, or connect to its HTTP, MCP, Telegram, or cron surfaces.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[psyb0t](https://clawhub.ai/user/psyb0t)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and engineers use codexbox to run Codex in a containerized workspace, automate one-shot or scheduled Codex runs, and expose Codex through HTTP, MCP, Telegram, or OpenAI-compatible endpoints when those service modes are explicitly needed.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Unauthenticated API or MCP service modes can expose prompt execution and workspace file access to anyone who can reach the port.\n\nMitigation: Set strong distinct API and MCP bearer tokens before enabling service modes, and bind services to localhost or place them behind an authenticated proxy.\n\nRisk: The Docker image and one-line installer execute code from this third-party publisher, and mutable remote sources can change over time.\n\nMitigation: Install only after reviewing the publisher and source; prefer pinned image digests, a local checkout, or downloading and inspecting the installer before running it.\n\nRisk: Workspace mounts and file deletion endpoints can affect local files, including deleting files without undo.\n\nMitigation: Avoid broad extra mounts, scope workspaces narrowly, and treat delete and run endpoints as administrative access that should be used only for intended task files.\n\n## Reference(s):\n\n- [codexbox setup](references/setup.md)\n- [ClawHub skill page](https://clawhub.ai/psyb0t/skills/codexbox)\n- [codexbox repository](https://github.com/psyb0t/docker-codexbox)\n- [OpenAI Codex CLI](https://github.com/openai/codex)\n- [aicodebox repository](https://github.com/psyb0t/docker-aicodebox)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Markdown, Code, Shell commands, Configuration, Guidance]\n\n**Output Format:** [Markdown with inline shell commands, code snippets, JSON examples, and configuration guidance]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May include commands for wrapper use, Docker deployment, REST requests, MCP setup, Telegram mode, cron jobs, and authentication configuration.]\n\n## Skill Version(s):\n\n0.6.3 (source: ClawHub release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v0.6.2: 4 files, 12974 bytes\n\nFiles: references/setup.md (10614b), skill-card.md (2594b), SKILL.md (17422b), _meta.json (127b)\n\nFile v0.6.2:SKILL.md\n\n---\nname: codexbox\ndescription: OpenAI Codex CLI running inside an aicodebox container, put on the network. Exposes seven ways in — interactive shell, one-shot exec, an HTTP REST API (workspace file ops, sync/async prompt runs with run-id polling), an OpenAI-compatible /openai/v1/chat/completions endpoint (streaming, client-executed tools/tool_choice, response_format/JSON-schema), an MCP server (streamable HTTP, mounted at /mcp in API mode or as a sidecar), a Telegram bot, and a cron scheduler that fires codex on a schedule. Auth is bearer-token per surface (CODEXBOX_API_MODE_TOKEN, CODEXBOX_MCP_MODE_TOKEN) plus codex's own OpenAI API-key or ChatGPT-subscription login. Use when the user wants to run OpenAI Codex programmatically over HTTP/MCP/Telegram/cron instead of only in a local terminal, or wants an OpenAI-compatible endpoint backed by Codex.\nhomepage: https://github.com/psyb0t/docker-codexbox\nuser-invocable: true\nmetadata:\n  { \"openclaw\": { \"emoji\": \"🧑‍💻\", \"primaryEnv\": \"CODEXBOX_URL\", \"requires\": { \"bins\": [\"docker\", \"curl\"] } } }\n---\n\n# codexbox\n\n[OpenAI Codex CLI](https://github.com/openai/codex) inside an [aicodebox](https://github.com/psyb0t/docker-aicodebox) container, put on the network. codexbox is aicodebox's `codex` adapter — the HTTP/MCP/Telegram/cron surfaces are aicodebox's, the argv/JSON-event translation is codexbox's.\n\nFor installation and configuration, see [references/setup.md](references/setup.md).\n\n## Security & safety\n\n- **Set the mode tokens before exposing a port.** `CODEXBOX_API_MODE_TOKEN` (REST) and `CODEXBOX_MCP_MODE_TOKEN` (MCP) each default to no auth when unset, leaving that surface open to anyone who can reach it — run-execution plus full workspace file access. The two are independent (the MCP token has no fallback to the API token), so set whichever mode(s) you enable, and bind to loopback / behind an authenticating proxy. Per-mode detail: [HTTP REST API mode](#http-rest-api-mode), [MCP server mode](#mcp-server-mode).\n- **File deletion has no undo** — the run/file tools include a remove operation; only delete files the current task created, only when the user asked, and don't touch another caller's data on a shared workspace.\n- **The one-line installer pipes a remote script into `bash`.** Piping a remote script straight into bash executes unreviewed remote code as you. Prefer download → inspect → run (shown in [references/setup.md](references/setup.md)) unless you already trust the source and channel.\n\n## When To Use\n\n- Drive Codex from a script/CI job via `POST /run` instead of a terminal session.\n- Point an OpenAI-SDK client at Codex via `/openai/v1/chat/completions` (drop-in base-URL swap).\n- Wire Codex into an MCP-aware agent (Claude Code, another OpenClaw agent, Cursor) as a tool-calling backend.\n- Run Codex from Telegram on a phone, or on a cron schedule with no human in the loop.\n- Manage workspace files (upload/download/list/delete) over HTTP without a shell.\n\n## When NOT To Use\n\n- Need `--append-system-prompt` exact CLI semantics — codex has no such flag; codexbox maps `appendSystemPrompt` to `-c developer_instructions=...` (a developer-role message), not a raw prompt prepend.\n- Need per-tool allow/deny lists — codex has no name-based built-in tool allowlist. `toolsAllowlist` is accepted for cross-adapter API compatibility but logged and ignored. `noTools` is the only lever (drops shell/exec + web_search, forces the sandbox read-only).\n- Need codex's own MCP client/server support (`[mcp_servers.*]` in `config.toml`, `codex mcp-server` stdio) — that's a different, unrelated surface from the MCP mode documented here (which is aicodebox's file-ops + prompt-running MCP surface, not codex's).\n- Multiple concurrent runs against the *same* workspace — the API/OAI/MCP surfaces all serialize per-workspace; a second run against a busy workspace gets 409.\n\n## Shell mode\n\nThe default. `codexbox` (installed wrapper) or raw `docker run` drop you into `codex`'s interactive TUI, or run codex subcommands directly. No env flag — this is the base behavior with no `*_MODE` var set.\n\n```bash\nexport OPENAI_API_KEY=sk-...\ncodexbox                       # interactive TUI, continues the last session for this dir\ncodexbox --no-continue         # same, but starts a brand-new session\ncodexbox login --device-auth   # ChatGPT-subscription OAuth login\ncodexbox stop                  # stop this dir's running container(s)\n```\n\nThe wrapper mounts `$PWD` as the workspace, persists `~/.codex`, forwards `\"$@\"` straight to the image — any `codex` subcommand works (`codexbox mcp ...`, `codexbox doctor`, etc.). The sandbox-bypass flag is injected inside the container automatically.\n\n## One-shot exec mode\n\n`codex exec` (or `codexbox exec` through the wrapper) — single prompt in, output to your terminal, no TUI.\n\n```bash\ncodexbox exec \"fix the failing test in ./app\"\necho \"summarize README.md\" | codexbox exec -     # prompt via stdin\n```\n\nRaw Docker equivalent:\n\n```bash\ndocker run --rm \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD:/workspace\" \\\n  -v \"$PWD/.codex:/home/aicode/.codex\" \\\n  psyb0t/codexbox:latest \\\n  exec \"say HELLO\"\n```\n\n## API mode\n\n`CODEXBOX_API_MODE=1`. FastAPI server on `:8080` (override `CODEXBOX_API_MODE_PORT`). **Requires** `CODEXBOX_AVAILABLE_MODELS=<csv>` — API mode refuses to boot without it (codex has no hardcoded model slug to fall back to).\n\n```bash\ndocker run -d --name codexbox-api \\\n  -e CODEXBOX_API_MODE=1 \\\n  -e CODEXBOX_API_MODE_TOKEN=your-secret \\\n  -e CODEXBOX_AVAILABLE_MODELS=gpt-5.1-codex,gpt-5.1-codex-mini \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD:/workspace\" \\\n  -p 8080:8080 \\\n  psyb0t/codexbox:latest\n```\n\nWith `CODEXBOX_API_MODE_TOKEN` unset the API surface is unauthenticated — anyone who can reach `:8080` gets run-execution plus full workspace file access. Set the token and bind to loopback / behind an authenticating proxy before exposing it beyond localhost.\n\n| Method | Path | What it does |\n|--------|------|---------------|\n| `GET` | `/healthz` | liveness — `{ok, adapter}` |\n| `GET` | `/status` | in-flight runs + busy workspaces |\n| `POST` | `/run` | sync agent run → `{runId, workspace, exitCode, text, ...}` |\n| `GET` | `/run/result?runId=<id>` | poll an async run |\n| `DELETE` | `/run/{run_id}` | cancel an in-flight run |\n| `GET` | `/files` | list the workspace root |\n| `GET` | `/files/{path}` | list a sub-directory, or stream a file's bytes |\n| `PUT` | `/files/{path}` | upload — raw request body becomes the file contents; parent dirs auto-created |\n| `DELETE` | `/files/{path}` | delete a file (refuses directories — 400) |\n| `POST` | `/openai/v1/chat/completions` | OpenAI-compatible chat endpoint (see below) |\n| `GET` | `/openai/v1/models` | model list from `CODEXBOX_AVAILABLE_MODELS` |\n| `POST` | `/mcp` | MCP server, mounted only when `CODEXBOX_MCP_MODE=1` (see MCP mode) |\n\n`DELETE /files/{path}` removes a workspace file (no undo). Confirm the target path first and only remove files the current task created — see [Security & safety](#security--safety).\n\n`POST /run` body: `prompt` (required), `workspace`, `model`, `systemPrompt`, `appendSystemPrompt`, `jsonSchema`, `noContinue`, `resume`, `timeoutSeconds`, `thinking`, `noTools`, `toolsAllowlist`, `includeRaw`, `async`, `fireAndForget`. With `jsonSchema` set, the response adds `json`, `events`, `sessionId`, `usage`, `attempts` — codex has native `--output-schema` enforcement, so `jsonSchema` maps straight onto it (no self-correction retries needed, unlike adapters without native schema support).\n\nDefault programmatic runs continue the exact top-level Codex `exec` root\npinned to the canonical workspace. The first run creates the pin; existing\nworkspaces migrate their newest top-level `exec` rollout. Newer subagent\nrollouts are deliberately excluded because Codex rejects direct turns on\nmulti-agent children. Explicit `resume` re-pins the confirmed thread;\n`noContinue` is ephemeral and leaves the workspace pin unchanged.\n\n```bash\ncurl -s http://localhost:8080/run \\\n  --oauth2-bearer \"$CODEXBOX_API_MODE_TOKEN\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"prompt\": \"say HELLO\", \"workspace\": \"/workspace\"}'\n```\n\nAsync: set `\"async\": true`, poll `GET /run/result?runId=<id>` until `status != \"running\"`.\n\nAll `/files/*` paths are resolved against the workspace root with traversal checking — `..` segments that escape the root return 400.\n\n```bash\ncurl -sS -X PUT --oauth2-bearer \"$CODEXBOX_API_MODE_TOKEN\" \\\n  --data-binary @local.txt http://localhost:8080/files/notes/hello.txt\n\ncurl -sS --oauth2-bearer \"$CODEXBOX_API_MODE_TOKEN\" \\\n  http://localhost:8080/files/notes/hello.txt\n```\n\n## OpenAI-compatible endpoint\n\n`POST /openai/v1/chat/completions` (mounted under API mode, same port/token). Point any OpenAI SDK's base URL at `http://host:8080/openai/v1` and call it like the real API.\n\n- **Streaming**: `\"stream\": true` — real incremental SSE for plain chat. When `tools`/`tool_choice` or a schema constraint is also set, the full answer is computed first, then replayed as a single-shot SSE stream (tool-call/schema turns can't be streamed token-by-token).\n- **Tools**: OpenAI-style `tools` / `tool_choice` in the request body. codex runs its own tools internally, so client-executed tool calling is bridged — codexbox injects an \"emit `{\"tool_calls\":[...]}` and stop\" protocol into the system prompt and parses codex's textual output back into OpenAI `tool_calls`. Stateless: resend full history each round-trip, same as the standard OpenAI tool loop.\n- **`response_format`**: `{\"type\":\"text\"}` (default), `{\"type\":\"json_object\"}` (force parseable JSON, no schema), or `{\"type\":\"json_schema\",\"json_schema\":{\"name\",\"schema\",\"strict?\"}}` (schema-constrained — same native `--output-schema` path as `/run`'s `jsonSchema`). C\n\nArchive v0.6.1: 4 files, 13029 bytes\n\nFiles: references/setup.md (10614b), skill-card.md (2683b), SKILL.md (17422b), _meta.json (127b)\n\nArchive v0.6.0: 4 files, 12858 bytes\n\nFiles: references/setup.md (10287b), skill-card.md (2656b), SKILL.md (17422b), _meta.json (127b)\n\nArchive v0.5.11: 4 files, 12870 bytes\n\nFiles: references/setup.md (10287b), skill-card.md (2700b), SKILL.md (17422b), _meta.json (128b)\n\nArchive v0.5.9: 4 files, 12786 bytes\n\nFiles: references/setup.md (10287b), skill-card.md (2495b), SKILL.md (17422b), _meta.json (127b)\n\nArchive v0.5.8: 4 files, 12823 bytes\n\nFiles: references/setup.md (10287b), skill-card.md (2539b), SKILL.md (17422b), _meta.json (127b)","readmeExcerpt":"Skill: codexbox Owner: psyb0t Summary: Install, configure, or run Codex through the codexbox wrapper, or connect to its HTTP, MCP, Telegram, or cron surfaces. Tags: latest:0.7.0 Version history: v0.7.0 | 2026-10-07T17:22:41.115Z | auto codexbox 0.7.0 - Documentation updates in SKILL.md, including revised instructions and clarifications. - Minor corrections to server endpoint documentation (e.g., /mcp/ endpoint path).","codeSnippets":[],"executableExamples":[{"language":"bash","snippet":"codexbox                                      # interactive Codex TUI\ncodexbox exec \"inspect this workspace\"        # one-shot work\nprintf '%s\\n' \"summarize README.md\" | codexbox exec -\nCODEXBOX_FULL=1 codexbox exec \"run the full suite\""},{"language":"bash","snippet":"CODEXBOX_ENV_CODEXBOX_API_MODE=1 \\\nCODEXBOX_ENV_CODEXBOX_MCP_MODE=1 \\\nCODEXBOX_ENV_CODEXBOX_AVAILABLE_MODELS=your-model-id \\\nCODEXBOX_ENV_CODEXBOX_API_MODE_TOKEN=your-api-token \\\nCODEXBOX_ENV_CODEXBOX_MCP_MODE_TOKEN=your-mcp-token \\\ncodexbox"},{"language":"bash","snippet":"export OPENAI_API_KEY=sk-...\ncodexbox                       # interactive TUI, continues the last session for this dir\ncodexbox --no-continue         # same, but starts a brand-new session\ncodexbox login --device-auth   # ChatGPT-subscription OAuth login\ncodexbox stop                  # stop this dir's running container(s)"},{"language":"bash","snippet":"codexbox exec \"fix the failing test in ./app\"\necho \"summarize README.md\" | codexbox exec -     # prompt via stdin"},{"language":"bash","snippet":"docker run --rm \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD:/workspace\" \\\n  -v \"$PWD/.codex:/home/aicode/.codex\" \\\n  psyb0t/codexbox:latest \\\n  exec \"say HELLO\""},{"language":"bash","snippet":"docker run -d --name codexbox-api \\\n  -e CODEXBOX_API_MODE=1 \\\n  -e CODEXBOX_API_MODE_TOKEN=your-secret \\\n  -e CODEXBOX_AVAILABLE_MODELS=gpt-5.1-codex,gpt-5.1-codex-mini \\\n  -e OPENAI_API_KEY=sk-... \\\n  -v \"$PWD:/workspace\" \\\n  -p 8080:8080 \\\n  psyb0t/codexbox:latest"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: codexbox\ndescription: \"Install, configure, or run Codex through the codexbox wrapper, or connect to its HTTP, MCP, Telegram, or cron surfaces.\"\nhomepage: https://github.com/psyb0t/docker-codexbox\nuser-invocable: true\nmetadata:\n  { \"openclaw\": { \"emoji\": \"🧑‍💻\", \"primaryEnv\": \"CODEXBOX_URL\", \"requires\": { \"bins\": [\"docker\", \"curl\"] } } }\n---\n\n# codexbox\n\n[OpenAI Codex CLI](https://github.com/openai/codex) inside an [aicodebox](https://github.com/psyb0t/docker-aicodebox) container, put on the network. codexbox is aicodebox's `codex` adapter — the HTTP/MCP/Telegram/cron surfaces are aicodebox's, the argv/JSON-event translation is codexbox's.\n\nFor installation and configuration, see [references/setup.md](references/setup.md).\n\n## Agent execution\n\nUse `codexbox` when it is on `PATH`. Run it from the workspace the user\nnamed. Do not assemble a new `docker run` command for routine interactive or\none-shot work. The wrapper owns the workspace mount, `~/.codex`, SSH state,\nimage selection, and session lifecycle.\n\n```bash\ncodexbox                                      # interactive Codex TUI\ncodexbox exec \"inspect this workspace\"        # one-shot work\nprintf '%s\\n' \"summarize README.md\" | codexbox exec -\nCODEXBOX_FULL=1 codexbox exec \"run the full suite\"\n```\n\nFor a wrapper-started server, prefix container variables with\n`CODEXBOX_ENV_`. For example,\n`CODEXBOX_ENV_CODEXBOX_API_MODE=1 codexbox` passes\n`CODEXBOX_API_MODE=1` into the container. Bare `CODEXBOX_API_MODE` is not\nforwarded and does not start the server.\n\nStart a local API and MCP server only when the user asks for one. Authenticate\nCodex with `codexbox login --device-auth` or `CODEXBOX_ENV_OPENAI_API_KEY`,\nthen set the actual model identifiers and distinct bearer tokens:\n\n```bash\nCODEXBOX_ENV_CODEXBOX_API_MODE=1 \\\nCODEXBOX_ENV_CODEXBOX_MCP_MODE=1 \\\nCODEXBOX_ENV_CODEXBOX_AVAILABLE_MODELS=your-model-id \\\nCODEXBOX_ENV_CODEXBOX_API_MODE_TOKEN=your-api-token \\\nCODEXBOX_ENV_CODEXBOX_MCP_MODE_TOKEN=your-mcp-token \\\ncodexbox\n```\n\nUse an HTTP or MCP endpoint only when the user asks for a service or provides\nan already-running remote URL. MCP plugins connect to a server. They do not\nreplace the local wrapper.\n\nIf `codexbox`, `claudebox`, and `pibox` were installed in the same command\ndirectory, a box can invoke a sibling command directly. The parent wrapper\npasses the real host paths and the sibling wrapper file. Do not set\n`AICODEBOX_HOST_*`, copy wrapper files, or manually mount another box's state\ndirectory. If the sibling command is absent, ask the user to install it or to\nchoose another approach.\n\n## Security & safety\n\n- **Set the mode tokens before exposing a port.** `CODEXBOX_API_MODE_TOKEN` (REST) and `CODEXBOX_MCP_MODE_TOKEN` (MCP) each default to no auth when unset, leaving that surface open to anyone who can reach it — run-execution plus full workspace file access. The two are independent (the MCP token has no fallback to the API token), so set whichever mode(s) you enable, and bind to "},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn79dhvmpjng4rp2jjk8k0v5xx80ccbk\",\n  \"slug\": \"codexbox\",\n  \"version\": \"0.7.0\",\n  \"publishedAt\": 1791393761115\n}"},{"path":"references/setup.md","content":"# codexbox setup\n\nSee [SKILL.md](../SKILL.md#security--safety) for the full destructive-operation and unauthenticated-surface warnings before running any mode that binds a port.\n\n## Requirements\n\n- Docker\n- Codex auth: `OPENAI_API_KEY` (pay-as-you-go) or a ChatGPT Plus/Pro/Team subscription (`codexbox login --device-auth`)\n- Optional: SSH key for git-over-SSH inside the container (the installer generates one)\n\nFor ordinary agent work, use the installed `codexbox` command from the target\nworkspace. Do not replace it with a hand-written Docker invocation. The\nwrapper handles the workspace, state, SSH, image, and nested launch context.\n\n## Quick Install (wrapper)\n\nThe one-liner installer pulls the image, creates persistent Codex/SSH dirs, and installs the `codexbox` wrapper on `PATH`.\n\n**Recommended: download, inspect, then run.** Piping a remote script straight into bash executes unreviewed remote code as you. Download it, read it, then run it:\n\n```bash\ncurl -fsSL -o install.sh https://raw.githubusercontent.com/psyb0t/docker-codexbox/master/install.sh\nless install.sh          # read it before running anything\nbash install.sh          # minimal image — default\n# CODEXBOX_FULL=1 bash install.sh        # full image — every development tool pre-installed\n# bash install.sh codex                  # custom command name\n```\n\n`CODEXBOX_FULL=1` must be set before `install.sh` runs — the installer needs it in `bash`'s environment. The choice is baked into the installed wrapper; you don't need to set it again afterward.\n\n### Install from a local checkout\n\nFrom this repository, build and install without pulling a published codexbox\nimage:\n\n```bash\nmake install       # minimal image\nmake install-full  # full image\n\n# wrapper only — no build or pull; select full when needed\nmake install-wrapper\nCODEXBOX_FULL=1 make install-wrapper\n```\n\nThe installer-only `CODEXBOX_SRC_LOCAL=true` flag skips `docker pull` and\nrequires the selected local image to already exist. `make install-wrapper`\nuses that existing image without rebuilding it.\n\n**Verify:** `codexbox --version` should print the codex CLI version.\n\n```bash\ncodexbox                                  # interactive\ncodexbox exec \"inspect this workspace\"    # one-shot\nCODEXBOX_FULL=1 codexbox exec \"run tests\" # temporary full image\n```\n\nFor a wrapper-started server, use `CODEXBOX_ENV_` before every variable that\nmust reach the container. For example,\n`CODEXBOX_ENV_CODEXBOX_API_MODE=1 codexbox` starts API mode.\n\n### Sibling boxes\n\nInstall `codexbox`, `claudebox`, and `pibox` in the same command directory,\nnormally `/usr/local/bin`, to make the sibling commands available inside a\nbox. The parent mounts only the wrapper files read-only. A sibling wrapper then\nruns through the host Docker daemon and mounts its own host data directory.\n\n## Image Variants\n\n| Image | Tag | Contents |\n|---|---|---|\n| Minimal (default) | `psyb0t/codexbox:latest` | Codex, Node.js, Python, `uv`, Docker, Git, `jq`, `curl` |\n| Full | `psyb0t/codex"},{"path":"skill-card.md","content":"## Description:\n\nInstall, configure, or run Codex through the codexbox wrapper, or connect to its HTTP, MCP, Telegram, or cron surfaces.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[psyb0t](https://clawhub.ai/user/psyb0t)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and engineers use codexbox to run Codex in a container for interactive or automated workspace tasks, or to connect it to HTTP, MCP, Telegram, and scheduled workflows.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Exposed API or MCP endpoints may allow unauthenticated execution and workspace file access.\n\nMitigation: Set separate API and MCP bearer tokens and bind services to loopback or use an authenticating proxy.\n\nRisk: File deletion can permanently remove workspace data.\n\nMitigation: Review the target before deletion and only remove files the user has authorized.\n\nRisk: Remote installers and container images run code in the user's environment.\n\nMitigation: Inspect or pin the installer and Docker image before use.\n\n## Reference(s):\n\n- [codexbox on ClawHub](https://clawhub.ai/psyb0t/skills/codexbox)\n- [codexbox setup guide](references/setup.md)\n- [codexbox project documentation](https://github.com/psyb0t/docker-codexbox)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Markdown, Code, Shell commands, Configuration instructions]\n\n**Output Format:** [Plain text, Markdown, code, shell commands, or structured API responses]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [Output depends on the requested Codex task and interface.]\n\n## Skill Version(s):\n\n0.7.0 (source: ClawHub release metadata)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment."}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":null,"editorialQuality":{"score":100,"threshold":65,"status":"thin","wordCount":1520,"uniquenessScore":44,"reasons":["uniqueness-below-45"]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-10T03:09:29.550Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-10T03:09:29.550Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-10T06:42:29.923Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}