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:

ItemBehaviorReason
`history.jsonl`Symlinked (shared)Operator history is cross-profile
`sessions/`Symlinked (shared)Session index is cross-profile
`auth.json`IsolatedOAuth tokens are profile-scoped
`.credentials`IsolatedCredentials are profile-scoped
`config.toml`IsolatedMCP 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.

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