feat: Complete LLMX v0.1.0 - Rebrand from Codex with LiteLLM Integration

This release represents a comprehensive transformation of the codebase from Codex to LLMX,
enhanced with LiteLLM integration to support 100+ LLM providers through a unified API.

## Major Changes

### Phase 1: Repository & Infrastructure Setup
- Established new repository structure and branching strategy
- Created comprehensive project documentation (CLAUDE.md, LITELLM-SETUP.md)
- Set up development environment and tooling configuration

### Phase 2: Rust Workspace Transformation
- Renamed all Rust crates from `codex-*` to `llmx-*` (30+ crates)
- Updated package names, binary names, and workspace members
- Renamed core modules: codex.rs → llmx.rs, codex_delegate.rs → llmx_delegate.rs
- Updated all internal references, imports, and type names
- Renamed directories: codex-rs/ → llmx-rs/, codex-backend-openapi-models/ → llmx-backend-openapi-models/
- Fixed all Rust compilation errors after mass rename

### Phase 3: LiteLLM Integration
- Integrated LiteLLM for multi-provider LLM support (Anthropic, OpenAI, Azure, Google AI, AWS Bedrock, etc.)
- Implemented OpenAI-compatible Chat Completions API support
- Added model family detection and provider-specific handling
- Updated authentication to support LiteLLM API keys
- Renamed environment variables: OPENAI_BASE_URL → LLMX_BASE_URL
- Added LLMX_API_KEY for unified authentication
- Enhanced error handling for Chat Completions API responses
- Implemented fallback mechanisms between Responses API and Chat Completions API

### Phase 4: TypeScript/Node.js Components
- Renamed npm package: @codex/codex-cli → @valknar/llmx
- Updated TypeScript SDK to use new LLMX APIs and endpoints
- Fixed all TypeScript compilation and linting errors
- Updated SDK tests to support both API backends
- Enhanced mock server to handle multiple API formats
- Updated build scripts for cross-platform packaging

### Phase 5: Configuration & Documentation
- Updated all configuration files to use LLMX naming
- Rewrote README and documentation for LLMX branding
- Updated config paths: ~/.codex/ → ~/.llmx/
- Added comprehensive LiteLLM setup guide
- Updated all user-facing strings and help text
- Created release plan and migration documentation

### Phase 6: Testing & Validation
- Fixed all Rust tests for new naming scheme
- Updated snapshot tests in TUI (36 frame files)
- Fixed authentication storage tests
- Updated Chat Completions payload and SSE tests
- Fixed SDK tests for new API endpoints
- Ensured compatibility with Claude Sonnet 4.5 model
- Fixed test environment variables (LLMX_API_KEY, LLMX_BASE_URL)

### Phase 7: Build & Release Pipeline
- Updated GitHub Actions workflows for LLMX binary names
- Fixed rust-release.yml to reference llmx-rs/ instead of codex-rs/
- Updated CI/CD pipelines for new package names
- Made Apple code signing optional in release workflow
- Enhanced npm packaging resilience for partial platform builds
- Added Windows sandbox support to workspace
- Updated dotslash configuration for new binary names

### Phase 8: Final Polish
- Renamed all assets (.github images, labels, templates)
- Updated VSCode and DevContainer configurations
- Fixed all clippy warnings and formatting issues
- Applied cargo fmt and prettier formatting across codebase
- Updated issue templates and pull request templates
- Fixed all remaining UI text references

## Technical Details

**Breaking Changes:**
- Binary name changed from `codex` to `llmx`
- Config directory changed from `~/.codex/` to `~/.llmx/`
- Environment variables renamed (CODEX_* → LLMX_*)
- npm package renamed to `@valknar/llmx`

**New Features:**
- Support for 100+ LLM providers via LiteLLM
- Unified authentication with LLMX_API_KEY
- Enhanced model provider detection and handling
- Improved error handling and fallback mechanisms

**Files Changed:**
- 578 files modified across Rust, TypeScript, and documentation
- 30+ Rust crates renamed and updated
- Complete rebrand of UI, CLI, and documentation
- All tests updated and passing

**Dependencies:**
- Updated Cargo.lock with new package names
- Updated npm dependencies in llmx-cli
- Enhanced OpenAPI models for LLMX backend

This release establishes LLMX as a standalone project with comprehensive LiteLLM
integration, maintaining full backward compatibility with existing functionality
while opening support for a wide ecosystem of LLM providers.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Sebastian Krüger <support@pivoine.art>
This commit is contained in:
Sebastian Krüger
2025-11-12 20:40:44 +01:00
parent 052b052832
commit 3c7efc58c8
1248 changed files with 10085 additions and 9580 deletions

View File

@@ -1,6 +1,6 @@
# Config
Codex configuration gives you fine-grained control over the model, execution environment, and integrations available to the CLI. Use this guide alongside the workflows in [`codex exec`](./exec.md), the guardrails in [Sandbox & approvals](./sandbox.md), and project guidance from [AGENTS.md discovery](./agents_md.md).
LLMX configuration gives you fine-grained control over the model, execution environment, and integrations available to the CLI. Use this guide alongside the workflows in [`llmx exec`](./exec.md), the guardrails in [Sandbox & approvals](./sandbox.md), and project guidance from [AGENTS.md discovery](./agents_md.md).
## Quick navigation
@@ -12,24 +12,24 @@ Codex configuration gives you fine-grained control over the model, execution env
- [Profiles and overrides](#profiles-and-overrides)
- [Reference table](#config-reference)
Codex supports several mechanisms for setting config values:
LLMX supports several mechanisms for setting config values:
- Config-specific command-line flags, such as `--model o3` (highest precedence).
- A generic `-c`/`--config` flag that takes a `key=value` pair, such as `--config model="o3"`.
- The key can contain dots to set a value deeper than the root, e.g. `--config model_providers.openai.wire_api="chat"`.
- For consistency with `config.toml`, values are a string in TOML format rather than JSON format, so use `key='{a = 1, b = 2}'` rather than `key='{"a": 1, "b": 2}'`.
- The quotes around the value are necessary, as without them your shell would split the config argument on spaces, resulting in `codex` receiving `-c key={a` with (invalid) additional arguments `=`, `1,`, `b`, `=`, `2}`.
- The quotes around the value are necessary, as without them your shell would split the config argument on spaces, resulting in `llmx` receiving `-c key={a` with (invalid) additional arguments `=`, `1,`, `b`, `=`, `2}`.
- Values can contain any TOML object, such as `--config shell_environment_policy.include_only='["PATH", "HOME", "USER"]'`.
- If `value` cannot be parsed as a valid TOML value, it is treated as a string value. This means that `-c model='"o3"'` and `-c model=o3` are equivalent.
- In the first case, the value is the TOML string `"o3"`, while in the second the value is `o3`, which is not valid TOML and therefore treated as the TOML string `"o3"`.
- Because quotes are interpreted by one's shell, `-c key="true"` will be correctly interpreted in TOML as `key = true` (a boolean) and not `key = "true"` (a string). If for some reason you needed the string `"true"`, you would need to use `-c key='"true"'` (note the two sets of quotes).
- The `$CODEX_HOME/config.toml` configuration file where the `CODEX_HOME` environment value defaults to `~/.codex`. (Note `CODEX_HOME` will also be where logs and other Codex-related information are stored.)
- The `$LLMX_HOME/config.toml` configuration file where the `LLMX_HOME` environment value defaults to `~/.llmx`. (Note `LLMX_HOME` will also be where logs and other LLMX-related information are stored.)
Both the `--config` flag and the `config.toml` file support the following options:
## Feature flags
Optional and experimental capabilities are toggled via the `[features]` table in `$CODEX_HOME/config.toml`. If you see a deprecation notice mentioning a legacy key (for example `experimental_use_exec_command_tool`), move the setting into `[features]` or pass `--enable <feature>`.
Optional and experimental capabilities are toggled via the `[features]` table in `$LLMX_HOME/config.toml`. If you see a deprecation notice mentioning a legacy key (for example `experimental_use_exec_command_tool`), move the setting into `[features]` or pass `--enable <feature>`.
```toml
[features]
@@ -61,15 +61,15 @@ Notes:
### model
The model that Codex should use.
The model that LLMX should use.
```toml
model = "gpt-5" # overrides the default ("gpt-5-codex" on macOS/Linux, "gpt-5" on Windows)
model = "gpt-5" # overrides the default ("gpt-5-llmx" on macOS/Linux, "gpt-5" on Windows)
```
### model_providers
This option lets you add to the default set of model providers bundled with Codex. The map key becomes the value you use with `model_provider` to select the provider.
This option lets you add to the default set of model providers bundled with LLMX. The map key becomes the value you use with `model_provider` to select the provider.
> [!NOTE]
> Built-in providers are not overwritten when you reuse their key. Entries you add only take effect when the key is **new**; for example `[model_providers.openai]` leaves the original OpenAI definition untouched. To customize the bundled OpenAI provider, prefer the dedicated knobs (for example the `OPENAI_BASE_URL` environment variable) or register a new provider key and point `model_provider` at it.
@@ -82,13 +82,13 @@ model = "gpt-4o"
model_provider = "openai-chat-completions"
[model_providers.openai-chat-completions]
# Name of the provider that will be displayed in the Codex UI.
# Name of the provider that will be displayed in the LLMX UI.
name = "OpenAI using Chat Completions"
# The path `/chat/completions` will be amended to this URL to make the POST
# request for the chat completions.
base_url = "https://api.openai.com/v1"
# If `env_key` is set, identifies an environment variable that must be set when
# using Codex with this provider. The value of the environment variable must be
# using LLMX with this provider. The value of the environment variable must be
# non-empty and will be used in the `Bearer TOKEN` HTTP header for the POST request.
env_key = "OPENAI_API_KEY"
# Valid values for wire_api are "chat" and "responses". Defaults to "chat" if omitted.
@@ -98,7 +98,7 @@ wire_api = "chat"
query_params = {}
```
Note this makes it possible to use Codex CLI with non-OpenAI models, so long as they use a wire API that is compatible with the OpenAI chat completions API. For example, you could define the following provider to use Codex CLI with Ollama running locally:
Note this makes it possible to use LLMX CLI with non-OpenAI models, so long as they use a wire API that is compatible with the OpenAI chat completions API. For example, you could define the following provider to use LLMX CLI with Ollama running locally:
```toml
[model_providers.ollama]
@@ -145,7 +145,7 @@ query_params = { api-version = "2025-04-01-preview" }
wire_api = "responses"
```
Export your key before launching Codex: `export AZURE_OPENAI_API_KEY=…`
Export your key before launching LLMX: `export AZURE_OPENAI_API_KEY=…`
#### Per-provider network tuning
@@ -166,15 +166,15 @@ stream_idle_timeout_ms = 300000 # 5m idle timeout
##### request_max_retries
How many times Codex will retry a failed HTTP request to the model provider. Defaults to `4`.
How many times LLMX will retry a failed HTTP request to the model provider. Defaults to `4`.
##### stream_max_retries
Number of times Codex will attempt to reconnect when a streaming response is interrupted. Defaults to `5`.
Number of times LLMX will attempt to reconnect when a streaming response is interrupted. Defaults to `5`.
##### stream_idle_timeout_ms
How long Codex will wait for activity on a streaming response before treating the connection as lost. Defaults to `300_000` (5 minutes).
How long LLMX will wait for activity on a streaming response before treating the connection as lost. Defaults to `300_000` (5 minutes).
### model_provider
@@ -191,7 +191,7 @@ model = "mistral"
### model_reasoning_effort
If the selected model is known to support reasoning (for example: `o3`, `o4-mini`, `codex-*`, `gpt-5`, `gpt-5-codex`), reasoning is enabled by default when using the Responses API. As explained in the [OpenAI Platform documentation](https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning), this can be set to:
If the selected model is known to support reasoning (for example: `o3`, `o4-mini`, `llmx-*`, `gpt-5`, `gpt-5-llmx`), reasoning is enabled by default when using the Responses API. As explained in the [OpenAI Platform documentation](https://platform.openai.com/docs/guides/reasoning?api-mode=responses#get-started-with-reasoning), this can be set to:
- `"minimal"`
- `"low"`
@@ -202,7 +202,7 @@ Note: to minimize reasoning, choose `"minimal"`.
### model_reasoning_summary
If the model name starts with `"o"` (as in `"o3"` or `"o4-mini"`) or `"codex"`, reasoning is enabled by default when using the Responses API. As explained in the [OpenAI Platform documentation](https://platform.openai.com/docs/guides/reasoning?api-mode=responses#reasoning-summaries), this can be set to:
If the model name starts with `"o"` (as in `"o3"` or `"o4-mini"`) or `"llmx"`, reasoning is enabled by default when using the Responses API. As explained in the [OpenAI Platform documentation](https://platform.openai.com/docs/guides/reasoning?api-mode=responses#reasoning-summaries), this can be set to:
- `"auto"` (default)
- `"concise"`
@@ -222,7 +222,7 @@ Controls output length/detail on GPT5 family models when using the Responses
- `"medium"` (default when omitted)
- `"high"`
When set, Codex includes a `text` object in the request payload with the configured verbosity, for example: `"text": { "verbosity": "low" }`.
When set, LLMX includes a `text` object in the request payload with the configured verbosity, for example: `"text": { "verbosity": "low" }`.
Example:
@@ -245,26 +245,26 @@ model_supports_reasoning_summaries = true
The size of the context window for the model, in tokens.
In general, Codex knows the context window for the most common OpenAI models, but if you are using a new model with an old version of the Codex CLI, then you can use `model_context_window` to tell Codex what value to use to determine how much context is left during a conversation.
In general, LLMX knows the context window for the most common OpenAI models, but if you are using a new model with an old version of the LLMX CLI, then you can use `model_context_window` to tell LLMX what value to use to determine how much context is left during a conversation.
### model_max_output_tokens
This is analogous to `model_context_window`, but for the maximum number of output tokens for the model.
> See also [`codex exec`](./exec.md) to see how these model settings influence non-interactive runs.
> See also [`llmx exec`](./exec.md) to see how these model settings influence non-interactive runs.
## Execution environment
### approval_policy
Determines when the user should be prompted to approve whether Codex can execute a command:
Determines when the user should be prompted to approve whether LLMX can execute a command:
```toml
# Codex has hardcoded logic that defines a set of "trusted" commands.
# Setting the approval_policy to `untrusted` means that Codex will prompt the
# LLMX has hardcoded logic that defines a set of "trusted" commands.
# Setting the approval_policy to `untrusted` means that LLMX will prompt the
# user before running a command not in the "trusted" set.
#
# See https://github.com/openai/codex/issues/1260 for the plan to enable
# See https://github.com/valknar/llmx/issues/1260 for the plan to enable
# end-users to define their own trusted commands.
approval_policy = "untrusted"
```
@@ -272,7 +272,7 @@ approval_policy = "untrusted"
If you want to be notified whenever a command fails, use "on-failure":
```toml
# If the command fails when run in the sandbox, Codex asks for permission to
# If the command fails when run in the sandbox, LLMX asks for permission to
# retry the command outside the sandbox.
approval_policy = "on-failure"
```
@@ -287,14 +287,14 @@ approval_policy = "on-request"
Alternatively, you can have the model run until it is done, and never ask to run a command with escalated permissions:
```toml
# User is never prompted: if the command fails, Codex will automatically try
# User is never prompted: if the command fails, LLMX will automatically try
# something out. Note the `exec` subcommand always uses this mode.
approval_policy = "never"
```
### sandbox_mode
Codex executes model-generated shell commands inside an OS-level sandbox.
LLMX executes model-generated shell commands inside an OS-level sandbox.
In most cases you can pick the desired behaviour with a single option:
@@ -306,9 +306,9 @@ sandbox_mode = "read-only"
The default policy is `read-only`, which means commands can read any file on
disk, but attempts to write a file or access the network will be blocked.
A more relaxed policy is `workspace-write`. When specified, the current working directory for the Codex task will be writable (as well as `$TMPDIR` on macOS). Note that the CLI defaults to using the directory where it was spawned as `cwd`, though this can be overridden using `--cwd/-C`.
A more relaxed policy is `workspace-write`. When specified, the current working directory for the LLMX task will be writable (as well as `$TMPDIR` on macOS). Note that the CLI defaults to using the directory where it was spawned as `cwd`, though this can be overridden using `--cwd/-C`.
On macOS (and soon Linux), all writable roots (including `cwd`) that contain a `.git/` folder _as an immediate child_ will configure the `.git/` folder to be read-only while the rest of the Git repository will be writable. This means that commands like `git commit` will fail, by default (as it entails writing to `.git/`), and will require Codex to ask for permission.
On macOS (and soon Linux), all writable roots (including `cwd`) that contain a `.git/` folder _as an immediate child_ will configure the `.git/` folder to be read-only while the rest of the Git repository will be writable. This means that commands like `git commit` will fail, by default (as it entails writing to `.git/`), and will require LLMX to ask for permission.
```toml
# same as `--sandbox workspace-write`
@@ -316,7 +316,7 @@ sandbox_mode = "workspace-write"
# Extra settings that only apply when `sandbox = "workspace-write"`.
[sandbox_workspace_write]
# By default, the cwd for the Codex session will be writable as well as $TMPDIR
# By default, the cwd for the LLMX session will be writable as well as $TMPDIR
# (if set) and /tmp (if it exists). Setting the respective options to `true`
# will override those defaults.
exclude_tmpdir_env_var = false
@@ -337,9 +337,9 @@ To disable sandboxing altogether, specify `danger-full-access` like so:
sandbox_mode = "danger-full-access"
```
This is reasonable to use if Codex is running in an environment that provides its own sandboxing (such as a Docker container) such that further sandboxing is unnecessary.
This is reasonable to use if LLMX is running in an environment that provides its own sandboxing (such as a Docker container) such that further sandboxing is unnecessary.
Though using this option may also be necessary if you try to use Codex in environments where its native sandboxing mechanisms are unsupported, such as older Linux kernels or on Windows.
Though using this option may also be necessary if you try to use LLMX in environments where its native sandboxing mechanisms are unsupported, such as older Linux kernels or on Windows.
### tools.\*
@@ -347,29 +347,29 @@ Use the optional `[tools]` table to toggle built-in tools that the agent may cal
```toml
[tools]
web_search = true # allow Codex to issue first-party web searches without prompting you (deprecated)
web_search = true # allow LLMX to issue first-party web searches without prompting you (deprecated)
view_image = false # disable image uploads (they're enabled by default)
```
`web_search` is deprecated; use the `web_search_request` feature flag instead.
The `view_image` toggle is useful when you want to include screenshots or diagrams from your repo without pasting them manually. Codex still respects sandboxing: it can only attach files inside the workspace roots you allow.
The `view_image` toggle is useful when you want to include screenshots or diagrams from your repo without pasting them manually. LLMX still respects sandboxing: it can only attach files inside the workspace roots you allow.
### approval_presets
Codex provides three main Approval Presets:
LLMX provides three main Approval Presets:
- Read Only: Codex can read files and answer questions; edits, running commands, and network access require approval.
- Auto: Codex can read files, make edits, and run commands in the workspace without approval; asks for approval outside the workspace or for network access.
- Read Only: LLMX can read files and answer questions; edits, running commands, and network access require approval.
- Auto: LLMX can read files, make edits, and run commands in the workspace without approval; asks for approval outside the workspace or for network access.
- Full Access: Full disk and network access without prompts; extremely risky.
You can further customize how Codex runs at the command line using the `--ask-for-approval` and `--sandbox` options.
You can further customize how LLMX runs at the command line using the `--ask-for-approval` and `--sandbox` options.
> See also [Sandbox & approvals](./sandbox.md) for in-depth examples and platform-specific behaviour.
### shell_environment_policy
Codex spawns subprocesses (e.g. when executing a `local_shell` tool-call suggested by the assistant). By default it now passes **your full environment** to those subprocesses. You can tune this behavior via the **`shell_environment_policy`** block in `config.toml`:
LLMX spawns subprocesses (e.g. when executing a `local_shell` tool-call suggested by the assistant). By default it now passes **your full environment** to those subprocesses. You can tune this behavior via the **`shell_environment_policy`** block in `config.toml`:
```toml
[shell_environment_policy]
@@ -388,7 +388,7 @@ include_only = ["PATH", "HOME"]
| Field | Type | Default | Description |
| ------------------------- | -------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| `inherit` | string | `all` | Starting template for the environment:<br>`all` (clone full parent env), `core` (`HOME`, `PATH`, `USER`, …), or `none` (start empty). |
| `ignore_default_excludes` | boolean | `false` | When `false`, Codex removes any var whose **name** contains `KEY`, `SECRET`, or `TOKEN` (case-insensitive) before other rules run. |
| `ignore_default_excludes` | boolean | `false` | When `false`, LLMX removes any var whose **name** contains `KEY`, `SECRET`, or `TOKEN` (case-insensitive) before other rules run. |
| `exclude` | array<string> | `[]` | Case-insensitive glob patterns to drop after the default filter.<br>Examples: `"AWS_*"`, `"AZURE_*"`. |
| `set` | table<string,string> | `{}` | Explicit key/value overrides or additions always win over inherited values. |
| `include_only` | array<string> | `[]` | If non-empty, a whitelist of patterns; only variables that match _one_ pattern survive the final step. (Generally used with `inherit = "all"`.) |
@@ -407,13 +407,13 @@ inherit = "none"
set = { PATH = "/usr/bin", MY_FLAG = "1" }
```
Currently, `CODEX_SANDBOX_NETWORK_DISABLED=1` is also added to the environment, assuming network is disabled. This is not configurable.
Currently, `LLMX_SANDBOX_NETWORK_DISABLED=1` is also added to the environment, assuming network is disabled. This is not configurable.
## MCP integration
### mcp_servers
You can configure Codex to use [MCP servers](https://modelcontextprotocol.io/about) to give Codex access to external applications, resources, or services.
You can configure LLMX to use [MCP servers](https://modelcontextprotocol.io/about) to give LLMX access to external applications, resources, or services.
#### Server configuration
@@ -430,7 +430,7 @@ command = "npx"
args = ["-y", "mcp-server"]
# Optional: propagate additional env vars to the MVP server.
# A default whitelist of env vars will be propagated to the MCP server.
# https://github.com/openai/codex/blob/main/codex-rs/rmcp-client/src/utils.rs#L82
# https://github.com/valknar/llmx/blob/main/llmx-rs/rmcp-client/src/utils.rs#L82
env = { "API_KEY" = "value" }
# or
[mcp_servers.server_name.env]
@@ -444,7 +444,7 @@ cwd = "/Users/<user>/code/my-server"
##### Streamable HTTP
[Streamable HTTP servers](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#streamable-http) enable Codex to talk to resources that are accessed via a http url (either on localhost or another domain).
[Streamable HTTP servers](https://modelcontextprotocol.io/specification/2025-06-18/basic/transports#streamable-http) enable LLMX to talk to resources that are accessed via a http url (either on localhost or another domain).
```toml
[mcp_servers.figma]
@@ -463,7 +463,7 @@ Streamable HTTP connections always use the experimental Rust MCP client under th
experimental_use_rmcp_client = true
```
After enabling it, run `codex mcp login <server-name>` when the server supports OAuth.
After enabling it, run `llmx mcp login <server-name>` when the server supports OAuth.
#### Other configuration options
@@ -480,7 +480,7 @@ enabled_tools = ["search", "summarize"]
disabled_tools = ["search"]
```
When both `enabled_tools` and `disabled_tools` are specified, Codex first restricts the server to the allow-list and then removes any tools that appear in the deny-list.
When both `enabled_tools` and `disabled_tools` are specified, LLMX first restricts the server to the allow-list and then removes any tools that appear in the deny-list.
#### Experimental RMCP client
@@ -497,32 +497,32 @@ experimental_use_rmcp_client = true
```shell
# List all available commands
codex mcp --help
llmx mcp --help
# Add a server (env can be repeated; `--` separates the launcher command)
codex mcp add docs -- docs-server --port 4000
llmx mcp add docs -- docs-server --port 4000
# List configured servers (pretty table or JSON)
codex mcp list
codex mcp list --json
llmx mcp list
llmx mcp list --json
# Show one server (table or JSON)
codex mcp get docs
codex mcp get docs --json
llmx mcp get docs
llmx mcp get docs --json
# Remove a server
codex mcp remove docs
llmx mcp remove docs
# Log in to a streamable HTTP server that supports oauth
codex mcp login SERVER_NAME
llmx mcp login SERVER_NAME
# Log out from a streamable HTTP server that supports oauth
codex mcp logout SERVER_NAME
llmx mcp logout SERVER_NAME
```
### Examples of useful MCPs
There is an ever growing list of useful MCP servers that can be helpful while you are working with Codex.
There is an ever growing list of useful MCP servers that can be helpful while you are working with LLMX.
Some of the most common MCPs we've seen are:
@@ -530,14 +530,14 @@ Some of the most common MCPs we've seen are:
- Figma [Local](https://developers.figma.com/docs/figma-mcp-server/local-server-installation/) and [Remote](https://developers.figma.com/docs/figma-mcp-server/remote-server-installation/) - access to your Figma designs
- [Playwright](https://www.npmjs.com/package/@playwright/mcp) - control and inspect a browser using Playwright
- [Chrome Developer Tools](https://github.com/ChromeDevTools/chrome-devtools-mcp/) — control and inspect a Chrome browser
- [Sentry](https://docs.sentry.io/product/sentry-mcp/#codex) — access to your Sentry logs
- [Sentry](https://docs.sentry.io/product/sentry-mcp/#llmx) — access to your Sentry logs
- [GitHub](https://github.com/github/github-mcp-server) — Control over your GitHub account beyond what git allows (like controlling PRs, issues, etc.)
## Observability and telemetry
### otel
Codex can emit [OpenTelemetry](https://opentelemetry.io/) **log events** that
LLMX 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
@@ -550,10 +550,10 @@ exporter = "none" # defaults to "none"; set to otlp-http or otlp-grpc t
log_user_prompt = false # defaults to false; redact prompt text unless explicitly enabled
```
Codex tags every exported event with `service.name = $ORIGINATOR` (the same
value sent in the `originator` header, `codex_cli_rs` by default), the CLI
LLMX tags every exported event with `service.name = $ORIGINATOR` (the same
value sent in the `originator` header, `llmx_cli_rs` by default), the CLI
version, and an `env` attribute so downstream collectors can distinguish
dev/staging/prod traffic. Only telemetry produced inside the `codex_otel`
dev/staging/prod traffic. Only telemetry produced inside the `llmx_otel`
crate—the events listed below—is forwarded to the exporter.
### Event catalog
@@ -562,10 +562,10 @@ Every event shares a common set of metadata fields: `event.timestamp`,
`conversation.id`, `app.version`, `auth_mode` (when available),
`user.account_id` (when available), `user.email` (when available), `terminal.type`, `model`, and `slug`.
With OTEL enabled Codex emits the following event types (in addition to the
With OTEL enabled LLMX emits the following event types (in addition to the
metadata above):
- `codex.conversation_starts`
- `llmx.conversation_starts`
- `provider_name`
- `reasoning_effort` (optional)
- `reasoning_summary`
@@ -576,12 +576,12 @@ metadata above):
- `sandbox_policy`
- `mcp_servers` (comma-separated list)
- `active_profile` (optional)
- `codex.api_request`
- `llmx.api_request`
- `attempt`
- `duration_ms`
- `http.response.status_code` (optional)
- `error.message` (failures)
- `codex.sse_event`
- `llmx.sse_event`
- `event.kind`
- `duration_ms`
- `error.message` (failures)
@@ -590,15 +590,15 @@ metadata above):
- `cached_token_count` (responses only, optional)
- `reasoning_token_count` (responses only, optional)
- `tool_token_count` (responses only)
- `codex.user_prompt`
- `llmx.user_prompt`
- `prompt_length`
- `prompt` (redacted unless `log_user_prompt = true`)
- `codex.tool_decision`
- `llmx.tool_decision`
- `tool_name`
- `call_id`
- `decision` (`approved`, `approved_for_session`, `denied`, or `abort`)
- `source` (`config` or `user`)
- `codex.tool_result`
- `llmx.tool_result`
- `tool_name`
- `call_id` (optional)
- `arguments` (optional)
@@ -641,14 +641,14 @@ If the exporter is `none` nothing is written anywhere; otherwise you must run or
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
If you build LLMX 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.
### notify
Specify a program that will be executed to get notified about events generated by Codex. Note that the program will receive the notification argument as a string of JSON, e.g.:
Specify a program that will be executed to get notified about events generated by LLMX. Note that the program will receive the notification argument as a string of JSON, e.g.:
```json
{
@@ -663,7 +663,7 @@ Specify a program that will be executed to get notified about events generated b
The `"type"` property will always be set. Currently, `"agent-turn-complete"` is the only notification type that is supported.
`"thread-id"` contains a string that identifies the Codex session that produced the notification; you can use it to correlate multiple turns that belong to the same task.
`"thread-id"` contains a string that identifies the LLMX session that produced the notification; you can use it to correlate multiple turns that belong to the same task.
`"cwd"` reports the absolute working directory for the session so scripts can disambiguate which project triggered the notification.
@@ -691,9 +691,9 @@ def main() -> int:
case "agent-turn-complete":
assistant_message = notification.get("last-assistant-message")
if assistant_message:
title = f"Codex: {assistant_message}"
title = f"LLMX: {assistant_message}"
else:
title = "Codex: Turn Complete!"
title = "LLMX: Turn Complete!"
input_messages = notification.get("input-messages", [])
message = " ".join(input_messages)
title += message
@@ -711,7 +711,7 @@ def main() -> int:
"-message",
message,
"-group",
"codex-" + thread_id,
"llmx-" + thread_id,
"-ignoreDnD",
"-activate",
"com.googlecode.iterm2",
@@ -725,18 +725,18 @@ if __name__ == "__main__":
sys.exit(main())
```
To have Codex use this script for notifications, you would configure it via `notify` in `~/.codex/config.toml` using the appropriate path to `notify.py` on your computer:
To have LLMX use this script for notifications, you would configure it via `notify` in `~/.llmx/config.toml` using the appropriate path to `notify.py` on your computer:
```toml
notify = ["python3", "/Users/mbolin/.codex/notify.py"]
notify = ["python3", "/Users/mbolin/.llmx/notify.py"]
```
> [!NOTE]
> Use `notify` for automation and integrations: Codex invokes your external program with a single JSON argument for each event, independent of the TUI. If you only want lightweight desktop notifications while using the TUI, prefer `tui.notifications`, which uses terminal escape codes and requires no external program. You can enable both; `tui.notifications` covers inTUI alerts (e.g., approval prompts), while `notify` is best for systemlevel hooks or custom notifiers. Currently, `notify` emits only `agent-turn-complete`, whereas `tui.notifications` supports `agent-turn-complete` and `approval-requested` with optional filtering.
> Use `notify` for automation and integrations: LLMX invokes your external program with a single JSON argument for each event, independent of the TUI. If you only want lightweight desktop notifications while using the TUI, prefer `tui.notifications`, which uses terminal escape codes and requires no external program. You can enable both; `tui.notifications` covers inTUI alerts (e.g., approval prompts), while `notify` is best for systemlevel hooks or custom notifiers. Currently, `notify` emits only `agent-turn-complete`, whereas `tui.notifications` supports `agent-turn-complete` and `approval-requested` with optional filtering.
### hide_agent_reasoning
Codex intermittently emits "reasoning" events that show the model's internal "thinking" before it produces a final answer. Some users may find these events distracting, especially in CI logs or minimal terminal output.
LLMX intermittently emits "reasoning" events that show the model's internal "thinking" before it produces a final answer. Some users may find these events distracting, especially in CI logs or minimal terminal output.
Setting `hide_agent_reasoning` to `true` suppresses these events in **both** the TUI as well as the headless `exec` sub-command:
@@ -804,11 +804,11 @@ Users can specify config values at multiple levels. Order of precedence is as fo
1. custom command-line argument, e.g., `--model o3`
2. as part of a profile, where the `--profile` is specified via a CLI (or in the config file itself)
3. as an entry in `config.toml`, e.g., `model = "o3"`
4. the default value that comes with Codex CLI (i.e., Codex CLI defaults to `gpt-5-codex`)
4. the default value that comes with LLMX CLI (i.e., LLMX CLI defaults to `gpt-5-llmx`)
### history
By default, Codex CLI records messages sent to the model in `$CODEX_HOME/history.jsonl`. Note that on UNIX, the file permissions are set to `o600`, so it should only be readable and writable by the owner.
By default, LLMX CLI records messages sent to the model in `$LLMX_HOME/history.jsonl`. Note that on UNIX, the file permissions are set to `o600`, so it should only be readable and writable by the owner.
To disable this behavior, configure `[history]` as follows:
@@ -831,7 +831,7 @@ Note this is **not** a general editor setting (like `$EDITOR`), as it only accep
- `"cursor"`
- `"none"` to explicitly disable this feature
Currently, `"vscode"` is the default, though Codex does not verify VS Code is installed. As such, `file_opener` may default to `"none"` or something else in the future.
Currently, `"vscode"` is the default, though LLMX does not verify VS Code is installed. As such, `file_opener` may default to `"none"` or something else in the future.
### project_doc_max_bytes
@@ -847,7 +847,7 @@ project_doc_fallback_filenames = ["CLAUDE.md", ".exampleagentrules.md"]
We recommend migrating instructions to AGENTS.md; other filenames may reduce model performance.
> See also [AGENTS.md discovery](./agents_md.md) for how Codex locates these files during a session.
> See also [AGENTS.md discovery](./agents_md.md) for how LLMX locates these files during a session.
### tui
@@ -865,7 +865,7 @@ notifications = [ "agent-turn-complete", "approval-requested" ]
```
> [!NOTE]
> Codex emits desktop notifications using terminal escape codes. Not all terminals support these (notably, macOS Terminal.app and VS Code's terminal do not support custom notifications. iTerm2, Ghostty and WezTerm do support these notifications).
> LLMX emits desktop notifications using terminal escape codes. Not all terminals support these (notably, macOS Terminal.app and VS Code's terminal do not support custom notifications. iTerm2, Ghostty and WezTerm do support these notifications).
> [!NOTE] > `tui.notifications` is builtin and limited to the TUI session. For programmatic or crossenvironment notifications—or to integrate with OSspecific notifiers—use the toplevel `notify` option to run an external program that receives event JSON. The two settings are independent and can be used together.
@@ -873,17 +873,17 @@ notifications = [ "agent-turn-complete", "approval-requested" ]
### Forcing a login method
To force users on a given machine to use a specific login method or workspace, use a combination of [managed configurations](https://developers.openai.com/codex/security#managed-configuration) as well as either or both of the following fields:
To force users on a given machine to use a specific login method or workspace, use a combination of [managed configurations](https://developers.openai.com/llmx/security#managed-configuration) as well as either or both of the following fields:
```toml
# Force the user to log in with ChatGPT or via an api key.
forced_login_method = "chatgpt" or "api"
# When logging in with ChatGPT, only the specified workspace ID will be presented during the login
# flow and the id will be validated during the oauth callback as well as every time Codex starts.
# flow and the id will be validated during the oauth callback as well as every time LLMX starts.
forced_chatgpt_workspace_id = "00000000-0000-0000-0000-000000000000"
```
If the active credentials don't match the config, the user will be logged out and Codex will exit.
If the active credentials don't match the config, the user will be logged out and LLMX will exit.
If `forced_chatgpt_workspace_id` is set but `forced_login_method` is not set, API key login will still work.
@@ -895,19 +895,19 @@ cli_auth_credentials_store = "keyring"
Valid values:
- `file` (default) Store credentials in `auth.json` under `$CODEX_HOME`.
- `file` (default) Store credentials in `auth.json` under `$LLMX_HOME`.
- `keyring` Store credentials in the operating system keyring via the [`keyring` crate](https://crates.io/crates/keyring); the CLI reports an error if secure storage is unavailable. Backends by OS:
- macOS: macOS Keychain
- Windows: Windows Credential Manager
- Linux: DBusbased Secret Service, the kernel keyutils, or a combination
- FreeBSD/OpenBSD: DBusbased Secret Service
- `auto` Save credentials to the operating system keyring when available; otherwise, fall back to `auth.json` under `$CODEX_HOME`.
- `auto` Save credentials to the operating system keyring when available; otherwise, fall back to `auth.json` under `$LLMX_HOME`.
## Config reference
| Key | Type / Values | Notes |
| ------------------------------------------------ | ----------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| `model` | string | Model to use (e.g., `gpt-5-codex`). |
| `model` | string | Model to use (e.g., `gpt-5-llmx`). |
| `model_provider` | string | Provider id from `model_providers` (default: `openai`). |
| `model_context_window` | number | Context window tokens. |
| `model_max_output_tokens` | number | Max output tokens. |
@@ -925,7 +925,7 @@ Valid values:
| `mcp_servers.<id>.env` | map<string,string> | MCP server env vars (stdio servers only). |
| `mcp_servers.<id>.url` | string | MCP server url (streamable http servers only). |
| `mcp_servers.<id>.bearer_token_env_var` | string | environment variable containing a bearer token to use for auth (streamable http servers only). |
| `mcp_servers.<id>.enabled` | boolean | When false, Codex skips starting the server (default: true). |
| `mcp_servers.<id>.enabled` | boolean | When false, LLMX skips starting the server (default: true). |
| `mcp_servers.<id>.startup_timeout_sec` | number | Startup timeout in seconds (default: 10). Timeout is applied both for initializing MCP server and initially listing tools. |
| `mcp_servers.<id>.tool_timeout_sec` | number | Per-tool timeout in seconds (default: 60). Accepts fractional values; omit to use the default. |
| `mcp_servers.<id>.enabled_tools` | array<string> | Restrict the server to the listed tool names. |
@@ -960,7 +960,7 @@ Valid values:
| `experimental_use_exec_command_tool` | boolean | Use experimental exec command tool. |
| `projects.<path>.trust_level` | string | Mark project/worktree as trusted (only `"trusted"` is recognized). |
| `tools.web_search` | boolean | Enable web search tool (deprecated) (default: false). |
| `tools.view_image` | boolean | Enable or disable the `view_image` tool so Codex can attach local image files from the workspace (default: true). |
| `forced_login_method` | `chatgpt` \| `api` | Only allow Codex to be used with ChatGPT or API keys. |
| `forced_chatgpt_workspace_id` | string (uuid) | Only allow Codex to be used with the specified ChatGPT workspace. |
| `tools.view_image` | boolean | Enable or disable the `view_image` tool so LLMX can attach local image files from the workspace (default: true). |
| `forced_login_method` | `chatgpt` \| `api` | Only allow LLMX to be used with ChatGPT or API keys. |
| `forced_chatgpt_workspace_id` | string (uuid) | Only allow LLMX to be used with the specified ChatGPT workspace. |
| `cli_auth_credentials_store` | `file` \| `keyring` \| `auto` | Where to store CLI login credentials (default: `file`). |