Most of this repository code is implemented and reviewed by
codexagents.
An Agent Client Protocol (ACP)–compatible agent that bridges the OpenAI Codex runtime with ACP clients over stdio. This project is under active development — features are evolving and breaking changes are likely.
The agent is structured around several key modules:
agent/core.rs— Core ACP request handlers (initialize,authenticate,new_session,load_session,prompt, etc.) andCodexAgentimplementationagent/session_manager.rs— Unified session management including:- Session state storage and mutation
- Session mode/model queries (
current_mode(),is_read_only(),resolve_acp_session_id()) - Conversation loading and caching
- Client update notifications
- Context override operations
agent/commands.rs— Slash command handlers (/init,/status,/compact,/review)agent/events.rs— Codex Event → ACP update conversion; reasoning aggregationagent/config_builder.rs— Session/conversation config construction (cwd, MCP servers, etc.)fs/— Filesystem bridge andacp_fsMCP server implementation
Key design principles:
SessionManagercentralizes all session operations — both mutations and queriesSessionStateis a pure data structure representing per-session state- The agent runs on Tokio's current-thread runtime with
LocalSetfor single-threaded async
- Agent Client Protocol (ACP) over stdio using
agent-client-protocol. - Integrates with the Codex Rust workspace for conversation management and event streaming.
- Slash commands with ACP AvailableCommands updates (advertised to clients on session start).
- Status output tailored for IDEs (workspace, account, model, token usage).
- Supports ACP session modes:
read-only,auto(default), andfull-access. - Automatically launches an internal MCP filesystem server (
acp_fs) built withrmcp, so Codex reads/writes files through ACP tooling instead of shell commands.
-
ACP Agent implementation
- Handles
initialize,authenticate,session/new,session/load,session/prompt,session/cancel,session/setMode,session/setModel. - Authentication support for OpenAI (ChatGPT/API key) and custom model providers.
- Streams Codex events (assistant messages, reasoning, token counts, tool calls) as
session/updatenotifications. - Event aggregation: reasoning deltas are accumulated and sent as complete blocks.
- Handles
-
Slash commands (advertised via
AvailableCommandsUpdate)/init— Create anAGENTS.mdwith repository contributor guidance. Uses a bundled prompt (src/agent/prompt_init_command.md)./status— Rich status output (workspace, account, model, token usage)./compact— Request Codex to compact/summarize the conversation to reduce context size./review— Ask Codex to review current changes, highlight issues, and suggest fixes.- Commands are dynamically advertised to clients on session start.
-
Session modes
- Three preset modes:
read-only,auto(default), andfull-access. - Modes control approval policy and sandbox restrictions.
- Clients switch modes via
session/setMode; agent emitsCurrentModeUpdate. SessionManagerprovidesis_read_only()to check mode restrictions.
- Three preset modes:
-
Custom model provider support
- Dynamic model listing and switching for custom (non-OpenAI) providers.
- Model format:
{provider_id}@{model_name}(e.g.,OpenRouter@anthropic/claude-3-opus). - Configure providers and models via Codex config profiles.
- Dedicated
custom_providerauthentication method for non-builtin providers. - Model switching enforces custom→custom provider transitions only.
-
Session management
SessionManagerprovides unified interface for all session operations:- State queries:
current_mode(),is_read_only(),resolve_acp_session_id() - Conversation management: lazy loading with caching
- Client notifications:
send_session_update(),send_message_chunk(),send_thought_chunk() - Context overrides:
apply_context_override()for approval/sandbox/model changes
- State queries:
- Access via
agent.session_manager()for read-only operations or internal mutation.
- Rust (Rust 2024 edition; rustc 1.90+ as pinned in
rust-toolchain.toml). - Network access for building Git dependencies (Codex workspace, ACP crate).
make buildTip: use
make release(orcargo build --release) when shipping the binary to an IDE like Zed. The release build lives attarget/release/codex-acp.
Configuration in Zed
Add this configuration to zed settings.
"agent_servers": {
"Codex": {
"command": "/path/to/codex-acp",
"args": [],
"env": {
"RUST_LOG": "info"
}
}
}When a session starts, codex-acp spins up an in-process TCP bridge and registers an MCP server named acp_fs using rmcp. Codex then calls structured tools:
read_text_file— reads workspace files via ACPclient.read_text_file, falling back to local disk if the client lacks FS support.write_text_file— writes workspace files via ACPclient.write_text_file, with a local fallback.edit_text_file— apply a focused replace in a file and persist.multi_edit_text_file— apply multiple sequential replacements and persist.
codex-acp also injects a default instruction reminding the model to use these tools rather than shelling out with cat/tee. If your client exposes filesystem capabilities, file access stays within ACP.
Dynamic tool availability:
- Tools are enabled/disabled based on client filesystem capabilities.
- Read-only sessions disable write tools (
write_text_file,edit_text_file,multi_edit_text_file). - If the client lacks FS support, tools fall back to local disk I/O.
- The FS bridge uses a dedicated bridge address and session ID for MCP server communication.
The /status command prints a human-friendly summary, e.g.:
📂 Workspace
• Path: ~/path/to/workspace
• Approval Mode: on-request
• Sandbox: workspace-write
👤 Account
• Signed in with ChatGPT (or API key / Not signed in)
• Login: [email protected]
• Plan: Plus
🧠 Model
• Name: gpt-5
• Provider: OpenAI
• Reasoning Effort: Medium
• Reasoning Summaries: Auto
📊 Token Usage
• Session ID: <uuid>
• Input: 0
• Output: 0
• Total: 0
Notes
- Some fields may be unknown depending on your auth mode and environment.
- Token counts are aggregated from Codex
EventMsg::TokenCountwhen available.
codex-acp supports multiple authentication methods:
- ChatGPT: Sign in with your ChatGPT account via
codex login - API Key: Use
OPENAI_API_KEYfrom environment orauth.json
For custom model providers (e.g., Anthropic, custom LLMs):
-
Configure the provider in your Codex config:
model_provider_id = "anthropic" model = "claude-3-opus" [model_providers.anthropic] name = "Anthropic" # ... provider-specific configuration [profiles.custom-fast] model = "claude-3-haiku" model_provider = "anthropic"
-
The agent will advertise a
custom_providerauthentication method during initialization. -
Authenticate with provider-specific credentials configured in your Codex setup.
- OpenAI: Standard authentication, no model switching (uses config defaults)
- Custom Providers:
- Model listing via
available_modelsin session responses - Model switching via
session/setModelwith{provider}@{model}format - Multiple model profiles for easy switching
- Model listing via
Example model switching (custom providers only):
{
"method": "session/setModel",
"params": {
"session_id": "...",
"model_id": "anthropic@claude-3-haiku"
}
}codex-acp uses tracing + tracing-subscriber and can log to stderr and/or a file. Configure it via environment variables:
Environment variables (highest precedence first):
CODEX_LOG_FILE— Path to append logs (non-rotating). Parent directories are created automatically. ANSI is disabled for file logs.CODEX_LOG_DIR— Directory for daily-rotated logs (file name:acp.log). Directory is created automatically. ANSI is disabled for file logs.CODEX_LOG_STDERR— Set to0,false,off, ornoto disable stderr logging. Enabled by default.RUST_LOG— Standard filtering directives (defaults toinfoif unset/invalid). Examples:info,debug,codex_acp=trace,rmcp=info.
Behavior:
- If
CODEX_LOG_FILEis set, logs go to stderr (unless disabled) and the specified file. - Else if
CODEX_LOG_DIRis set, logs go to stderr (unless disabled) and a daily-rotated file in that directory. - Else logs go to stderr only (unless disabled).
Examples:
# Console only
RUST_LOG=info cargo run --quiet
# Console + append to file (non-rotating)
RUST_LOG=debug CODEX_LOG_FILE=./logs/codex-acp.log cargo run --quiet
# Console + daily rotation under logs directory
RUST_LOG=info CODEX_LOG_DIR=./logs cargo run --quiet
# File only (disable stderr)
CODEX_LOG_STDERR=0 CODEX_LOG_FILE=./logs/codex-acp.log cargo run --quiet
# MCP filesystem server also honors logging env:
RUST_LOG=debug CODEX_LOG_DIR=./logs cargo run --quiet -- --acp-fs-mcp- Zed ACP example (Claude): https://github.com/zed-industries/claude-code-acp
- Agent Client Protocol (Rust): https://crates.io/crates/agent-client-protocol
- OpenAI Codex (Rust workspace): https://github.com/openai/codex
- rmcp (Rust MCP): https://github.com/domdomegg/rmcp