Commit Graph

64 Commits

  • docs: document enabling experimental skills (#8024)
    ## Notes
    
    Skills are behind the experimental `skills` feature flag (disabled by
    default), but the skills guide didn't explain how to turn them on.
    
    - Add an explicit enable section to `docs/skills.md` (config +
    `--enable`)
    - Add the skills flag to `docs/config.md` and `docs/example-config.md`
    - Document the `/skills` slash command
  • docs: clarify xhigh reasoning effort on gpt-5.2 (#7911)
    ## Changes
    - Update config docs and example config comments to state that "xhigh"
    is supported on gpt-5.2 as well as gpt-5.1-codex-max
    - Adjust the FAQ model-support section to reflect broader xhigh
    availability
  • Fix toasts on Windows under WSL 2 (#7137)
    Before this: no notifications or toasts when using Codex CLI in WSL 2.
    
    After this: I get toasts from Codex
  • Removed experimental "command risk assessment" feature (#7799)
    This experimental feature received lukewarm reception during internal
    testing. Removing from the code base.
  • feat(tui2): add feature-flagged tui2 frontend (#7793)
    Introduce a new codex-tui2 crate that re-exports the existing
    interactive TUI surface and delegates run_main directly to codex-tui.
    This keeps behavior identical while giving tui2 its own crate for future
    viewport work.
    
    Wire the codex CLI to select the frontend via the tui2 feature flag.
    When the merged CLI overrides include features.tui2=true (e.g. via
    --enable tui2), interactive runs are routed through
    codex_tui2::run_main; otherwise they continue to use the original
    codex_tui::run_main.
    
    Register Feature::Tui2 in the core feature registry and add the tui2
    crate and dependency entries so the new frontend builds alongside the
    existing TUI.
    
    This is a stub that only wires up the feature flag for this.
    
    <img width="619" height="364" alt="image"
    src="https://github.com/user-attachments/assets/4893f030-932f-471e-a443-63fe6b5d8ed9"
    />
  • fix: refine the warning message and docs for deprecated tools config (#7685)
    Issue #7661 revealed that users are confused by deprecation warnings
    like:
    > `tools.web_search` is deprecated. Use `web_search_request` instead.
    
    This message misleadingly suggests renaming the config key from
    `web_search` to `web_search_request`, when the actual required change is
    to **move and rename the configuration from the `[tools]` section to the
    `[features]` section**.
    
    This PR clarifies the warning messages and documentation to make it
    clear that deprecated `[tools]` configurations should be moved to
    `[features]`. Changes made:
    - Updated deprecation warning format in `codex-rs/core/src/codex.rs:520`
    to include `[features].` prefix
    - Updated corresponding test expectations in
    `codex-rs/core/tests/suite/deprecation_notice.rs:39`
    - Improved documentation in `docs/config.md` to clarify upfront that
    `[tools]` options are deprecated in favor of `[features]`
  • fix(doc): TOML otel exporter example — multi-line inline table is inv… (#7669)
    …alid (#7668)
    
    The `otel` exporter example in `docs/config.md` is misleading and will
    cause
    the configuration parser to fail if copied verbatim.
    
    Summary
    -------
    The example uses a TOML inline table but spreads the inline-table braces
    across multiple lines. TOML inline tables must be contained on a single
    line
    (`key = { a = 1, b = 2 }`); placing newlines inside the braces triggers
    a
    parse error in most TOML parsers and prevents Codex from starting.
    
    Reproduction
    ------------
    1. Paste the snippet below into `~/.codex/config.toml` (or your project
    config).
    2. Run `codex` (or the command that loads the config).
    3. The process will fail to start with a TOML parse error similar to:
    
    ```text
    Error loading config.toml: TOML parse error at line 55, column 27
       |
    55 | exporter = { otlp-http = {
       |                           ^
    newlines are unsupported in inline tables, expected nothing
    ```
    
    Problematic snippet (as currently shown in the docs)
    ---------------------------------------------------
    ```toml
    [otel]
    exporter = { otlp-http = {
      endpoint = "https://otel.example.com/v1/logs",
      protocol = "binary",
      headers = { "x-otlp-api-key" = "${OTLP_TOKEN}" }
    }}
    ```
    
    Recommended fixes
    ------------------
    ```toml
    [otel.exporter."otlp-http"]
    endpoint = "https://otel.example.com/v1/logs"
    protocol = "binary"
    
    [otel.exporter."otlp-http".headers]
    "x-otlp-api-key" = "${OTLP_TOKEN}"
    ```
    
    Or, keep an inline table but write it on one line (valid but less
    readable):
    
    ```toml
    [otel]
    exporter = { "otlp-http" = { endpoint = "https://otel.example.com/v1/logs", protocol = "binary", headers = { "x-otlp-api-key" = "${OTLP_TOKEN}" } } }
    ```
  • docs: fix documentation of rmcp client flag (#7665)
    ## Summary
    - Updated the rmcp client flag's documentation in config.md file
    - changed it from `experimental_use_rmcp_client` to `rmcp_client`
  • Refactor execpolicy fallback evaluation (#7544)
    ## Refactor of the `execpolicy` crate
    
    To illustrate why we need this refactor, consider an agent attempting to
    run `apple | rm -rf ./`. Suppose `apple` is allowed by `execpolicy`.
    Before this PR, `execpolicy` would consider `apple` and `pear` and only
    render one rule match: `Allow`. We would skip any heuristics checks on
    `rm -rf ./` and immediately approve `apple | rm -rf ./` to run.
    
    To fix this, we now thread a `fallback` evaluation function into
    `execpolicy` that runs when no `execpolicy` rules match a given command.
    In our example, we would run `fallback` on `rm -rf ./` and prevent
    `apple | rm -rf ./` from being run without approval.
  • whitelist command prefix integration in core and tui (#7033)
    this PR enables TUI to approve commands and add their prefixes to an
    allowlist:
    <img width="708" height="605" alt="Screenshot 2025-11-21 at 4 18 07 PM"
    src="https://github.com/user-attachments/assets/56a19893-4553-4770-a881-becf79eeda32"
    />
    
    note: we only show the option to whitelist the command when 
    1) command is not multi-part (e.g `git add -A && git commit -m 'hello
    world'`)
    2) command is not already matched by an existing rule
  • Trim history.jsonl when history.max_bytes is set (#6242)
    This PR honors the `history.max_bytes` configuration parameter by
    trimming `history.jsonl` whenever it grows past the configured limit.
    While appending new entries we retain the newest record, drop the oldest
    lines to stay within the byte budget, and serialize the compacted file
    back to disk under the same lock to keep writers safe.
  • docs: clarify codex max defaults and xhigh availability (#7449)
    ## Summary
    Adds the missing `xhigh` reasoning level everywhere it should have been
    documented, and makes clear it only works with `gpt-5.1-codex-max`.
    
    ## Changes
    
    * `docs/config.md`
    
    * Add `xhigh` to the official list of reasoning levels with a note that
    `xhigh` is exclusive to Codex Max.
    
    * `docs/example-config.md`
    
    * Update the example comment adding `xhigh` as a valid option but only
    for Codex Max.
    
    * `docs/faq.md`
    
      * Update the model recommendation to `GPT-5.1 Codex Max`.
    * Mention that users can choose `high` or the newly documented `xhigh`
    level when using Codex Max.
  • Allow enterprises to skip upgrade checks and messages (#7213)
    This is a feature primarily for enterprises who centrally manage Codex
    updates.
  • Removed streamable_shell from docs (#7235)
    This config option no longer exists
    
    Addresses #7207
  • Added feature switch to disable animations in TUI (#6870)
    This PR adds support for a new feature flag `tui.animations`. By
    default, the TUI uses animations in its welcome screen, "working"
    spinners, and "shimmer" effects. This animations can interfere with
    screen readers, so it's good to provide a way to disable them.
    
    This change is inspired by [a
    PR](https://github.com/openai/codex/pull/4014) contributed by @Orinks.
    That PR has faltered a bit, but I think the core idea is sound. This
    version incorporates feedback from @aibrahim-oai. In particular:
    1. It uses a feature flag (`tui.animations`) rather than the unqualified
    CLI key `no-animations`. Feature flags are the preferred way to expose
    boolean switches. They are also exposed via CLI command switches.
    2. It includes more complete documentation.
    3. It disables a few animations that the other PR omitted.
  • feat: arcticfox in the wild (#6906)
    <img width="485" height="600" alt="image"
    src="https://github.com/user-attachments/assets/4341740d-dd58-4a3e-b69a-33a3be0606c5"
    />
    
    ---------
    
    Co-authored-by: jif-oai <jif@openai.com>
  • fix: typos in model picker (#6859)
    # External (non-OpenAI) Pull Request Requirements
    
    Before opening this Pull Request, please read the dedicated
    "Contributing" markdown file or your PR may be closed:
    https://github.com/openai/codex/blob/main/docs/contributing.md
    
    If your PR conforms to our contribution guidelines, replace this text
    with a detailed and high quality description of your changes.
    
    Include a link to a bug report or enhancement request.
  • Fix typo in config.md for MCP server (#6845)
    # External (non-OpenAI) Pull Request Requirements
    
    Before opening this Pull Request, please read the dedicated
    "Contributing" markdown file or your PR may be closed:
    https://github.com/openai/codex/blob/main/docs/contributing.md
    
    If your PR conforms to our contribution guidelines, replace this text
    with a detailed and high quality description of your changes.
    
    Include a link to a bug report or enhancement request.
  • [codex][otel] support mtls configuration (#6228)
    fix for https://github.com/openai/codex/issues/6153
    
    supports mTLS configuration and includes TLS features in the library
    build to enable secure HTTPS connections with custom root certificates.
    
    grpc:
    https://docs.rs/tonic/0.13.1/src/tonic/transport/channel/endpoint.rs.html#63
    https:
    https://docs.rs/reqwest/0.12.23/src/reqwest/async_impl/client.rs.html#516
  • Add the utility to truncate by tokens (#6746)
    - This PR is to make it on path for truncating by tokens. This path will
    be initially used by unified exec and context manager (responsible for
    MCP calls mainly).
    - We are exposing new config `calls_output_max_tokens`
    - Use `tokens` as the main budget unit but truncate based on the model
    family by Introducing `TruncationPolicy`.
    - Introduce `truncate_text` as a router for truncation based on the
    mode.
    
    In next PRs:
    - remove truncate_with_line_bytes_budget
    - Add the ability to the model to override the token budget.
  • Update defaults to gpt-5.1 (#6652)
    ## Summary
    - update documentation, example configs, and automation defaults to
    reference gpt-5.1 / gpt-5.1-codex
    - bump the CLI and core configuration defaults, model presets, and error
    messaging to the new models while keeping the model-family/tool coverage
    for legacy slugs
    - refresh tests, fixtures, and TUI snapshots so they expect the upgraded
    defaults
    
    ## Testing
    - `cargo test -p codex-core
    config::tests::test_precedence_fixture_with_gpt5_profile`
    
    
    ------
    [Codex
    Task](https://chatgpt.com/codex/tasks/task_i_6916c5b3c2b08321ace04ee38604fc6b)
  • LM Studio OSS Support (#2312)
    ## Overview
    
    Adds LM Studio OSS support. Closes #1883
    
    
    ### Changes
    This PR enhances the behavior of `--oss` flag to support LM Studio as a
    provider. Additionally, it introduces a new flag`--local-provider` which
    can take in `lmstudio` or `ollama` as values if the user wants to
    explicitly choose which one to use.
    
    If no provider is specified `codex --oss` will auto-select the provider
    based on whichever is running.
    
    #### Additional enhancements 
    The default can be set using `oss-provider` in config like:
    
    ```
    oss_provider = "lmstudio"
    ```
    
    For non-interactive users, they will need to either provide the provider
    as an arg or have it in their `config.toml`
    
    ### Notes
    For best performance, [set the default context
    length](https://lmstudio.ai/docs/app/advanced/per-model) for gpt-oss to
    the maximum your machine can support
    
    ---------
    
    Co-authored-by: Matt Clayton <matt@lmstudio.ai>
    Co-authored-by: Eric Traut <etraut@openai.com>
  • Enable TUI notifications by default (#6633)
    ## Summary
    - default the `tui.notifications` setting to enabled so desktop
    notifications work out of the box
    - update configuration tests and documentation to reflect the new
    default
    
    ## Testing
    - `cargo test -p codex-core` *(fails:
    `exec::tests::kill_child_process_group_kills_grandchildren_on_timeout`
    is flaky in this sandbox because the spawned grandchild process stays
    alive)*
    - `cargo test -p codex-core
    exec::tests::kill_child_process_group_kills_grandchildren_on_timeout`
    *(fails: same sandbox limitation as above)*
    
    ------
    [Codex
    Task](https://chatgpt.com/codex/tasks/task_i_69166f811144832c9e8aaf8ee2642373)
  • Updated docs to reflect recent changes in web_search configuration (#6376)
    This is a simplified version of [a
    PR](https://github.com/openai/codex/pull/6134) supplied by a community
    member.
    
    It updates the docs to reflect a recent config deprecation.
  • fix: Update the deprecation message to link to the docs (#6211)
    The deprecation message is currently a bit confusing. Users may not
    understand what is `[features].x`. I updated the docs and the
    deprecation message for more guidance.
    
    ---------
    
    Co-authored-by: Gabriel Peal <gpeal@users.noreply.github.com>
  • Fixing small typo in docs (#5659)
    Fixing a typo in the docs
    
    Co-authored-by: Eric Traut <etraut@openai.com>
  • [Hygiene] Remove include_view_image_tool config (#5976)
    There's still some debate about whether we want to expose
    `tools.view_image` or `feature.view_image` so those are left unchanged
    for now, but this old `include_view_image_tool` config is good-to-go.
    Also updated the doc to reflect that `view_image` tool is now by default
    true.
  • [Auth] Choose which auth storage to use based on config (#5792)
    This PR is a follow-up to #5591. It allows users to choose which auth
    storage mode they want by using the new
    `cli_auth_credentials_store_mode` config.
  • [MCP] Remove the legacy stdio client in favor of rmcp (#5529)
    I haven't heard of any issues with the studio rmcp client so let's
    remove the legacy one and default to the new one.
    
    Any code changes are moving code from the adapter inline but there
    should be no meaningful functionality changes.
  • feat: include cwd in notify payload (#5415)
    Expose the session cwd in the notify payload and update docs so scripts
    and extensions receive the real project path; users get accurate
    project-aware notifications in CLI and VS Code.
    
    Fixes #5387
  • [MCP] Add configuration options to enable or disable specific tools (#5367)
    Some MCP servers expose a lot of tools. In those cases, it is reasonable
    to allow/denylist tools for Codex to use so it doesn't get overwhelmed
    with too many tools.
    
    The new configuration options available in the `mcp_server` toml table
    are:
    * `enabled_tools`
    * `disabled_tools`
    
    Fixes #4796
  • Add forced_chatgpt_workspace_id and forced_login_method configuration options (#5303)
    This PR adds support for configs to specify a forced login method
    (chatgpt or api) as well as a forced chatgpt account id. This lets
    enterprises uses [managed
    configs](https://developers.openai.com/codex/security#managed-configuration)
    to force all employees to use their company's workspace instead of their
    own or any other.
    
    When a workspace id is set, a query param is sent to the login flow
    which auto-selects the given workspace or errors if the user isn't a
    member of it.
    
    This PR is large but a large % of it is tests, wiring, and required
    formatting changes.
    
    API login with chatgpt forced
    <img width="1592" height="116" alt="CleanShot 2025-10-19 at 22 40 04"
    src="https://github.com/user-attachments/assets/560c6bb4-a20a-4a37-95af-93df39d057dd"
    />
    
    ChatGPT login with api forced
    <img width="1018" height="100" alt="CleanShot 2025-10-19 at 22 40 29"
    src="https://github.com/user-attachments/assets/d010bbbb-9c8d-4227-9eda-e55bf043b4af"
    />
    
    Onboarding with api forced
    <img width="892" height="460" alt="CleanShot 2025-10-19 at 22 41 02"
    src="https://github.com/user-attachments/assets/cc0ed45c-b257-4d62-a32e-6ca7514b5edd"
    />
    
    Onboarding with ChatGPT forced
    <img width="1154" height="426" alt="CleanShot 2025-10-19 at 22 41 27"
    src="https://github.com/user-attachments/assets/41c41417-dc68-4bb4-b3e7-3b7769f7e6a1"
    />
    
    Logging in with the wrong workspace
    <img width="2222" height="84" alt="CleanShot 2025-10-19 at 22 42 31"
    src="https://github.com/user-attachments/assets/0ff4222c-f626-4dd3-b035-0b7fe998a046"
    />
  • docs: align sandbox defaults, dedupe sections and improve getting started guide (#5357)
    Tightened the docs so the sandbox guide matches reality, noted the new
    tools.view_image toggle next to web search, and linked the README to the
    getting-started guide which now owns the familiar tips (backtrack, --cd,
    --add-dir, etc.).
  • fix: config.md docs inaccuracies (#5355)
    Updated the configuration guide so it matches the current CLI behavior.
    Clarified the platform-specific default model, explained how custom
    model-providers interact with bundled ones, refreshed the streamable
    HTTP/MCP section with accurate guidance on the RMCP client and OAuth
    flag, and removed stale keys from the reference table.
  • docs: improve overall documentation (#5354)
    Update FAQ, improve general structure for config, add more links across
    the sections in the documentation, remove out of date and duplicate
    content and better explain certain concepts such as approvals and
    sandboxing.
  • [MCP] Add support for resources (#5239)
    This PR adds support for [MCP
    resources](https://modelcontextprotocol.io/specification/2025-06-18/server/resources)
    by adding three new tools for the model:
    1. `list_resources`
    2. `list_resource_templates`
    3. `read_resource`
    
    These 3 tools correspond to the [three primary MCP resource protocol
    messages](https://modelcontextprotocol.io/specification/2025-06-18/server/resources#protocol-messages).
    
    Example of listing and reading a GitHub resource tempalte
    <img width="2984" height="804" alt="CleanShot 2025-10-15 at 17 31 10"
    src="https://github.com/user-attachments/assets/89b7f215-2e2a-41c5-90dd-b932ac84a585"
    />
    
    `/mcp` with Figma configured
    <img width="2984" height="442" alt="CleanShot 2025-10-15 at 18 29 35"
    src="https://github.com/user-attachments/assets/a7578080-2ed2-4c59-b9b4-d8461f90d8ee"
    />
    
    Fixes #4956
  • [MCP] Allow specifying cwd and additional env vars (#5246)
    This makes stdio mcp servers more flexible by allowing users to specify
    the cwd to run the server command from and adding additional environment
    variables to be passed through to the server.
    
    Example config using the test server in this repo:
    ```toml
    [mcp_servers.test_stdio]
    cwd = "/Users/<user>/code/codex/codex-rs"
    command = "cargo"
    args = ["run", "--bin", "test_stdio_server"]
    env_vars = ["MCP_TEST_VALUE"]
    ```
    
    @bolinfest I know you hate these env var tests but let's roll with this
    for now. I may take a stab at the env guard + serial macro at some
    point.
  • Fix notify documentation to use emitted input-messages key (#5071)
    ## Summary
    - align the notify configuration example with the CLI payload by reading
    the `input-messages` key
    
    Fixes #4954
    
    
    ------
    https://chatgpt.com/codex/tasks/task_i_68e95e2be6ec832c8d09d6c65aac7c93
  • [codex][otel] propagate user email in otel events (#5223)
    include user email into otel events for proper user-level attribution in
    case of workspace setup
  • [MCP] Add an enabled config field (#4917)
    This lets users more easily toggle MCP servers.
  • [MCP] Improve docs (#4811)
    Updated, expanded on, clarified, and deduplicated some MCP docs
  • chore: subject docs/*.md to Prettier checks (#4645)
    Apparently we were not running our `pnpm run prettier` check in CI, so
    many files that were covered by the existing Prettier check were not
    well-formatted.
    
    This updates CI and formats the files.
  • [MCP] Add support for MCP Oauth credentials (#4517)
    This PR adds oauth login support to streamable http servers when
    `experimental_use_rmcp_client` is enabled.
    
    This PR is large but represents the minimal amount of work required for
    this to work. To keep this PR smaller, login can only be done with
    `codex mcp login` and `codex mcp logout` but it doesn't appear in `/mcp`
    or `codex mcp list` yet. Fingers crossed that this is the last large MCP
    PR and that subsequent PRs can be smaller.
    
    Under the hood, credentials are stored using platform credential
    managers using the [keyring crate](https://crates.io/crates/keyring).
    When the keyring isn't available, it falls back to storing credentials
    in `CODEX_HOME/.credentials.json` which is consistent with how other
    coding agents handle authentication.
    
    I tested this on macOS, Windows, WSL (ubuntu), and Linux. I wasn't able
    to test the dbus store on linux but did verify that the fallback works.
    
    One quirk is that if you have credentials, during development, every
    build will have its own ad-hoc binary so the keyring won't recognize the
    reader as being the same as the write so it may ask for the user's
    password. I may add an override to disable this or allow
    users/enterprises to opt-out of the keyring storage if it causes issues.
    
    <img width="5064" height="686" alt="CleanShot 2025-09-30 at 19 31 40"
    src="https://github.com/user-attachments/assets/9573f9b4-07f1-4160-83b8-2920db287e2d"
    />
    <img width="745" height="486" alt="image"
    src="https://github.com/user-attachments/assets/9562649b-ea5f-4f22-ace2-d0cb438b143e"
    />
  • Fall back to configured instruction files if AGENTS.md isn't available (#4544)
    Allow users to configure an agents.md alternative to consume, but warn
    the user it may degrade model performance.
    
    Fixes #4376
  • OpenTelemetry events (#2103)
    ### Title
    
    ## otel
    
    Codex can emit [OpenTelemetry](https://opentelemetry.io/) **log events**
    that
    describe each run: outbound API requests, streamed responses, user
    input,
    tool-approval decisions, and the result of every tool invocation. Export
    is
    **disabled by default** so local runs remain self-contained. Opt in by
    adding an
    `[otel]` table and choosing an exporter.
    
    ```toml
    [otel]
    environment = "staging"   # defaults to "dev"
    exporter = "none"          # defaults to "none"; set to otlp-http or otlp-grpc to send events
    log_user_prompt = false    # defaults to false; redact prompt text unless explicitly enabled
    ```
    
    Codex tags every exported event with `service.name = "codex-cli"`, the
    CLI
    version, and an `env` attribute so downstream collectors can distinguish
    dev/staging/prod traffic. Only telemetry produced inside the
    `codex_otel`
    crate—the events listed below—is forwarded to the exporter.
    
    ### Event catalog
    
    Every event shares a common set of metadata fields: `event.timestamp`,
    `conversation.id`, `app.version`, `auth_mode` (when available),
    `user.account_id` (when available), `terminal.type`, `model`, and
    `slug`.
    
    With OTEL enabled Codex emits the following event types (in addition to
    the
    metadata above):
    
    - `codex.api_request`
      - `cf_ray` (optional)
      - `attempt`
      - `duration_ms`
      - `http.response.status_code` (optional)
      - `error.message` (failures)
    - `codex.sse_event`
      - `event.kind`
      - `duration_ms`
      - `error.message` (failures)
      - `input_token_count` (completion only)
      - `output_token_count` (completion only)
      - `cached_token_count` (completion only, optional)
      - `reasoning_token_count` (completion only, optional)
      - `tool_token_count` (completion only)
    - `codex.user_prompt`
      - `prompt_length`
      - `prompt` (redacted unless `log_user_prompt = true`)
    - `codex.tool_decision`
      - `tool_name`
      - `call_id`
    - `decision` (`approved`, `approved_for_session`, `denied`, or `abort`)
      - `source` (`config` or `user`)
    - `codex.tool_result`
      - `tool_name`
      - `call_id`
      - `arguments`
      - `duration_ms` (execution time for the tool)
      - `success` (`"true"` or `"false"`)
      - `output`
    
    ### Choosing an exporter
    
    Set `otel.exporter` to control where events go:
    
    - `none` – leaves instrumentation active but skips exporting. This is
    the
      default.
    - `otlp-http` – posts OTLP log records to an OTLP/HTTP collector.
    Specify the
      endpoint, protocol, and headers your collector expects:
    
      ```toml
      [otel]
      exporter = { otlp-http = {
        endpoint = "https://otel.example.com/v1/logs",
        protocol = "binary",
        headers = { "x-otlp-api-key" = "${OTLP_TOKEN}" }
      }}
      ```
    
    - `otlp-grpc` – streams OTLP log records over gRPC. Provide the endpoint
    and any
      metadata headers:
    
      ```toml
      [otel]
      exporter = { otlp-grpc = {
        endpoint = "https://otel.example.com:4317",
        headers = { "x-otlp-meta" = "abc123" }
      }}
      ```
    
    If the exporter is `none` nothing is written anywhere; otherwise you
    must run or point to your
    own collector. All exporters run on a background batch worker that is
    flushed on
    shutdown.
    
    If you build Codex from source the OTEL crate is still behind an `otel`
    feature
    flag; the official prebuilt binaries ship with the feature enabled. When
    the
    feature is disabled the telemetry hooks become no-ops so the CLI
    continues to
    function without the extra dependencies.
    
    ---------
    
    Co-authored-by: Anton Panasenko <apanasenko@openai.com>