codex vs claude clis
Claude Code and Codex both turn a terminal into an agent loop. Both can read a repo, run commands, edit files, resume sessions, and connect to MCP servers. The split is not capability versus no capability. The split is where each CLI draws its boundary: prompt handling, tool disclosure, MCP ergonomics, and runtime control (src/crates/netsky-core/src/runtime/mod.rs:1-15, src/crates/netsky-ai/src/lib.rs:108-152).
flowchart LR
A[prompt + cwd] --> B{adapter}
B --> C[Claude CLI]
B --> D[Codex CLI]
C --> E[tool loop]
D --> E
E --> F[state or patch]
Netsky cares about that boundary because it runs both. The adapter takes one AiRequest, resolves the runtime from the model prefix, then builds a Claude or Codex command without changing the higher-level call site (src/crates/netsky-ai/src/lib.rs:21-34, src/crates/netsky-ai/src/lib.rs:98-152). The same pattern shows up in resident agents. Runtime::build_command and Runtime::post_spawn keep the lifecycle stable while each CLI keeps its own flags and startup semantics (src/crates/netsky-core/src/runtime/mod.rs:27-103).
same job, different invocation model #
At the flag layer, Claude exposes more first-class switches for prompt and tool shaping. Codex exposes fewer top-level knobs and leans harder on config plus subcommands. That is visible in the top-level help for both CLIs from April 20, 2026: claude --model --effort --tools --print --resume --mcp-config, versus codex -m --sandbox --ask-for-approval resume mcp exec (claude --help, codex --help, codex resume --help).
| concern | Claude Code | Codex |
|---|---|---|
| model | --model | -m, --model |
| reasoning | --effort | model-specific. no top-level --effort flag in codex --help |
| non-interactive run | -p, --print | codex exec |
| resume | -r, --resume or -c, --continue | codex resume |
| built-in tool exposure | top-level flags: --tools, --allowed-tools, --disallowed-tools | config-driven: ~/.codex/config.toml, profiles, and -c key=value overrides in codex --help |
| MCP config | --mcp-config, --strict-mcp-config, claude mcp ... | codex mcp ..., config in ~/.codex/config.toml |
| sandbox | --permission-mode and skip-permissions flags | -s, --sandbox, -a, --ask-for-approval |
| inline prompt | positional prompt | positional prompt |
| file-backed prompt injection | --system-prompt, --append-system-prompt | no top-level equivalent in codex --help |
Claude is easier to steer from one shell command. Codex leans harder on config.toml and subcommands like exec, resume, review, mcp, and sandbox (/Users/cody/netsky/gh-org/openai/codex/codex-rs/README.md:25-54, /Users/cody/netsky/gh-org/openai/codex/codex-rs/README.md:56-91).
# Claude: one-shot non-interactive call claude -p --model sonnet --effort high --tools Bash,Edit,Read "summarize this diff" # Codex: one-shot non-interactive call codex exec -m gpt-5.4 -s workspace-write -a never "summarize this diff" # Claude: resume a thread claude --resume # Codex: resume a thread codex resume --last
mcp is where the ergonomics diverge most #
Claude has the richer MCP client surface today. The top-level help exposes --mcp-config and --strict-mcp-config, and claude mcp ships with add, add-json, add-from-claude-desktop, get, list, remove, reset-project-choices, and serve (claude --help, claude mcp --help). That is a full operator surface from the CLI itself.
Codex supports MCP on both sides too, but the public surface is narrower. The maintained Rust CLI documents Codex as an MCP client and an experimental MCP server, and points configuration back to ~/.codex/config.toml plus codex mcp for list, get, add, remove, login, and logout (/Users/cody/netsky/gh-org/openai/codex/codex-rs/README.md:29-45, /Users/cody/netsky/gh-org/openai/codex/docs/config.md:9-37, codex mcp --help).
Netsky adapts around that mismatch instead of pretending it does not exist. Spawn writes a per-agent MCP JSON file, passes that file into Claude, and lets Codex ignore the path because Codex reads MCP launchers from its own config home (src/crates/netsky-core/src/spawn.rs:101-113, src/crates/netsky-core/src/runtime/codex.rs:73-87). The effect is runtime-neutral at the call site and runtime-specific at the edge.
| MCP concern | Claude Code | Codex | netsky adapter |
|---|---|---|---|
| project file injection | --mcp-config | not via top-level spawn flags | write config once, pass only where needed |
| strict mode | --strict-mcp-config | per-server config knobs | use Claude strict mode for clones |
| server management | rich claude mcp verbs | smaller codex mcp verb set | keep mutation policy in repo code |
| MCP server mode | claude mcp serve | codex mcp-server | treat both as pluggable edges |
the tool story is overlap first, then divergence #
Both CLIs can read files, edit files, run commands, and search the web when enabled. Netsky’s Claude clone profile makes that explicit with Bash,Edit,Glob,Grep,Read,WebFetch,WebSearch,Write (src/crates/netsky-core/src/consts.rs:159-176). Codex’s event model makes the same floor visible from the other side: command execution, file changes, MCP tool calls, web search, and todo lists are first-class event types in codex exec output (/Users/cody/netsky/gh-org/openai/codex/codex-rs/exec/src/exec_events.rs:8-37, /Users/cody/netsky/gh-org/openai/codex/codex-rs/exec/src/exec_events.rs:91-128).
The divergence is disclosure and governance, not whether tool policy is programmable.
- Claude exposes built-in tool selection directly with
--tools,--allowed-tools, and--disallowed-toolsin the main CLI (claude --help). - Codex exposes tool policy through config. The config model includes
include_apply_patch_tool,tools.view_image, and[tools.web_search], and profile-scoped overrides can replace those defaults per profile (/Users/cody/netsky/gh-org/openai/codex/codex-rs/core/src/config/mod.rs:535,/Users/cody/netsky/gh-org/openai/codex/codex-rs/config/src/config_toml.rs:494-504,/Users/cody/netsky/gh-org/openai/codex/codex-rs/core/tests/suite/web_search.rs:240-249,/Users/cody/netsky/gh-org/openai/codex/codex-rs/core/src/config/managed_features.rs:237-242,/Users/cody/netsky/gh-org/openai/codex/codex-rs/config/src/profile_toml.rs:52-59). - Codex also makes those settings programmable at launch with
-c key=value, which overrides~/.codex/config.tomlon one invocation (codex --help,codex exec --help). - Codex’s MCP layer extends the same pattern.
~/.codex/config.tomlcan store per-tool approval overrides and per-serversupports_parallel_tool_callsflags (/Users/cody/netsky/gh-org/openai/codex/docs/config.md:15-37).
That maps to real defaults. Claude’s permission mode is a session option. Codex puts autonomy front and center in the top-level UX: read-only, workspace-write, danger-full-access, plus untrusted, on-request, and never approval modes (codex --help, codex resume --help, /Users/cody/netsky/gh-org/openai/codex/codex-rs/README.md:75-91).
prompt handling is the deepest design split #
Claude has a distinct system-prompt layer. The CLI exposes --system-prompt, --append-system-prompt, and file variants in bare mode docs. Anthropic also exposes an explicit prompt-cache reuse knob with --exclude-dynamic-system-prompt-sections, which the help text says improves cross-user prompt-cache reuse by moving machine-specific sections out of the system prompt (claude --help, https://platform.claude.com/docs/en/build-with-claude/prompt-caching).
Codex does not expose an equivalent top-level append-system-prompt flag in codex --help. Its documented guidance points developers toward AGENTS.md, config.toml, and the initial prompt. The maintained CLI docs also say codex exec accepts a positional prompt or stdin, and if both are present stdin is appended as a <stdin> block (/Users/cody/netsky/gh-org/openai/codex/codex-rs/README.md:51-54, /Users/cody/netsky/gh-org/openai/codex/docs/agents_md.md:1-7, /Users/cody/netsky/gh-org/openai/codex/codex-rs/exec/src/lib.rs:161-170).
Netsky’s runtime adapter has to respect that difference:
- Claude path: write composed skills to a tempfile, then pass
--append-system-prompt-file(src/crates/netsky-ai/src/lib.rs:114-131). - Codex path: prepend the composed skill text into the user prompt body because there is no matching append-system-prompt file flag in the CLI path netsky targets (
src/crates/netsky-ai/src/lib.rs:132-144). - Resident Claude agents take startup as a second positional arg (
src/crates/netsky-core/src/runtime/claude.rs:49-55,src/crates/netsky-core/src/runtime/claude.rs:119-129). - Resident Codex agents use the positional slot for the rendered base prompt, then paste startup into the tmux pane as a follow-on turn (
src/crates/netsky-core/src/runtime/codex.rs:3-19,src/crates/netsky-core/src/runtime/codex.rs:83-87,src/crates/netsky-core/src/runtime/codex.rs:186-238).
Prompt caching is first-class on both CLIs in practice. Claude documents prompt caching directly as a user-facing feature. Codex surfaces cached_input_tokens in turn usage events, so cached accounting is part of the runtime contract even though the top-level CLI help does not expose a comparable cache-control flag (/Users/cody/netsky/gh-org/openai/codex/codex-rs/exec/src/exec_events.rs:59-68, claude --help, codex --help).
runtime characteristics #
Both CLIs stream. They just do it through different interfaces.
- Claude uses
--printplus--output-format text|json|stream-jsonand can include partial messages and hook events in the stream (claude --help). - Codex uses an interactive TUI by default and
codex exec --jsonfor JSONL event streaming in non-interactive mode (codex exec --help,/Users/cody/netsky/gh-org/openai/codex/codex-rs/exec/src/exec_events.rs:8-37). - Claude auth exposes OAuth-like interactive login plus API-key-oriented bare mode details in the main help (
claude --help). - Codex splits auth into a dedicated
loginflow and separate authentication docs, with source references that show both API-key and ChatGPT-auth paths inside the maintained codebase (codex --help,/Users/cody/netsky/gh-org/openai/codex/docs/authentication.md:1-3,/Users/cody/netsky/gh-org/openai/codex/codex-rs/app-server/src/codex_message_processor.rs:268-273,/Users/cody/netsky/gh-org/openai/codex/codex-rs/app-server/src/codex_message_processor.rs:1179-1189). - Codex makes sandboxing a first-class concept. The maintained README documents platform sandbox helpers and
--sandboxpolicies directly (/Users/cody/netsky/gh-org/openai/codex/codex-rs/README.md:56-91). - Claude exposes permission mode and skip-permissions flags, but not the same “sandbox as the headline abstraction” posture in the top-level CLI (
claude --help).
netsky’s adapter pattern #
The useful abstraction is not “make the CLIs look the same”. It is “hold one internal contract and translate at the edge”.
sequenceDiagram
participant N as netsky
participant A as adapter
participant C as Claude or Codex
N->>A: AiRequest
A->>A: resolve runtime from model
A->>C: build runtime-specific argv
C-->>A: JSON or event stream
A-->>N: normalized text + metadata
netsky_ai::build_worker_command is the narrow sidecar version of that pattern. netsky_core::runtime::Runtime is the resident-agent version. Both preserve one internal request shape while admitting that Claude and Codex differ on system prompts, startup delivery, MCP loading, and runtime policy (src/crates/netsky-ai/src/lib.rs:108-152, src/crates/netsky-core/src/runtime/mod.rs:52-103).
when to pick which #
- Pick Claude Code when the shell invocation itself needs to declare tool policy, MCP files, resume behavior, and prompt layering in one place.
- Pick Codex when sandbox mode and approval policy are the primary control plane, especially for interactive repo work or
codex execautomation. - Pick Claude when MCP-heavy workflows need richer CLI-side management.
- Pick Codex when a persistent
config.toml,AGENTS.md, and subcommand-oriented UX fit the way the team already works. - Pick either when the real requirement is read, edit, run, resume, and stream. The common floor is already there.
This is not a benchmark. It maps the CLI shape. If the question is “which one fits this repo’s control model”, the answer is usually visible before the first token is spent.