Skip to content

Commit 027ea5f

Browse files
authored
Isolate Codex app-server state per agent (#74556)
* fix(codex): isolate app-server home per agent * fix(codex): isolate native Codex assets per agent * fix(channels): mark inbound system events untrusted * fix(doctor): warn on personal Codex agent skills * test(doctor): cover personal Codex agent skills warning * fix(codex): forward auth profiles to harness runs * fix(codex): preserve auto auth for harness runs * fix(codex): auto-select harness auth profiles * test(codex): type harness auth mock * feat(codex): select migrated skills * fix(codex): satisfy migration selection lint * docs: add codex isolation changelog
1 parent 7d77680 commit 027ea5f

35 files changed

Lines changed: 2299 additions & 49 deletions

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ Docs: https://docs.openclaw.ai
1515
- Agents/tool-result guard: use the resolved runtime context token budget for non-context-engine tool-result overflow checks, so long tool-heavy sessions no longer compact early when `contextTokens` is larger than native `contextWindow`. Fixes #74917. Thanks @kAIborg24.
1616
- Gateway/systemd: exit with sysexits 78 for supervised lock and `EADDRINUSE` conflicts so `RestartPreventExitStatus=78` stops `Restart=always` restart loops instead of repeatedly reloading plugins against an occupied port. Fixes #75115. Thanks @yhyatt.
1717
- Agents/runtime: skip blank visible user prompts at the embedded-runner boundary before provider submission while still allowing internal runtime-only turns and media-only prompts, so Telegram/group sessions no longer leak raw empty-input provider errors when replay history exists. Fixes #74137. Thanks @yelog, @Gracker, and @nhaener.
18+
- Agents/Codex: isolate local Codex app-server `CODEX_HOME` and `HOME` per agent and add a deliberate Codex migration path with selectable skill copies, so personal Codex CLI skills, plugins, config, and hooks no longer leak into OpenClaw agents unless the operator migrates them into the workspace. Thanks @pashpashpash.
1819
- Plugins/runtime-deps: replace stale symlinked mirror target roots before writing runtime-mirror temp files and skip rewriting already materialized hardlinks, so cross-version container upgrades no longer crash-loop on read-only image-layer paths while warm mirrors do less churn. Fixes #75108; refs #75069. Thanks @coletebou and @xiaohuaxi.
1920
- Auto-reply/group chats: fall back to automatic source delivery when a channel precomputes message-tool-only replies but the `message` tool is unavailable, so Discord/Slack-style group turns do not silently complete without a visible reply. Fixes #74868. Thanks @kagura-agent.
2021
- Browser/gateway: share one browser control runtime across the HTTP control server and `browser.request`, and refresh browser profile config from the source snapshot, so CLI status/start honors configured `browser.executablePath`, `headless`, and `noSandbox` instead of falling back to stale auto-detection. Fixes #75087; repairs #73617. Thanks @civiltox and @martingarramon.

docs/cli/doctor.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ Notes:
5252
- Repeat `doctor --fix` runs no longer report/apply Talk normalization when the only difference is object key order.
5353
- Doctor includes a memory-search readiness check and can recommend `openclaw configure --section model` when embedding credentials are missing.
5454
- Doctor warns when no command owner is configured. The command owner is the human operator account allowed to run owner-only commands and approve dangerous actions. DM pairing only lets someone talk to the bot; if you approved a sender before first-owner bootstrap existed, set `commands.ownerAllowFrom` explicitly.
55+
- Doctor warns when Codex-mode agents are configured and personal Codex CLI assets exist in the operator's Codex home. Local Codex app-server launches use isolated per-agent homes, so use `openclaw migrate codex --dry-run` to inventory assets that should be promoted deliberately.
5556
- If sandbox mode is enabled but Docker is unavailable, doctor reports a high-signal warning with remediation (`install Docker` or `openclaw config set agents.defaults.sandbox.mode off`).
5657
- If `gateway.auth.token`/`gateway.auth.password` are SecretRef-managed and unavailable in the current command path, doctor reports a read-only warning and does not write plaintext fallback credentials.
5758
- If channel SecretRef inspection fails in a fix path, doctor continues and reports a warning instead of exiting early.

docs/cli/migrate.md

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ title: "Migrate"
88

99
# `openclaw migrate`
1010

11-
Import state from another agent system through a plugin-owned migration provider. Bundled providers cover [Claude](/install/migrating-claude) and [Hermes](/install/migrating-hermes); third-party plugins can register additional providers.
11+
Import state from another agent system through a plugin-owned migration provider. Bundled providers cover Codex CLI state, [Claude](/install/migrating-claude), and [Hermes](/install/migrating-hermes); third-party plugins can register additional providers.
1212

1313
<Tip>
1414
For user-facing walkthroughs, see [Migrating from Claude](/install/migrating-claude) and [Migrating from Hermes](/install/migrating-hermes). The [migration hub](/install/migrating) lists all paths.
@@ -19,8 +19,12 @@ For user-facing walkthroughs, see [Migrating from Claude](/install/migrating-cla
1919
```bash
2020
openclaw migrate list
2121
openclaw migrate claude --dry-run
22+
openclaw migrate codex --dry-run
23+
openclaw migrate codex --skill gog-vault77-google-workspace
2224
openclaw migrate hermes --dry-run
2325
openclaw migrate hermes
26+
openclaw migrate apply codex --yes --skill gog-vault77-google-workspace
27+
openclaw migrate apply codex --yes
2428
openclaw migrate apply claude --yes
2529
openclaw migrate apply hermes --yes
2630
openclaw migrate apply hermes --include-secrets --yes
@@ -47,6 +51,9 @@ openclaw onboard --import-from hermes --import-source ~/.hermes
4751
<ParamField path="--yes" type="boolean">
4852
Skip the confirmation prompt. Required in non-interactive mode.
4953
</ParamField>
54+
<ParamField path="--skill <name>" type="string">
55+
Select one skill copy item by skill name or item id. Repeat the flag to migrate multiple skills. When omitted, interactive Codex migrations show a checkbox selector and non-interactive migrations keep all planned skills.
56+
</ParamField>
5057
<ParamField path="--no-backup" type="boolean">
5158
Skip the pre-apply backup. Requires `--force` when local OpenClaw state exists.
5259
</ParamField>
@@ -99,6 +106,43 @@ For a user-facing walkthrough, see [Migrating from Claude](/install/migrating-cl
99106

100107
Claude hooks, permissions, environment defaults, local memory, path-scoped rules, subagents, caches, plans, and project history are preserved in the migration report or reported as manual-review items. OpenClaw does not execute hooks, copy broad allowlists, or import OAuth/Desktop credential state automatically.
101108

109+
## Codex provider
110+
111+
The bundled Codex provider detects Codex CLI state at `~/.codex` by default, or
112+
at `CODEX_HOME` when that environment variable is set. Use `--from <path>` to
113+
inventory a specific Codex home.
114+
115+
Use this provider when moving to the OpenClaw Codex harness and you want to
116+
promote useful personal Codex CLI assets deliberately. Local Codex app-server
117+
launches use per-agent `CODEX_HOME` and `HOME` directories, so they do not read
118+
your personal Codex CLI state by default.
119+
120+
Running `openclaw migrate codex` in an interactive terminal previews the full
121+
plan, then opens a checkbox selector for skill copy items before the final
122+
apply confirmation. All skills start selected; uncheck any skill you do not want
123+
copied into this agent. For scripted or exact runs, pass `--skill <name>` once
124+
per skill, for example:
125+
126+
```bash
127+
openclaw migrate codex --dry-run --skill gog-vault77-google-workspace
128+
openclaw migrate apply codex --yes --skill gog-vault77-google-workspace
129+
```
130+
131+
### What Codex imports
132+
133+
- Codex CLI skill directories under `$CODEX_HOME/skills`, excluding Codex's
134+
`.system` cache.
135+
- Personal AgentSkills under `$HOME/.agents/skills`, copied into the current
136+
OpenClaw agent workspace when you want per-agent ownership.
137+
138+
### Manual-review Codex state
139+
140+
Codex native plugins, `config.toml`, and native `hooks/hooks.json` are not
141+
activated automatically. Plugins may expose MCP servers, apps, hooks, or other
142+
executable behavior, so the provider reports them for review instead of loading
143+
them into OpenClaw. Config and hook files are copied into the migration report
144+
for manual review.
145+
102146
## Hermes provider
103147

104148
The bundled Hermes provider detects state at `~/.hermes` by default. Use `--from <path>` when Hermes lives elsewhere.

docs/concepts/agent-workspace.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ These live under `~/.openclaw/` and should NOT be committed to the workspace rep
108108

109109
- `~/.openclaw/openclaw.json` (config)
110110
- `~/.openclaw/agents/<agentId>/agent/auth-profiles.json` (model auth profiles: OAuth + API keys)
111+
- `~/.openclaw/agents/<agentId>/agent/codex-home/` (per-agent Codex runtime account, config, skills, plugins, and native thread state)
111112
- `~/.openclaw/credentials/` (channel/provider state plus legacy OAuth import data)
112113
- `~/.openclaw/agents/<agentId>/sessions/` (session transcripts + metadata)
113114
- `~/.openclaw/skills/` (managed skills)

docs/gateway/security/index.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ Use this when auditing access or deciding what to back up:
236236
- `~/.openclaw/credentials/<channel>-allowFrom.json` (default account)
237237
- `~/.openclaw/credentials/<channel>-<accountId>-allowFrom.json` (non-default accounts)
238238
- **Model auth profiles**: `~/.openclaw/agents/<agentId>/agent/auth-profiles.json`
239+
- **Codex runtime state**: `~/.openclaw/agents/<agentId>/agent/codex-home/`
239240
- **File-backed secrets payload (optional)**: `~/.openclaw/secrets.json`
240241
- **Legacy OAuth import**: `~/.openclaw/credentials/oauth.json`
241242

@@ -965,6 +966,7 @@ Assume anything under `~/.openclaw/` (or `$OPENCLAW_STATE_DIR/`) may contain sec
965966
- `openclaw.json`: config may include tokens (gateway, remote gateway), provider settings, and allowlists.
966967
- `credentials/**`: channel credentials (example: WhatsApp creds), pairing allowlists, legacy OAuth imports.
967968
- `agents/<agentId>/agent/auth-profiles.json`: API keys, token profiles, OAuth tokens, and optional `keyRef`/`tokenRef`.
969+
- `agents/<agentId>/agent/codex-home/**`: per-agent Codex app-server account, config, skills, plugins, native thread state, and diagnostics.
968970
- `secrets.json` (optional): file-backed secret payload used by `file` SecretRef providers (`secrets.providers`).
969971
- `agents/<agentId>/agent/auth.json`: legacy compatibility file. Static `api_key` entries are scrubbed when discovered.
970972
- `agents/<agentId>/sessions/**`: session transcripts (`*.jsonl`) + routing metadata (`sessions.json`) that can contain private messages and tool output.

docs/plugins/codex-harness.md

Lines changed: 44 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,10 @@ Codex after changing config.
180180
Codex app-server binary by default, so local `codex` commands on `PATH` do
181181
not affect normal harness startup.
182182
- Codex auth available to the app-server process or to OpenClaw's Codex auth
183-
bridge.
183+
bridge. Local app-server launches use an OpenClaw-managed Codex home for each
184+
agent and an isolated child `HOME`, so they do not read your personal
185+
`~/.codex` account, skills, plugins, config, thread state, or native
186+
`$HOME/.agents/skills` by default.
184187

185188
The plugin blocks older or unversioned app-server handshakes. That keeps
186189
OpenClaw on the protocol surface it has been tested against.
@@ -511,11 +514,33 @@ For an already-running app-server, use WebSocket transport:
511514
```
512515

513516
Stdio app-server launches inherit OpenClaw's process environment by default,
514-
but OpenClaw owns the Codex app-server account bridge. Auth is selected in this
515-
order:
517+
but OpenClaw owns the Codex app-server account bridge and sets both
518+
`CODEX_HOME` and `HOME` to per-agent directories under that agent's OpenClaw
519+
state. Codex's own skill loader reads `$CODEX_HOME/skills` and
520+
`$HOME/.agents/skills`, so both values are isolated for local app-server
521+
launches. That keeps Codex-native skills, plugins, config, accounts, and thread
522+
state scoped to the OpenClaw agent instead of leaking in from the operator's
523+
personal Codex CLI home.
524+
525+
OpenClaw plugins and OpenClaw skill snapshots still flow through OpenClaw's own
526+
plugin registry and skill loader. Personal Codex CLI assets do not. If you have
527+
useful Codex CLI skills or plugins that should become part of an OpenClaw agent,
528+
inventory them explicitly:
529+
530+
```bash
531+
openclaw migrate codex --dry-run
532+
openclaw migrate apply codex --yes
533+
```
534+
535+
The Codex migration provider copies skills into the current OpenClaw agent
536+
workspace. Codex native plugins, hooks, and config files are reported or archived
537+
for manual review instead of being activated automatically, because they can
538+
execute commands, expose MCP servers, or carry credentials.
539+
540+
Auth is selected in this order:
516541

517542
1. An explicit OpenClaw Codex auth profile for the agent.
518-
2. The app-server's existing account, such as a local Codex CLI ChatGPT sign-in.
543+
2. The app-server's existing account in that agent's Codex home.
519544
3. For local stdio app-server launches only, `CODEX_API_KEY`, then
520545
`OPENAI_API_KEY`, when no app-server account is present and OpenAI auth is
521546
still required.
@@ -553,21 +578,21 @@ If a deployment needs additional environment isolation, add those variables to
553578

554579
Supported `appServer` fields:
555580

556-
| Field | Default | Meaning |
557-
| ------------------- | ---------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
558-
| `transport` | `"stdio"` | `"stdio"` spawns Codex; `"websocket"` connects to `url`. |
559-
| `command` | managed Codex binary | Executable for stdio transport. Leave unset to use the managed binary; set it only for an explicit override. |
560-
| `args` | `["app-server", "--listen", "stdio://"]` | Arguments for stdio transport. |
561-
| `url` | unset | WebSocket app-server URL. |
562-
| `authToken` | unset | Bearer token for WebSocket transport. |
563-
| `headers` | `{}` | Extra WebSocket headers. |
564-
| `clearEnv` | `[]` | Extra environment variable names removed from the spawned stdio app-server process after OpenClaw builds its inherited environment. |
565-
| `requestTimeoutMs` | `60000` | Timeout for app-server control-plane calls. |
566-
| `mode` | `"yolo"` | Preset for YOLO or guardian-reviewed execution. |
567-
| `approvalPolicy` | `"never"` | Native Codex approval policy sent to thread start/resume/turn. |
568-
| `sandbox` | `"danger-full-access"` | Native Codex sandbox mode sent to thread start/resume. |
569-
| `approvalsReviewer` | `"user"` | Use `"auto_review"` to let Codex review native approval prompts. `guardian_subagent` remains a legacy alias. |
570-
| `serviceTier` | unset | Optional Codex app-server service tier: `"fast"`, `"flex"`, or `null`. Invalid legacy values are ignored. |
581+
| Field | Default | Meaning |
582+
| ------------------- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
583+
| `transport` | `"stdio"` | `"stdio"` spawns Codex; `"websocket"` connects to `url`. |
584+
| `command` | managed Codex binary | Executable for stdio transport. Leave unset to use the managed binary; set it only for an explicit override. |
585+
| `args` | `["app-server", "--listen", "stdio://"]` | Arguments for stdio transport. |
586+
| `url` | unset | WebSocket app-server URL. |
587+
| `authToken` | unset | Bearer token for WebSocket transport. |
588+
| `headers` | `{}` | Extra WebSocket headers. |
589+
| `clearEnv` | `[]` | Extra environment variable names removed from the spawned stdio app-server process after OpenClaw builds its inherited environment. `CODEX_HOME` and `HOME` are reserved for OpenClaw's per-agent Codex isolation on local launches. |
590+
| `requestTimeoutMs` | `60000` | Timeout for app-server control-plane calls. |
591+
| `mode` | `"yolo"` | Preset for YOLO or guardian-reviewed execution. |
592+
| `approvalPolicy` | `"never"` | Native Codex approval policy sent to thread start/resume/turn. |
593+
| `sandbox` | `"danger-full-access"` | Native Codex sandbox mode sent to thread start/resume. |
594+
| `approvalsReviewer` | `"user"` | Use `"auto_review"` to let Codex review native approval prompts. `guardian_subagent` remains a legacy alias. |
595+
| `serviceTier` | unset | Optional Codex app-server service tier: `"fast"`, `"flex"`, or `null`. Invalid legacy values are ignored. |
571596

572597
OpenClaw-owned dynamic tool calls are bounded independently from
573598
`appServer.requestTimeoutMs`: each Codex `item/tool/call` request must receive

0 commit comments

Comments
 (0)