Codex MCP Profiles
Codex-specific MCP profiles
Codex Per-Profile Runtime Homes
Prompt-first procedure: Describe the outcome you want in your agent conversation. The agent should select and load the appropriate AIWG assets, explain material changes, request any needed approval, and report verification evidence. Exact commands and flags appear only in the CLI reference.
Codex has no native per-session config flag (unlike `claude the mcp-config option`). AIWG implements OAuth isolation per MCP profile by giving each profile its own runtime home directory. Codex is launched with `HOME=<runtime-home>` so all config reads, auth token writes, and OAuth flows are scoped to that profile.
This mirrors the sysops `codex-role.sh` pattern from `roctinam/sysops`.
How It Works
~/.codex/ ← global Codex home (shared)
├── history.jsonl ← symlinked into each runtime home
├── sessions/ ← symlinked into each runtime home
└── roles-runtime/ ← runtime homes live here
├── dev/ ← runtime home for "dev" profile
│ ├── config.toml ← profile-scoped MCP server config
│ ├── auth.json ← OAuth tokens (isolated per profile)
│ ├── history.jsonl → ← symlink to ~/.codex/history.jsonl
│ └── sessions/ → ← symlink to ~/.codex/sessions/
└── ops/ ← runtime home for "ops" profile
├── config.toml
├── auth.json
├── history.jsonl →
└── sessions/ →
Isolated per profile: `auth.json`, `.credentials`, `config.toml` Shared across profiles: `history.jsonl`, `sessions/`
Session Flow
sequenceDiagram
participant User
participant the agent-owned participant operation FS as Filesystem
participant Codex
User->>aiwg: the agent-owned session operation the provider option codex the profile option ops
aiwg->>FS: mkdir ~/.codex/roles-runtime/ops/
aiwg->>FS: symlink history.jsonl (if source exists)
aiwg->>FS: symlink sessions/ (if source exists)
aiwg->>FS: read ~/.codex/config.toml (strip [mcp_servers.*] blocks)
aiwg->>FS: resolve "ops" profile servers from ~/.aiwg/mcp-profiles.json
aiwg->>FS: write ~/.codex/roles-runtime/ops/config.toml
Note over FS: Profile-scoped config with only ops servers
aiwg->>Codex: spawnSync('codex', [], { env: { HOME: '~/.codex/roles-runtime/ops' } })
Note over Codex: Reads config from runtime home, not ~/.codex
alt First run (no auth.json in runtime home)
Codex->>User: OAuth login prompt
User->>Codex: authenticate
Codex->>FS: write auth.json to runtime home (isolated)
else Already authenticated
Codex->>FS: read auth.json from runtime home
end
Codex->>User: session active with ops profile servers
Using Profile Sessions
Use AIWG to complete this documented outcome: Using Profile Sessions
Have it inspect the current state, explain the plan, ask before material
changes, and report the result with verification evidence.
Each profile authenticates independently. Logging out of one profile does not affect other profiles.
Explicit Login
Run OAuth login for a profile without starting a full session:
Use AIWG to complete this documented outcome: Run OAuth login for a profile without starting a full session
Have it inspect the current state, explain the plan, ask before material
changes, and report the result with verification evidence.
This calls `codex login` with `HOME` set to the profile runtime home. Useful for pre-authenticating profiles before starting a session.
Shared State Policy
The `SharedStatePolicy` controls which files are symlinked (shared) vs isolated per profile. The default policy:
| Item | Behavior | Reason |
|---|---|---|
| `history.jsonl` | Symlinked (shared) | Operator history is cross-profile |
| `sessions/` | Symlinked (shared) | Session index is cross-profile |
| `auth.json` | Isolated | OAuth tokens are profile-scoped |
| `.credentials` | Isolated | Credentials are profile-scoped |
| `config.toml` | Isolated | MCP server config is profile-scoped |
Symlinks are created only when the source exists in `~/.codex/`. If the source does not exist, the symlink is skipped silently (the runtime home still works).
config.toml Generation
When setting up a runtime home, AIWG:
1. Reads `~/.codex/config.toml` (if it exists) 2. Strips all `[mcp_servers.]` sections 3. Appends profile-scoped `[mcp_servers.]` blocks for each server in the profile
Each server block follows the Codex TOML format:
[mcp_servers.git-gitea]
command = "npx"
args = ["-y", "@gitea/mcp-server"]
env.GITEA_TOKEN = "..."
startup_timeout_sec = 10.0
tool_timeout_sec = 60.0
Non-MCP settings from the global config (model preferences, theme, keybindings) are preserved.
Runtime Home Management
Use AIWG to complete this documented outcome: Runtime Home Management
Have it inspect the current state, explain the plan, ask before material
changes, and report the result with verification evidence.
Troubleshooting
"Runtime home does not exist"
Error: Runtime home for profile "ops" does not exist.
Run "the agent-owned mcp operation profile add ops" or "the agent-owned session operation the provider option codex the profile option ops" to create it.
Run the agent-owned session operation once to initialize the runtime home.
Auth tokens not persisting across sessions
Verify the runtime home was created with the correct path:
ls ~/.codex/roles-runtime/ops/auth.json
If missing, the OAuth flow did not complete. Re-run the agent-owned session operation.
MCP servers not appearing in Codex
Check the generated config:
cat ~/.codex/roles-runtime/ops/config.toml
If empty or missing `[mcp_servers.*]` blocks, the profile may have no servers resolved. Run the agent-owned mcp operation to verify the server list.
Cross-device symlink errors
On systems where `~/.codex/` is on a different filesystem, symlinks may fail with `EXDEV`. AIWG suppresses this error and continues — the runtime home still works, but history and sessions will not be shared across profiles.
Further Reading
- MCP Profiles — Profile registry, CRUD, and provider overrides
- CLI Reference: mcp profile — Full command reference
- CLI Reference: session — Session launcher with profile support