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: truerenders 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.examplerenders 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.
| Field | Type | Description |
|---|---|---|
configToml | string | A raw TOML document, written as is. |
config | object | Settings as YAML, rendered to TOML. Wins if configToml is also present. |
userConfig | object | An alias for config. |
mcpServers | object | MCP 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 projectNotes
- Codex has no managed (operator-enforced) layer here, only a single user-owned file.
- The file is rewritten every time the workstation applies its configuration, so edits made inside it revert.
- Secret references are resolved before the file is rendered, in either form.