codex

Codex works on a workstation with no configuration. This is for when you want to set a model, add MCP servers, or hand Codex a config.toml of your own.

Install Codex with the codex devtool and it is ready to use with its own defaults. Add this toolconfig when you want to change them. The simplest form is your config.toml, written as you would write it yourself:

toolconfigs:
  - id: codex
    name: codex
    config:
      configToml: |
        model = "o4-mini"

Ringleader writes that to ~/.codex/config.toml, owned by the login user and readable by nobody else, since it may hold a provider API key. The rest of this page covers the structured form, MCP servers, workspace trust, and the field list.

Structured form

If you would rather not write TOML, give the same settings as YAML under config and Ringleader renders them:

toolconfigs:
  - id: codex
    name: codex
    config:
      config:
        model: o4-mini              # a top-level scalar
        some_section:               # an object becomes a [section] table
          key: value
          enabled: true

renders as:

model = "o4-mini"

[some_section]
enabled = true
key = "value"

Key names are Codex’s, not Ringleader’s; nothing is validated or renamed, and keys are sorted so re-applying the same input changes nothing. The renderer handles top-level values and one level of [section] tables. Anything deeper (a table inside a section, an array of tables) is refused with a clear error; use configToml for those. If both are present, config wins.

MCP servers

Declare MCP servers by name and Ringleader writes Codex’s own [mcp_servers.<name>] tables, the same bytes codex mcp add would write:

toolconfigs:
  - id: codex
    name: codex
    config:
      mcpServers:
        linear:
          command: npx
          args: ["-y", "mcp-remote", "https://mcp.linear.app/sse"]
        internal:
          command: /opt/tools/mcp-internal
          env:
            API_BASE: https://api.internal.example

renders as:

[mcp_servers.internal]
command = "/opt/tools/mcp-internal"

[mcp_servers.internal.env]
API_BASE = "https://api.internal.example"

[mcp_servers.linear]
args = ["-y", "mcp-remote", "https://mcp.linear.app/sse"]
command = "npx"

A server definition takes scalars, an array of scalars (args), and one level of nested table (env); anything deeper is refused, and configToml is the way to write it. If your configToml already contains a [mcp_servers.<name>] table, the declared server of that name is skipped, because a duplicate table would make Codex reject the whole file.

Workspace trust

Folders in sources[].path and trustedFolders are added to the file as [projects."<absolute path>"] tables with trust_level = "trusted", which is Codex’s own per-project trust setting. A path you declared yourself is left alone. This happens whenever the workstation declares trusted folders, even with no codex toolconfig.

config fields

Provide one of the first three. mcpServers can accompany any of them.

FieldTypeDescription
configTomlstringA TOML document of your own. Its settings are merged into the file one key at a time (see Notes).
configobjectSettings as YAML, rendered to TOML. Wins if configToml is also present.
userConfigobjectAn alias for config.
mcpServersobjectMCP servers by name, rendered into [mcp_servers.…] tables.

Example

apiVersion: workstations.ringleader.dev/v1
kind: WorkstationConfig
metadata:
  name: codex-box
  namespace: local
spec:
  selector:
    matchLabels:
      tier: dev
  identity:
    user: dev
  devtools:
    - name: nodejs
      version: "24"
    - name: codex
  toolconfigs:
    - id: codex
      name: codex
      config:
        configToml: |
          model = "o4-mini"
  sources:
    - name: app
      git:
        url: https://github.com/acme/app.git
      path: /home/dev/src/app     # added as a trusted project

Notes

  • Codex has no managed (operator-enforced) layer here, only a single user-owned file.
  • Ringleader manages only the settings it declares, including the ones in your configToml. Everything else in the file survives: the folder trust Codex records when you accept its own prompt, and the tables Codex writes for itself. Stop declaring a setting and it is removed on the next pass. Remove the toolconfig and only Ringleader’s settings go; the file is deleted only when nothing else is left in it.
  • On a workstation where Codex has written nothing of its own, your configToml lands as you wrote it. Once Codex has saved something, Ringleader re-renders the file, and the comments and key order from your text do not survive that.
  • Secret references are resolved before the file is rendered, in either form.