mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
2b9bf5d3d43e39811d9f8db8d65b79bc2f7c12e9
31 Commits
-
[codex] Add danger-full-access denylist-only network mode (#16946)
## Summary This adds `experimental_network.danger_full_access_denylist_only` for orgs that want yolo / danger-full-access sessions to keep full network access while still enforcing centrally managed deny rules. When the flag is true and the session sandbox is `danger-full-access`, the network proxy starts with: - domain allowlist set to `*` - managed domain `deny` entries enforced - upstream proxy use allowed - all Unix sockets allowed - local/private binding allowed Caveat: the denylist is best effort only. In yolo / danger-full-access mode, Codex or the model can use an allowed socket or other local/private network path to bypass the proxy denylist, so this should not be treated as a hard security boundary. The flag is intentionally scoped to `SandboxPolicy::DangerFullAccess`. Read-only and workspace-write modes keep the existing managed/user allowlist, denylist, Unix socket, and local-binding behavior. This does not enable the non-loopback proxy listener setting; that still requires its own explicit config. This also threads the new field through config requirements parsing, app-server protocol/schema output, config API mapping, and the TUI debug config output. ## How to use Add the flag under `[experimental_network]` in the network policy config that is delivered to Codex. The setting is not under `[permissions]`. ```toml [experimental_network] enabled = true danger_full_access_denylist_only = true [experimental_network.domains] "blocked.example.com" = "deny" "*.blocked.example.com" = "deny" ``` With that configuration, yolo / danger-full-access sessions get broad network access except for the managed denied domains above. The denylist remains a best-effort proxy policy because the session may still use allowed sockets to bypass it. Other sandbox modes do not get the wildcard domain allowlist or the socket/local-binding relaxations from this flag. ## Verification - `cargo test -p codex-config network_requirements` - `cargo test -p codex-core network_proxy_spec` - `cargo test -p codex-app-server map_requirements_toml_to_api` - `cargo test -p codex-tui debug_config_output` - `cargo test -p codex-app-server-protocol` - `just write-app-server-schema` - `just fmt` - `just fix -p codex-config -p codex-core -p codex-app-server-protocol -p codex-app-server -p codex-tui` - `just fix -p codex-core -p codex-config` - `git diff --check` - `cargo clean`
viyatb-oai ·
2026-04-06 19:38:51 -07:00 -
feat(requirements): support allowed_approval_reviewers (#16701)
## Description Add requirements.toml support for `allowed_approvals_reviewers = ["user", "guardian_subagent"]`, so admins can now restrict the use of guardian mode. Note: If a user sets a reviewer that isn’t allowed by requirements.toml, config loading falls back to the first allowed reviewer and emits a startup warning. The table below describes the possible admin controls. | Admin intent | `requirements.toml` | User `config.toml` | End result | |---|---|---|---| | Leave Guardian optional | omit `allowed_approvals_reviewers` or set `["user", "guardian_subagent"]` | user chooses `approvals_reviewer = "user"` or `"guardian_subagent"` | Guardian off for `user`, on for `guardian_subagent` + `approval_policy = "on-request"` | | Force Guardian off | `allowed_approvals_reviewers = ["user"]` | any user value | Effective reviewer is `user`; Guardian off | | Force Guardian on | `allowed_approvals_reviewers = ["guardian_subagent"]` and usually `allowed_approval_policies = ["on-request"]` | any user reviewer value; user should also have `approval_policy = "on-request"` unless policy is forced | Effective reviewer is `guardian_subagent`; Guardian on when effective approval policy is `on-request` | | Allow both, but default to manual if user does nothing | `allowed_approvals_reviewers = ["user", "guardian_subagent"]` | omit `approvals_reviewer` | Effective reviewer is `user`; Guardian off | | Allow both, and user explicitly opts into Guardian | `allowed_approvals_reviewers = ["user", "guardian_subagent"]` | `approvals_reviewer = "guardian_subagent"` and `approval_policy = "on-request"` | Guardian on | | Invalid admin config | `allowed_approvals_reviewers = []` | anything | Config load error |
Owen Lin ·
2026-04-06 11:11:44 -07:00 -
core: remove cross-crate re-exports from lib.rs (#16512)
## Why `codex-core` was re-exporting APIs owned by sibling `codex-*` crates, which made downstream crates depend on `codex-core` as a proxy module instead of the actual owner crate. Removing those forwards makes crate boundaries explicit and lets leaf crates drop unnecessary `codex-core` dependencies. In this PR, this reduces the dependency on `codex-core` to `codex-login` in the following files: ``` codex-rs/backend-client/Cargo.toml codex-rs/mcp-server/tests/common/Cargo.toml ``` ## What - Remove `codex-rs/core/src/lib.rs` re-exports for symbols owned by `codex-login`, `codex-mcp`, `codex-rollout`, `codex-analytics`, `codex-protocol`, `codex-shell-command`, `codex-sandboxing`, `codex-tools`, and `codex-utils-path`. - Delete the `default_client` forwarding shim in `codex-rs/core`. - Update in-crate and downstream callsites to import directly from the owning `codex-*` crate. - Add direct Cargo dependencies where callsites now target the owner crate, and remove `codex-core` from `codex-rs/backend-client`.
Michael Bolin ·
2026-04-01 23:06:24 -07:00 -
chore: refactor network permissions to use explicit domain and unix socket rule maps (#15120)
## Summary This PR replaces the legacy network allow/deny list model with explicit rule maps for domains and unix sockets across managed requirements, permissions profiles, the network proxy config, and the app server protocol. Concretely, it: - introduces typed domain (`allow` / `deny`) and unix socket permission (`allow` / `none`) entries instead of separate `allowed_domains`, `denied_domains`, and `allow_unix_sockets` lists - updates config loading, managed requirements merging, and exec-policy overlays to read and upsert rule entries consistently - exposes the new shape through protocol/schema outputs, debug surfaces, and app-server config APIs - rejects the legacy list-based keys and updates docs/tests to reflect the new config format ## Why The previous representation split related network policy across multiple parallel lists, which made merging and overriding rules harder to reason about. Moving to explicit keyed permission maps gives us a single source of truth per host/socket entry, makes allow/deny precedence clearer, and gives protocol consumers access to the full rule state instead of derived projections only. ## Backward Compatibility ### Backward compatible - Managed requirements still accept the legacy `experimental_network.allowed_domains`, `experimental_network.denied_domains`, and `experimental_network.allow_unix_sockets` fields. They are normalized into the new canonical `domains` and `unix_sockets` maps internally. - App-server v2 still deserializes legacy `allowedDomains`, `deniedDomains`, and `allowUnixSockets` payloads, so older clients can continue reading managed network requirements. - App-server v2 responses still populate `allowedDomains`, `deniedDomains`, and `allowUnixSockets` as legacy compatibility views derived from the canonical maps. - `managed_allowed_domains_only` keeps the same behavior after normalization. Legacy managed allowlists still participate in the same enforcement path as canonical `domains` entries. ### Not backward compatible - Permissions profiles under `[permissions.<profile>.network]` no longer accept the legacy list-based keys. Those configs must use the canonical `[domains]` and `[unix_sockets]` tables instead of `allowed_domains`, `denied_domains`, or `allow_unix_sockets`. - Managed `experimental_network` config cannot mix canonical and legacy forms in the same block. For example, `domains` cannot be combined with `allowed_domains` or `denied_domains`, and `unix_sockets` cannot be combined with `allow_unix_sockets`. - The canonical format can express explicit `"none"` entries for unix sockets, but those entries do not round-trip through the legacy compatibility fields because the legacy fields only represent allow/deny lists. ## Testing `/target/debug/codex sandbox macos --log-denials /bin/zsh -c 'curl https://www.example.com' ` gives 200 with config ``` [permissions.workspace.network.domains] "www.example.com" = "allow" ``` and fails when set to deny: `curl: (56) CONNECT tunnel failed, response 403`. Also tested backward compatibility path by verifying that adding the following to `/etc/codex/requirements.toml` works: ``` [experimental_network] allowed_domains = ["www.example.com"] ```
Celia Chen ·
2026-03-27 06:17:59 +00:00 -
[mcp] Improve custom MCP elicitation (#15800)
- [x] Support don't ask again for custom MCP tool calls. - [x] Don't run arc in yolo mode. - [x] Run arc for custom MCP tools in always allow mode.
Matthew Zeng ·
2026-03-26 01:02:37 +00:00 -
Extract codex-analytics crate (#15748)
## Summary - move the analytics events client into codex-analytics - update codex-core and app-server callsites to use the new crate ## Testing - CI --------- Co-authored-by: Codex <noreply@openai.com>
Ahmed Ibrahim ·
2026-03-25 11:08:05 -07:00 -
[plugins] Add a flag for tool search. (#15722)
- [x] Add a flag for tool search.
Matthew Zeng ·
2026-03-25 07:00:25 +00:00 -
[app-server] Add a method to override feature flags. (#15601)
- [x] Add a method to override feature flags globally and not just thread level.
Matthew Zeng ·
2026-03-25 02:27:00 +00:00 -
Use workspace requirements for guardian prompt override (#14727)
## Summary - move `guardian_developer_instructions` from managed config into workspace-managed `requirements.toml` - have guardian continue using the override when present and otherwise fall back to the bundled local guardian prompt - keep the generalized prompt-quality improvements in the shared guardian default prompt - update requirements parsing, layering, schema, and tests for the new source of truth ## Context This replaces the earlier managed-config / MDM rollout plan. The intended rollout path is workspace-managed requirements, including cloud enterprise policies, rather than backend model metadata, Statsig, or Jamf-managed config. That keeps the default/fallback behavior local to `codex-rs` while allowing faster policy updates through the enterprise requirements plane. This is intentionally an admin-managed policy input, not a user preference: the guardian prompt should come either from the bundled `codex-rs` default or from enterprise-managed `requirements.toml`, and normal user/project/session config should not override it. ## Updating The OpenAI Prompt After this lands, the OpenAI-specific guardian prompt should be updated through the workspace Policies UI at `/codex/settings/policies` rather than through Jamf or codex-backend model metadata. Operationally: - open the workspace Policies editor as a Codex admin - edit the default `requirements.toml` policy, or a higher-precedence group-scoped override if we ever want different behavior for a subset of users - set `guardian_developer_instructions = """..."""` to the full OpenAI-specific guardian prompt text - save the policy; codex-backend stores the raw TOML and `codex-rs` fetches the effective requirements file from `/wham/config/requirements` When updating the OpenAI-specific prompt, keep it aligned with the shared default guardian policy in `codex-rs` except for intentional OpenAI-only additions. ## Testing - `cargo check --tests -p codex-core -p codex-config -p codex-cloud-requirements --message-format short` - `cargo run -p codex-core --bin codex-write-config-schema` - `cargo fmt` - `git diff --check` Co-authored-by: Codex <noreply@openai.com>
Charley Cunningham ·
2026-03-17 22:05:41 -07:00 -
Override local apps settings with requirements.toml settings (#14304)
This PR changes app and connector enablement when `requirements.toml` is present locally or via remote configuration. For apps.* entries: - `enabled = false` in `requirements.toml` overrides the user’s local `config.toml` and forces the app to be disabled. - `enabled = true` in `requirements.toml` does not re-enable an app the user has disabled in config.toml. This behavior applies whether or not the user has an explicit entry for that app in `config.toml`. It also applies to cloud-managed policies and configurations when the admin sets the override through `requirements.toml`. Scenarios tested and verified: - Remote managed, user config (present) override - Admin-defined policies & configurations include a connector override: `[apps.<appID>] enabled = false` - User's config.toml has the same connector configured with `enabled = true` - TUI/App should show connector as disabled - Connector should be unavailable for use in the composer - Remote managed, user config (absent) override - Admin-defined policies & configurations include a connector override: `[apps.<appID>] enabled = false` - User's config.toml has no entry for the the same connector - TUI/App should show connector as disabled - Connector should be unavailable for use in the composer - Locally managed, user config (present) override - Local requirements.toml includes a connector override: `[apps.<appID>] enabled = false` - User's config.toml has the same connector configured with `enabled = true` - TUI/App should show connector as disabled - Connector should be unavailable for use in the composer - Locally managed, user config (absent) override - Local requirements.toml includes a connector override: `[apps.<appID>] enabled = false` - User's config.toml has no entry for the the same connector - TUI/App should show connector as disabled - Connector should be unavailable for use in the composer <img width="1446" height="753" alt="image" src="https://github.com/user-attachments/assets/61c714ca-dcca-4952-8ad2-0afc16ff3835" /> <img width="595" height="233" alt="image" src="https://github.com/user-attachments/assets/7c8ab147-8fd7-429a-89fb-591c21c15621" />
canvrno-oai ·
2026-03-13 12:40:24 -07:00 -
Add plugin usage telemetry (#14531)
adding metrics including: * plugin used * plugin installed/uninstalled * plugin enabled/disabled
alexsong-oai ·
2026-03-12 19:22:30 -07:00 -
[app-server] Support hot-reload user config when batch writing config. (#13839)
- [x] Support hot-reload user config when batch writing config.
Matthew Zeng ·
2026-03-08 17:38:01 -07:00 -
fix: support managed network allowlist controls (#12752)
## Summary - treat `requirements.toml` `allowed_domains` and `denied_domains` as managed network baselines for the proxy - in restricted modes by default, build the effective runtime policy from the managed baseline plus user-configured allowlist and denylist entries, so common hosts can be pre-approved without blocking later user expansion - add `experimental_network.managed_allowed_domains_only = true` to pin the effective allowlist to managed entries, ignore user allowlist additions, and hard-deny non-managed domains without prompting - apply `managed_allowed_domains_only` anywhere managed network enforcement is active, including full access, while continuing to respect denied domains from all sources - add regression coverage for merged-baseline behavior, managed-only behavior, and full-access managed-only enforcement ## Behavior Assuming `requirements.toml` defines both `experimental_network.allowed_domains` and `experimental_network.denied_domains`. ### Default mode - By default, the effective allowlist is `experimental_network.allowed_domains` plus user or persisted allowlist additions. - By default, the effective denylist is `experimental_network.denied_domains` plus user or persisted denylist additions. - Allowlist misses can go through the network approval flow. - Explicit denylist hits and local or private-network blocks are still hard-denied. - When `experimental_network.managed_allowed_domains_only = true`, only managed `allowed_domains` are respected, user allowlist additions are ignored, and non-managed domains are hard-denied without prompting. - Denied domains continue to be respected from all sources. ### Full access - With managed requirements present, the effective allowlist is pinned to `experimental_network.allowed_domains`. - With managed requirements present, the effective denylist is pinned to `experimental_network.denied_domains`. - There is no allowlist-miss approval path in full access. - Explicit denylist hits are hard-denied. - `experimental_network.managed_allowed_domains_only = true` now also applies in full access, so managed-only behavior remains in effect anywhere managed network enforcement is active.
viyatb-oai ·
2026-03-06 17:52:54 -08:00 -
refactor: remove proxy admin endpoint (#13687)
## Summary - delete the network proxy admin server and its runtime listener/task plumbing - remove the admin endpoint config, runtime, requirement, protocol, schema, and debug-surface fields - update proxy docs to reflect the remaining HTTP and SOCKS listeners only
viyatb-oai ·
2026-03-05 22:03:16 -08:00 -
config: enforce enterprise feature requirements (#13388)
## Why Enterprises can already constrain approvals, sandboxing, and web search through `requirements.toml` and MDM, but feature flags were still only configurable as managed defaults. That meant an enterprise could suggest feature values, but it could not actually pin them. This change closes that gap and makes enterprise feature requirements behave like the other constrained settings. The effective feature set now stays consistent with enterprise requirements during config load, when config writes are validated, and when runtime code mutates feature flags later in the session. It also tightens the runtime API for managed features. `ManagedFeatures` now follows the same constraint-oriented shape as `Constrained<T>` instead of exposing panic-prone mutation helpers, and production code can no longer construct it through an unconstrained `From<Features>` path. The PR also hardens the `compact_resume_fork` integration coverage on Windows. After the feature-management changes, `compact_resume_after_second_compaction_preserves_history` was overflowing the libtest/Tokio thread stacks on Windows, so the test now uses an explicit larger-stack harness as a pragmatic mitigation. That may not be the ideal root-cause fix, and it merits a parallel investigation into whether part of the async future chain should be boxed to reduce stack pressure instead. ## What Changed Enterprises can now pin feature values in `requirements.toml` with the requirements-side `features` table: ```toml [features] personality = true unified_exec = false ``` Only canonical feature keys are allowed in the requirements `features` table; omitted keys remain unconstrained. - Added a requirements-side pinned feature map to `ConfigRequirementsToml`, threaded it through source-preserving requirements merge and normalization in `codex-config`, and made the TOML surface use `[features]` (while still accepting legacy `[feature_requirements]` for compatibility). - Exposed `featureRequirements` from `configRequirements/read`, regenerated the JSON/TypeScript schema artifacts, and updated the app-server README. - Wrapped the effective feature set in `ManagedFeatures`, backed by `ConstrainedWithSource<Features>`, and changed its API to mirror `Constrained<T>`: `can_set(...)`, `set(...) -> ConstraintResult<()>`, and result-returning `enable` / `disable` / `set_enabled` helpers. - Removed the legacy-usage and bulk-map passthroughs from `ManagedFeatures`; callers that need those behaviors now mutate a plain `Features` value and reapply it through `set(...)`, so the constrained wrapper remains the enforcement boundary. - Removed the production loophole for constructing unconstrained `ManagedFeatures`. Non-test code now creates it through the configured feature-loading path, and `impl From<Features> for ManagedFeatures` is restricted to `#[cfg(test)]`. - Rejected legacy feature aliases in enterprise feature requirements, and return a load error when a pinned combination cannot survive dependency normalization. - Validated config writes against enterprise feature requirements before persisting changes, including explicit conflicting writes and profile-specific feature states that normalize into invalid combinations. - Updated runtime and TUI feature-toggle paths to use the constrained setter API and to persist or apply the effective post-constraint value rather than the requested value. - Updated the `core_test_support` Bazel target to include the bundled core model-catalog fixtures in its runtime data, so helper code that resolves `core/models.json` through runfiles works in remote Bazel test environments. - Renamed the core config test coverage to emphasize that effective feature values are normalized at runtime, while conflicting persisted config writes are rejected. - Ran `compact_resume_after_second_compaction_preserves_history` inside an explicit 8 MiB test thread and Tokio runtime worker stack, following the existing larger-stack integration-test pattern, to keep the Windows `compact_resume_fork` test slice from aborting while a parallel investigation continues into whether some of the underlying async futures should be boxed. ## Verification - `cargo test -p codex-config` - `cargo test -p codex-core feature_requirements_ -- --nocapture` - `cargo test -p codex-core load_requirements_toml_produces_expected_constraints -- --nocapture` - `cargo test -p codex-core compact_resume_after_second_compaction_preserves_history -- --nocapture` - `cargo test -p codex-core compact_resume_fork -- --nocapture` - Re-ran the built `codex-core` `tests/all` binary with `RUST_MIN_STACK=262144` for `compact_resume_after_second_compaction_preserves_history` to confirm the explicit-stack harness fixes the deterministic low-stack repro. - `cargo test -p codex-core` - This still fails locally in unrelated integration areas that expect the `codex` / `test_stdio_server` binaries or hit existing `search_tool` wiremock mismatches. ## Docs `developers.openai.com/codex` should document the requirements-side `[features]` table for enterprise and MDM-managed configuration, including that it only accepts canonical feature keys and that conflicting config writes are rejected.
Michael Bolin ·
2026-03-04 04:40:22 +00:00 -
fix(network-proxy): add unix socket allow-all and update seatbelt rules (#11368)
## Summary Adds support for a Unix socket escape hatch so we can bypass socket allowlisting when explicitly enabled. ## Description * added a new flag, `network.dangerously_allow_all_unix_sockets` as an explicit escape hatch * In codex-network-proxy, enabling that flag now allows any absolute Unix socket path from x-unix-socket instead of requiring each path to be explicitly allowlisted. Relative paths are still rejected. * updated the macOS seatbelt path in core so it enforces the same Unix socket behavior: * allowlisted sockets generate explicit network* subpath rules * allow-all generates a broad network* (subpath "/") rule --------- Co-authored-by: Codex <199175422+chatgpt-codex-connector[bot]@users.noreply.github.com>
viyatb-oai ·
2026-02-20 10:56:57 -08:00 -
feat(core): add network constraints schema to requirements.toml (#10958)
## Summary Add `requirements.toml` schema support for admin-defined network constraints in the requirements layer example config: ``` [experimental_network] enabled = true allowed_domains = ["api.openai.com"] denied_domains = ["example.com"] ```
viyatb-oai ·
2026-02-07 19:48:24 +00:00 -
feat: add support for allowed_web_search_modes in requirements.toml (#10964)
This PR makes it possible to disable live web search via an enterprise config even if the user is running in `--yolo` mode (though cached web search will still be available). To do this, create `/etc/codex/requirements.toml` as follows: ```toml # "live" is not allowed; "disabled" is allowed even though not listed explicitly. allowed_web_search_modes = ["cached"] ``` Or set `requirements_toml_base64` MDM as explained on https://developers.openai.com/codex/security/#locations. ### Why - Enforce admin/MDM/`requirements.toml` constraints on web-search behavior, independent of user config and per-turn sandbox defaults. - Ensure per-turn config resolution and review-mode overrides never crash when constraints are present. ### What - Add `allowed_web_search_modes` to requirements parsing and surface it in app-server v2 `ConfigRequirements` (`allowedWebSearchModes`), with fixtures updated. - Define a requirements allowlist type (`WebSearchModeRequirement`) and normalize semantics: - `disabled` is always implicitly allowed (even if not listed). - An empty list is treated as `["disabled"]`. - Make `Config.web_search_mode` a `Constrained<WebSearchMode>` and apply requirements via `ConstrainedWithSource<WebSearchMode>`. - Update per-turn resolution (`resolve_web_search_mode_for_turn`) to: - Prefer `Live → Cached → Disabled` when `SandboxPolicy::DangerFullAccess` is active (subject to requirements), unless the user preference is explicitly `Disabled`. - Otherwise, honor the user’s preferred mode, falling back to an allowed mode when necessary. - Update TUI `/debug-config` and app-server mapping to display normalized `allowed_web_search_modes` (including implicit `disabled`). - Fix web-search integration tests to assert cached behavior under `SandboxPolicy::ReadOnly` (since `DangerFullAccess` legitimately prefers `live` when allowed).
Michael Bolin ·
2026-02-07 05:55:15 +00:00 -
Sync app-server requirements API with refreshed cloud loader (#10815)
configRequirements/read now returns updated cloud requirements after login.
xl-openai ·
2026-02-05 14:43:31 -08:00 -
Add enforce_residency to requirements (#10263)
Add `enforce_residency` to requirements.toml and thread it through to a header on `default_client`.
gt-oai ·
2026-01-31 00:26:25 +00:00 -
Wire up cloud reqs in exec, app-server (#10241)
We're fetching cloud requirements in TUI in https://github.com/openai/codex/pull/10167. This adds the same fetching in exec and app-server binaries also.
gt-oai ·
2026-01-30 23:53:41 +00:00 -
Load exec policy rules from requirements (#10190)
`requirements.toml` should be able to specify rules which always run. My intention here was that these rules could only ever be restrictive, which means the decision can be "prompt" or "forbidden" but never "allow". A requirement of "you must always allow this command" didn't make sense to me, but happy to be gaveled otherwise. Rules already applies the most restrictive decision, so we can safely merge these with rules found in other config folders.
gt-oai ·
2026-01-30 18:04:09 +00:00 -
s/mcp_server_requirements/mcp_servers (#9212)
A simple `s/mcp_server_requirements/mcp_servers/g` for an unreleased feature. @bolinfest correctly pointed out, it's already in `requirements.toml` so the `_requirements` is redundant.
gt-oai ·
2026-01-14 18:41:52 +00:00 -
Restrict MCP servers from
requirements.toml(#9101)Enterprises want to restrict the MCP servers their users can use. Admins can now specify an allowlist of MCPs in `requirements.toml`. The MCP servers are matched on both Name and Transport (local path or HTTP URL) -- both must match to allow the MCP server. This prevents circumventing the allowlist by renaming MCP servers in user config. (It is still possible to replace the local path e.g. rewrite say `/usr/local/github-mcp` with a nefarious MCP. We could allow hash pinning in the future, but that would break updates. I also think this represents a broader, out-of-scope problem.) We introduce a new field to Constrained: "normalizer". In general, it is a fn(T) -> T and applies when `Constrained<T>.set()` is called. In this particular case, it disables MCP servers which do not match the allowlist. An alternative solution would remove this and instead throw a ConstraintError. That would stop Codex launching if any MCP server was configured which didn't match. I think this is bad. We currently reuse the enabled flag on MCP servers to disable them, but don't propagate any information about why they are disabled. I'd like to add that in a follow up PR, possibly by switching out enabled with an enum. In action: ``` # MCP server config has two MCPs. We are going to allowlist one of them. ➜ codex git:(gt/restrict-mcps) ✗ cat ~/.codex/config.toml | grep mcp_servers -A1 [mcp_servers.hello_world] command = "hello-world-mcp" -- [mcp_servers.docs] command = "docs-mcp" # Restrict the MCPs to the hello_world MCP. ➜ codex git:(gt/restrict-mcps) ✗ defaults read com.openai.codex requirements_toml_base64 | base64 -d [mcp_server_allowlist.hello_world] command = "hello-world-mcp" # List the MCPs, observe hello_world is enabled and docs is disabled. ➜ codex git:(gt/restrict-mcps) ✗ just codex mcp list cargo run --bin codex -- "$@" Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.25s Running `target/debug/codex mcp list` Name Command Args Env Cwd Status Auth docs docs-mcp - - - disabled Unsupported hello_world hello-world-mcp - - - enabled Unsupported # Remove the restrictions. ➜ codex git:(gt/restrict-mcps) ✗ defaults delete com.openai.codex requirements_toml_base64 # Observe both MCPs are enabled. ➜ codex git:(gt/restrict-mcps) ✗ just codex mcp list cargo run --bin codex -- "$@" Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.25s Running `target/debug/codex mcp list` Name Command Args Env Cwd Status Auth docs docs-mcp - - - enabled Unsupported hello_world hello-world-mcp - - - enabled Unsupported # A new requirements that updates the command to one that does not match. ➜ codex git:(gt/restrict-mcps) ✗ cat ~/requirements.toml [mcp_server_allowlist.hello_world] command = "hello-world-mcp-v2" # Use those requirements. ➜ codex git:(gt/restrict-mcps) ✗ defaults write com.openai.codex requirements_toml_base64 "$(base64 -i /Users/gt/requirements.toml)" # Observe both MCPs are disabled. ➜ codex git:(gt/restrict-mcps) ✗ just codex mcp list cargo run --bin codex -- "$@" Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.75s Running `target/debug/codex mcp list` Name Command Args Env Cwd Status Auth docs docs-mcp - - - disabled Unsupported hello_world hello-world-mcp - - - disabled Unsupported ```gt-oai ·
2026-01-13 19:45:00 +00:00 -
Feat: appServer.requirementList for requirement.toml (#8800)
### Summary We are exposing requirements via `requirement/list` method from app-server so that we can conditionally disable the agent mode dropdown selection in VSCE and correctly setting the default value. ### Sample output #### `etc/codex/requirements.toml` <img width="497" height="49" alt="Screenshot 2026-01-06 at 11 32 06 PM" src="https://github.com/user-attachments/assets/fbd9402e-515f-4b9e-a158-2abb23e866a0" /> #### App server response <img width="1107" height="79" alt="Screenshot 2026-01-06 at 11 30 18 PM" src="https://github.com/user-attachments/assets/c0d669cd-54ef-4789-a26c-adb2c41950af" />
Shijie Rao ·
2026-01-07 13:57:44 -08:00 -
Michael Bolin ·
2026-01-06 07:10:27 -08:00 -
feat: clean config loading and config api (#7924)
Check the README of the `config_loader` for details
jif-oai ·
2025-12-12 12:01:24 -08:00 -
[app-server-protocol] Add types for config (#7658)
Currently the config returned by `config/read` in untyped. Add types so it's easier for client to parse the config. Since currently configs are all defined in snake case we'll keep that instead of using camel case like the rest of V2. Sample output by testing using the app server test client: ``` { < "id": "f28449f4-b015-459b-b07b-eef06980165d", < "result": { < "config": { < "approvalPolicy": null, < "compactPrompt": null, < "developerInstructions": null, < "features": { < "experimental_use_rmcp_client": true < }, < "forcedChatgptWorkspaceId": null, < "forcedLoginMethod": null, < "instructions": null, < "model": "gpt-5.1-codex-max", < "modelAutoCompactTokenLimit": null, < "modelContextWindow": null, < "modelProvider": null, < "modelReasoningEffort": null, < "modelReasoningSummary": null, < "modelVerbosity": null, < "model_providers": { < "local": { < "base_url": "http://localhost:8061/api/codex", < "env_http_headers": { < "ChatGPT-Account-ID": "OPENAI_ACCOUNT_ID" < }, < "env_key": "CHATGPT_TOKEN_STAGING", < "name": "local", < "wire_api": "responses" < } < }, < "model_reasoning_effort": "medium", < "notice": { < "hide_gpt-5.1-codex-max_migration_prompt": true, < "hide_gpt5_1_migration_prompt": true < }, < "profile": null, < "profiles": {}, < "projects": { < "/Users/celia/code": { < "trust_level": "trusted" < }, < "/Users/celia/code/codex": { < "trust_level": "trusted" < }, < "/Users/celia/code/openai": { < "trust_level": "trusted" < } < }, < "reviewModel": null, < "sandboxMode": null, < "sandboxWorkspaceWrite": null, < "tools": { < "viewImage": null, < "webSearch": null < } < }, < "origins": { < "features.experimental_use_rmcp_client": { < "name": "user", < "source": "/Users/celia/.codex/config.toml", < "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c" < }, < "model": { < "name": "user", < "source": "/Users/celia/.codex/config.toml", < "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c" < }, < "model_providers.local.base_url": { < "name": "user", < "source": "/Users/celia/.codex/config.toml", < "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c" < }, < "model_providers.local.env_http_headers.ChatGPT-Account-ID": { < "name": "user", < "source": "/Users/celia/.codex/config.toml", < "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c" < }, < "model_providers.local.env_key": { < "name": "user", < "source": "/Users/celia/.codex/config.toml", < "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c" < }, < "model_providers.local.name": { < "name": "user", < "source": "/Users/celia/.codex/config.toml", < "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c" < }, < "model_providers.local.wire_api": { < "name": "user", < "source": "/Users/celia/.codex/config.toml", < "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c" < }, < "model_reasoning_effort": { < "name": "user", < "source": "/Users/celia/.codex/config.toml", < "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c" < }, < "notice.hide_gpt-5.1-codex-max_migration_prompt": { < "name": "user", < "source": "/Users/celia/.codex/config.toml", < "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c" < }, < "notice.hide_gpt5_1_migration_prompt": { < "name": "user", < "source": "/Users/celia/.codex/config.toml", < "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c" < }, < "projects./Users/celia/code.trust_level": { < "name": "user", < "source": "/Users/celia/.codex/config.toml", < "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c" < }, < "projects./Users/celia/code/codex.trust_level": { < "name": "user", < "source": "/Users/celia/.codex/config.toml", < "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c" < }, < "projects./Users/celia/code/openai.trust_level": { < "name": "user", < "source": "/Users/celia/.codex/config.toml", < "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c" < }, < "tools.web_search": { < "name": "user", < "source": "/Users/celia/.codex/config.toml", < "version": "sha256:a1d8eaedb5d9db5dfdfa69f30fa9df2efec66bb4dd46aa67f149fcc67cd0711c" < } < } < } < } ```Celia Chen ·
2025-12-10 21:35:31 +00:00 -
[app-server] Make sure that config writes preserve comments & order or configs (#7789)
Make sure that config writes preserve comments and order of configs by utilizing the ConfigEditsBuilder in core. Tested by running a real example and made sure that nothing in the config file changes other than the configs to edit.
Celia Chen ·
2025-12-10 19:14:27 +00:00 -
[app-server] make
file_pathfor config optional (#7560)When we are writing to config using `config/value/write` or `config/batchWrite`, it always require a `config/read` before it right now in order to get the correct file path to write to. make this optional so we read from the default user config file if this is not passed in.
Celia Chen ·
2025-12-04 03:08:18 +00:00 -
jif-oai ·
2025-11-25 09:29:38 +00:00