Skip to content

Commit 3d6a221

Browse files
authored
feat(codex): share native threads across Codex clients (#99821)
* feat(codex): share native threads across clients * test(codex): track coexistence temp dirs * fix(codex): preserve native source on thread forks * test(codex): use public temp fixtures * fix(codex): preserve owner context for deferred tools * fix(codex): forward owner identity to dynamic tools * fix(codex): forward owner status to harness attempts * docs(security): document shared Codex home * docs(security): document shared Codex home * docs(security): document shared Codex home
1 parent 9a0c9f8 commit 3d6a221

32 files changed

Lines changed: 1209 additions & 40 deletions

docs/docs_map.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5417,6 +5417,7 @@ Do not edit it by hand; run `pnpm docs:map:gen`.
54175417
- Headings:
54185418
- H2: Requirements
54195419
- H2: Quickstart
5420+
- H2: Share threads with Codex Desktop and CLI
54205421
- H2: Configuration
54215422
- H2: Verify Codex runtime
54225423
- H2: Routing and model selection

docs/gateway/security/index.md

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,11 @@ Use this when auditing access or deciding what to back up:
261261
- `~/.openclaw/credentials/<channel>-allowFrom.json` (default account)
262262
- `~/.openclaw/credentials/<channel>-<accountId>-allowFrom.json` (non-default accounts)
263263
- **Model auth profiles**: `~/.openclaw/agents/<agentId>/agent/auth-profiles.json`
264-
- **Codex runtime state**: `~/.openclaw/agents/<agentId>/agent/codex-home/`
264+
- **Codex runtime state (default)**: `~/.openclaw/agents/<agentId>/agent/codex-home/`
265+
- **Shared Codex runtime state (opt-in)**: `$CODEX_HOME` or `~/.codex` when
266+
`plugins.entries.codex.config.appServer.homeScope` is `"user"`. This mode uses
267+
the native Codex account, config, plugins, and thread store; enable it only for
268+
an owner-controlled local Gateway. See [Codex harness](/plugins/codex-harness#share-threads-with-codex-desktop-and-cli).
265269
- **File-backed secrets payload (optional)**: `~/.openclaw/secrets.json`
266270
- **Legacy OAuth import**: `~/.openclaw/credentials/oauth.json`
267271

@@ -998,7 +1002,11 @@ Assume anything under `~/.openclaw/` (or `$OPENCLAW_STATE_DIR/`) may contain sec
9981002
- `openclaw.json`: config may include tokens (gateway, remote gateway), provider settings, and allowlists.
9991003
- `credentials/**`: channel credentials (example: WhatsApp creds), pairing allowlists, legacy OAuth imports.
10001004
- `agents/<agentId>/agent/auth-profiles.json`: API keys, token profiles, OAuth tokens, and optional `keyRef`/`tokenRef`.
1001-
- `agents/<agentId>/agent/codex-home/**`: per-agent Codex app-server account, config, skills, plugins, native thread state, and diagnostics.
1005+
- `agents/<agentId>/agent/codex-home/**`: per-agent Codex app-server account, config, skills, plugins, native thread state, and diagnostics (the default).
1006+
- `$CODEX_HOME/**` or `~/.codex/**`: when the Codex plugin explicitly uses
1007+
`appServer.homeScope: "user"`, the Gateway can read and update the native Codex
1008+
account, config, plugins, and threads. Treat this as privileged owner access;
1009+
the mode is local-stdio-only and native thread management is owner-only.
10021010
- `secrets.json` (optional): file-backed secret payload used by `file` SecretRef providers (`secrets.providers`).
10031011
- `agents/<agentId>/agent/auth.json`: legacy compatibility file. Static `api_key` entries are scrubbed when discovered.
10041012
- `agents/<agentId>/sessions/**`: session transcripts (`*.jsonl`) + routing metadata (`sessions.json`) that can contain private messages and tool output.

docs/plugins/codex-harness-reference.md

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ Supported `appServer` fields:
8888
| Field | Default | Meaning |
8989
| --------------------------------------------- | ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
9090
| `transport` | `"stdio"` | `"stdio"` spawns Codex; `"websocket"` connects to `url`. |
91+
| `homeScope` | `"agent"` | `"agent"` isolates Codex state per OpenClaw agent. `"user"` shares the native `$CODEX_HOME` or `~/.codex`, uses native auth, and enables owner-only thread management. User scope requires stdio. |
9192
| `command` | managed Codex binary | Executable for stdio transport. Leave unset to use the managed binary. |
9293
| `args` | `["app-server", "--listen", "stdio://"]` | Arguments for stdio transport. |
9394
| `url` | unset | WebSocket app-server URL. |
@@ -265,7 +266,7 @@ that combination.
265266

266267
## Auth and environment isolation
267268

268-
Auth is selected in this order:
269+
In the default per-agent home, auth is selected in this order:
269270

270271
1. An explicit OpenClaw Codex auth profile for the agent.
271272
2. The app-server's existing account in that agent's Codex home.
@@ -289,17 +290,26 @@ per-agent directory under that agent's OpenClaw state. That keeps Codex config,
289290
accounts, plugin cache/data, and thread state scoped to the OpenClaw agent
290291
instead of leaking in from the operator's personal `~/.codex` home.
291292

293+
Set `appServer.homeScope: "user"` to share native Codex state with Codex
294+
Desktop and the CLI. This local-stdio-only mode uses `$CODEX_HOME` when set and
295+
`~/.codex` otherwise, including native auth, config, plugins, and threads.
296+
OpenClaw skips its auth-profile bridge for the app-server. Verified owner turns
297+
can use `codex_threads` to list, search, read, fork, rename, archive, and restore
298+
those threads. Fork a thread before continuing it in OpenClaw; independent
299+
Codex processes do not coordinate concurrent writers for the same thread.
300+
292301
OpenClaw does not rewrite `HOME` for normal local app-server launches. Codex-run
293302
subprocesses such as `openclaw`, `gh`, `git`, cloud CLIs, and shell commands see
294303
the normal process home and can find user-home config and tokens. Codex may also
295304
discover `$HOME/.agents/skills` and `$HOME/.agents/plugins/marketplace.json`;
296305
that `.agents` discovery is intentionally shared with the operator home and is
297306
separate from isolated `~/.codex` state.
298307

299-
OpenClaw plugins and OpenClaw skill snapshots still flow through OpenClaw's own
300-
plugin registry and skill loader. Personal Codex `~/.codex` assets do not. If
301-
you have useful Codex CLI skills or plugins from a Codex home that should become
302-
part of an OpenClaw agent, inventory them explicitly:
308+
In the default agent scope, OpenClaw plugins and OpenClaw skill snapshots still
309+
flow through OpenClaw's own plugin registry and skill loader; personal Codex
310+
`~/.codex` assets do not. If you have useful Codex CLI skills or plugins from a
311+
Codex home that should become part of an isolated OpenClaw agent, inventory
312+
them explicitly:
303313

304314
```bash
305315
openclaw migrate codex --dry-run
@@ -328,8 +338,8 @@ If a deployment needs additional environment isolation, add those variables to
328338

329339
`appServer.clearEnv` only affects the spawned Codex app-server child process.
330340
OpenClaw removes `CODEX_HOME` and `HOME` from this list during local launch
331-
normalization: `CODEX_HOME` stays per-agent, and `HOME` stays inherited so
332-
subprocesses can use normal user-home state.
341+
normalization: `CODEX_HOME` stays pointed at the selected agent or user scope,
342+
and `HOME` stays inherited so subprocesses can use normal user-home state.
333343

334344
## Dynamic tools
335345

docs/plugins/codex-harness.md

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,46 @@ Restart the gateway after changing plugin config. If an existing chat already
103103
has a session, use `/new` or `/reset` before testing runtime changes so the next
104104
turn resolves the harness from current config.
105105

106+
## Share threads with Codex Desktop and CLI
107+
108+
The default `appServer.homeScope: "agent"` keeps each OpenClaw agent isolated
109+
from the operator's native Codex state. To let an owner ask OpenClaw to inspect
110+
and manage the same native threads shown by Codex Desktop and the Codex CLI,
111+
opt into the user Codex home:
112+
113+
```json5
114+
{
115+
plugins: {
116+
entries: {
117+
codex: {
118+
enabled: true,
119+
config: {
120+
appServer: {
121+
homeScope: "user",
122+
},
123+
},
124+
},
125+
},
126+
},
127+
}
128+
```
129+
130+
User-home mode is available only with local stdio transport. It uses
131+
`$CODEX_HOME` when set and `~/.codex` otherwise, including that home's native
132+
Codex auth, config, plugins, and thread store. OpenClaw does not inject an
133+
OpenClaw auth profile into this app-server.
134+
135+
Owner turns gain the `codex_threads` tool. It can list, search, read, fork,
136+
rename, archive, and restore native threads. Ask the agent to fork a thread when
137+
you want to continue it in OpenClaw; the fork is attached to the current
138+
OpenClaw session and remains visible to other native Codex clients. Archive
139+
requires explicit confirmation that the thread is closed elsewhere.
140+
141+
Do not resume or write the same thread concurrently from OpenClaw and another
142+
Codex client. Codex coordinates live writers inside one app-server process, not
143+
across independent Desktop, CLI, and OpenClaw processes. Forking creates a
144+
separate continuation and is the safe coexistence path.
145+
106146
## Configuration
107147

108148
The quickstart config is the minimum viable Codex harness config. Set Codex
@@ -451,7 +491,7 @@ Get the thread id from the completed `/diagnostics` reply, `/codex binding`, or
451491
For upload mechanics and runtime-level diagnostics boundaries, see
452492
[Codex harness runtime](/plugins/codex-harness-runtime#codex-feedback-upload).
453493

454-
Auth is selected in this order:
494+
In the default per-agent home, auth is selected in this order:
455495

456496
1. Ordered OpenAI auth profiles for the agent, preferably under
457497
`auth.order.openai`. Run `openclaw doctor --fix` to migrate older
@@ -490,6 +530,8 @@ thread state do not read or write the operator's personal `~/.codex` by
490530
default. OpenClaw preserves the normal process `HOME`; Codex-run subprocesses
491531
can still find user-home config and tokens, and Codex may discover shared
492532
`$HOME/.agents/skills` and `$HOME/.agents/plugins/marketplace.json` entries.
533+
With `appServer.homeScope: "user"`, OpenClaw instead uses the native user Codex
534+
home and its existing account without injecting an OpenClaw auth profile.
493535

494536
If a deployment needs additional environment isolation, add those variables to
495537
`appServer.clearEnv`:
@@ -513,8 +555,8 @@ If a deployment needs additional environment isolation, add those variables to
513555

514556
`appServer.clearEnv` only affects the spawned Codex app-server child process.
515557
OpenClaw removes `CODEX_HOME` and `HOME` from this list during local launch
516-
normalization: `CODEX_HOME` stays per-agent, and `HOME` stays inherited so
517-
subprocesses can use normal user-home state.
558+
normalization: `CODEX_HOME` stays pointed at the selected agent or user scope,
559+
and `HOME` stays inherited so subprocesses can use normal user-home state.
518560

519561
Codex dynamic tools default to `searchable` loading. OpenClaw does not expose
520562
dynamic tools that duplicate Codex-native workspace operations: `read`, `write`,
@@ -561,12 +603,13 @@ Supported `appServer` fields:
561603
| Field | Default | Meaning |
562604
| --------------------------------------------- | ------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
563605
| `transport` | `"stdio"` | `"stdio"` spawns Codex; `"websocket"` connects to `url`. |
606+
| `homeScope` | `"agent"` | `"agent"` isolates Codex state per OpenClaw agent. `"user"` shares the native `$CODEX_HOME` or `~/.codex`, uses native auth, and enables owner-only thread management. User scope requires stdio. |
564607
| `command` | managed Codex binary | Executable for stdio transport. Leave unset to use the managed binary; set it only for an explicit override. |
565608
| `args` | `["app-server", "--listen", "stdio://"]` | Arguments for stdio transport. |
566609
| `url` | unset | WebSocket app-server URL. |
567610
| `authToken` | unset | Bearer token for WebSocket transport. Accepts a literal string or SecretInput such as `${CODEX_APP_SERVER_TOKEN}`. |
568611
| `headers` | `{}` | Extra WebSocket headers. Header values accept literal strings or SecretInput values, for example `x-codex-client-session-token: "${CODEX_CLIENT_SESSION_TOKEN}"`. |
569-
| `clearEnv` | `[]` | Extra environment variable names removed from the spawned stdio app-server process after OpenClaw builds its inherited environment. OpenClaw keeps per-agent `CODEX_HOME` and inherited `HOME` for local launches. |
612+
| `clearEnv` | `[]` | Extra environment variable names removed from the spawned stdio app-server process after OpenClaw builds its inherited environment. OpenClaw keeps the selected `CODEX_HOME` and inherited `HOME` for local launches. |
570613
| `codeModeOnly` | `false` | Opt into Codex's code-mode-only tool surface. OpenClaw dynamic tools remain registered with Codex so nested `tools.*` calls return through the app-server `item/tool/call` bridge. |
571614
| `remoteWorkspaceRoot` | unset | Remote Codex app-server workspace root. When set, OpenClaw infers the local workspace root from the resolved OpenClaw workspace, preserves the current cwd suffix under this remote root, and sends only the final app-server cwd to Codex. If the cwd is outside the resolved OpenClaw workspace root, OpenClaw fails closed instead of sending a gateway-local path to the remote app-server. |
572615
| `requestTimeoutMs` | `60000` | Timeout for app-server control-plane calls. |

0 commit comments

Comments
 (0)