Files
codex/codex-rs/debug-client
jif-oai 3cc9122ee2 feat: experimental flags (#10231)
## Problem being solved
- We need a single, reliable way to mark app-server API surface as
experimental so that:
  1. the runtime can reject experimental usage unless the client opts in
2. generated TS/JSON schemas can exclude experimental methods/fields for
stable clients.

Right now that’s easy to drift or miss when done ad-hoc.

## How to declare experimental methods and fields
- **Experimental method**: add `#[experimental("method/name")]` to the
`ClientRequest` variant in `client_request_definitions!`.
- **Experimental field**: on the params struct, derive `ExperimentalApi`
and annotate the field with `#[experimental("method/name.field")]` + set
`inspect_params: true` for the method variant so
`ClientRequest::experimental_reason()` inspects params for experimental
fields.

## How the macro solves it
- The new derive macro lives in
`codex-rs/codex-experimental-api-macros/src/lib.rs` and is used via
`#[derive(ExperimentalApi)]` plus `#[experimental("reason")]`
attributes.
- **Structs**:
- Generates `ExperimentalApi::experimental_reason(&self)` that checks
only annotated fields.
  - The “presence” check is type-aware:
    - `Option<T>`: `is_some_and(...)` recursively checks inner.
    - `Vec`/`HashMap`/`BTreeMap`: must be non-empty.
    - `bool`: must be `true`.
    - Other types: considered present (returns `true`).
- Registers each experimental field in an `inventory` with `(type_name,
serialized field name, reason)` and exposes `EXPERIMENTAL_FIELDS` for
that type. Field names are converted from `snake_case` to `camelCase`
for schema/TS filtering.
- **Enums**:
- Generates an exhaustive `match` returning `Some(reason)` for annotated
variants and `None` otherwise (no wildcard arm).
- **Wiring**:
- Runtime gating uses `ExperimentalApi::experimental_reason()` in
`codex-rs/app-server/src/message_processor.rs` to reject requests unless
`InitializeParams.capabilities.experimental_api == true`.
- Schema/TS export filters use the inventory list and
`EXPERIMENTAL_CLIENT_METHODS` from `client_request_definitions!` to
strip experimental methods/fields when `experimental_api` is false.
2026-02-02 11:06:50 +00:00
..
2026-02-02 11:06:50 +00:00

WARNING: this code is mainly generated by Codex and should not be used in production

codex-debug-client

A tiny interactive client for codex app-server (protocol v2 only). It prints all JSON-RPC lines from the server and lets you send new turns as you type.

Usage

Start the app-server client (it will spawn codex app-server itself):

cargo run -p codex-debug-client -- \
  --codex-bin codex \
  --approval-policy on-request

You can resume a specific thread:

cargo run -p codex-debug-client -- --thread-id thr_123

CLI flags

  • --codex-bin <path>: path to the codex binary (default: codex).
  • -c, --config key=value: pass through --config overrides to codex.
  • --thread-id <id>: resume a thread instead of starting a new one.
  • --approval-policy <policy>: untrusted, on-failure, on-request, never.
  • --auto-approve: auto-approve command/file-change approvals (default: decline).
  • --final-only: only show completed assistant messages and tool items.
  • --model <name>: optional model override for thread start/resume.
  • --model-provider <name>: optional provider override.
  • --cwd <path>: optional working directory override.

Interactive commands

Type a line to send it as a new turn. Commands are prefixed with ::

  • :help show help
  • :new start a new thread
  • :resume <thread-id> resume a thread
  • :use <thread-id> switch active thread without resuming
  • :refresh-thread list available threads
  • :quit exit

The prompt shows the active thread id. Client messages (help, errors, approvals) print to stderr; raw server JSON prints to stdout so you can pipe/record it unless --final-only is set.

Notes

  • The client performs the required initialize/initialized handshake.
  • It prints every server notification and response line as it arrives.
  • Approvals for item/commandExecution/requestApproval and item/fileChange/requestApproval are auto-responded to with decline unless --auto-approve is set.