Claude Code vs Codex CLI vs Gemini CLI: An Honest Comparison
On paper, Claude Code, Codex CLI, and Gemini CLI are the same product. You run one binary inside a repository, describe a task in plain language, and the agent reads files, edits them, runs commands, and loops until it decides it is done. All three load a project instruction file at startup. All three speak MCP. All three have a non-interactive mode built for CI. If your criterion is "which one can edit files and run tests," there is no difference.
The differences are in philosophy, and in where each team spent its engineering budget: how the agent asks permission, what it remembers between sessions, how far you can extend it without forking it, and how much of it you can actually read. This comparison sticks to documented, observable behavior — flags, files, and commands — and skips benchmark scores, which age badly.
## Getting each one running
All three install a single binary and launch by running that binary inside a project directory. Claude Code prefers its own installer, which auto-updates in the background; the npm and Homebrew packages ship the same binary but leave updating to you. Codex and Gemini CLI are npm-first, with Homebrew as a second path.
### Claude Code
# native installer (recommended, self-updating)
curl -fsSL https://claude.ai/install.sh | bash
# or via a package manager
npm install -g @anthropic-ai/claude-code
brew install --cask claude-code
cd your-project
claude
claude "what does this project do?"### Codex CLI
npm install -g @openai/codex
# or
brew install --cask codex
codex login # browser sign-in with a ChatGPT account
codex login --device-auth # for SSH boxes and containers
cd your-project
codex
codex "explain this codebase"### Gemini CLI
npm install -g @google/gemini-cli
# or
brew install gemini-cli
npx @google/gemini-cli # run once, no global install
cd your-project
gemini
gemini -m proAccess is the first real fork. Claude Code needs a paid Claude plan or a Console account billed per token, and can alternatively be pointed at a third-party provider with your own credentials. Codex needs a paid OpenAI account — either ChatGPT sign-in on a paid plan, where usage counts against plan limits, or an API key billed per use. Gemini CLI is the only one of the three with a real free tier: sign in with a personal Google account and you get a usable daily quota at no cost, with a Gemini API key or Vertex AI available when you outgrow it.
// note: Environment variables can silently move you onto a different bill. If ANTHROPIC_API_KEY is set, Claude Code offers to use that key instead of your subscription login. If GEMINI_API_KEY is exported, it takes precedence over a cached Google login and switches you from the free tier onto API billing. Unset them when you want subscription or free-tier quota.
## Permissions, sandboxing, and how much rope you get
This is where the three tools stop resembling each other. Claude Code expresses safety as a permission layer: a mode sets the baseline, and allow/deny rules layer exceptions on top. The modes are default (read-only until you approve), acceptEdits (writes files and common filesystem commands), plan (read-only, drafts a plan first), dontAsk (only pre-approved tools), and bypassPermissions (everything, containers only). Shift+Tab cycles them live. Rules use a pattern syntax — Bash(git diff *) pre-approves a command family — and they merge across every settings scope, with deny always beating allow. That merge is powerful and occasionally maddening: a deny rule you did not write can block a command you explicitly allowed.
Codex splits the same problem into two independent dials, which is the cleanest model of the three. The sandbox decides what commands can technically touch — read-only, workspace-write, or danger-full-access — and the approval policy decides when Codex stops to ask you: untrusted, on-request, or never. Because they are orthogonal, "never ask me" inside a read-only sandbox is still perfectly safe, which is a genuinely useful combination the other two express less directly. --full-auto is shorthand for workspace-write plus on-request; --yolo removes both fences at once.
Gemini CLI sits in between, with an approval mode (default, auto_edit, plan, plus YOLO on Ctrl+Y) and a separate, optional OS sandbox behind -s. The sandbox uses macOS Seatbelt natively and Docker or Podman elsewhere, selected via GEMINI_SANDBOX. The container backends need a daemon and an image before the session will start; the macOS path has no such dependency.
# Claude Code — modes plus rule-based pre-approval
claude --permission-mode plan
claude --allowedTools "Read" "Edit" "Bash(git diff *)"
# Codex — sandbox and approvals as separate dials
codex --sandbox read-only --ask-for-approval untrusted "audit this repo"
codex --full-auto "run the tests and fix whatever breaks"
# Gemini CLI — approval mode plus an OS sandbox
gemini -s --approval-mode auto_edit -p "fix the failing test"// note: Every one of these tools has a way to quietly do nothing in automation. A Gemini -p run that wants to edit files waits forever for an approval no TUI is there to give. codex exec defaults to the read-only sandbox, so "fix the tests" runs, reports success, and changes nothing until you add --sandbox workspace-write. A Claude Code headless run stalls on the first tool it was not pre-approved for. Set the permission posture explicitly before you schedule anything.
## What each one remembers about your project
All three read a Markdown instruction file at session start, and all three scaffold one with /init. The file names differ — CLAUDE.md, AGENTS.md, GEMINI.md — but the mechanism is nearly identical, and so are the precedence rules:
- Claude Code layers
CLAUDE.mdacross four scopes — managed policy, user (~/.claude/CLAUDE.md), project (committed), and local (gitignored) — concatenating them with the most specific read last. It also supports@imports to pull in other files. - Codex reads
AGENTS.mdfrom the repo root, from nested folders, and from~/.codex/AGENTS.mdfor personal defaults. The file nearest the code being edited wins, and oversized files are truncated at a configurable byte cap. - Gemini CLI merges
GEMINI.mdfrom the global file upward through the workspace, then down into subdirectories, with deeper files overriding shallower ones./memory showprints the exact merged result, which is the single most useful debugging command in this category.
Two things break the symmetry. First, Claude Code adds auto memory: a per-repository store the agent writes itself as it learns build commands and debugging facts, loaded into every session without you maintaining it. It is machine-local, so it does not travel to teammates or CI, but it removes a real chore. Second, Gemini CLI lets you rename its context file through settings, and it accepts a list — including AGENTS.md. That is the clearest signal yet that the instruction-file format is converging on a shared standard.
One shared caveat: these files are context, not enforcement. All three read them; none guarantee compliance with vague or contradictory rules. Keep them short and specific.
## Extending the agent
Claude Code has the deepest extension surface, and it is almost entirely file-based. Custom slash commands are Markdown files in .claude/commands/, with skills at .claude/skills/<name>/SKILL.md doing the same job. Subagents are Markdown files in .claude/agents/ that run a side task in their own context window with their own tool access and return a summary — the mechanism behind delegating a code review or a wide search without flooding your main thread. Hooks are shell commands wired to lifecycle events in settings.json, and unlike instruction files they execute deterministically: a PostToolUse hook that formats after every write always runs, and exit code 2 blocks the action outright.
.claude/commands/deploy.md # becomes /deploy
.claude/skills/deploy/SKILL.md # same command, skill form
.claude/agents/code-reviewer.md # subagent with its own context
.claude/settings.json # hooks, permissions, envCodex is deliberately narrower and more declarative. Nearly everything lives in ~/.codex/config.toml: model, reasoning effort, sandbox, approvals, MCP servers, theme. Profiles are its best idea — a [profiles.ci] table bundles a set of overrides you activate with --profile ci, so a locked-down CI posture and a permissive local one coexist in one file. Codex also runs in the other direction: codex mcp-server exposes Codex itself as an MCP server so an IDE or another agent can call it as a tool.
Gemini CLI's answer is extensions: installable bundles that package MCP servers, custom commands, context files, and tool restrictions into one unit, installed from a GitHub URL or a local path and managed per scope. It is the most distribution-oriented model of the three, with the corresponding trust cost: an extension can register servers that run arbitrary code.
MCP support is universal and the ergonomics are close to identical, though Gemini CLI is alone in offering per-server tool filtering (includeTools / excludeTools) and a trust flag that skips confirmation entirely. Claude Code is alone in scoping servers three ways — local, project, and user — so a committed .mcp.json can share servers with the team.
claude mcp add --transport http --scope project paypal https://mcp.paypal.com/mcp
codex mcp add context7 -- npx -y @upstash/context7-mcp
gemini mcp add github npx -y @modelcontextprotocol/server-github## Headless mode and automation
All three run non-interactively and all three emit structured output, but they optimize for different failure modes. Claude Code's -p is the most defensive: --output-format json returns the result alongside cost and session metadata, --json-schema forces the answer into a schema you supply, and --max-turns plus --max-budget-usd put hard ceilings on an unattended run. --bare is the underrated one — it skips auto-discovery of hooks, skills, MCP servers, and instruction files, so a CI run behaves the same on every machine.
Codex's codex exec is the most CI-native. It authenticates from a piped API key, --skip-git-repo-check lets it run outside a repo, --json streams JSON Lines events you can follow as work happens, --output-schema constrains the final answer, and codex exec resume --last chains runs across steps. There is also an official GitHub Action for credential handling. Gemini CLI is the simplest: --output-format json gives one object with a response string and a stats block — the easiest shape to consume with jq — and -i seeds an interactive session instead of exiting.
# Claude Code — reproducible, capped, parseable
claude --bare -p "summarize the auth module" \
--allowedTools "Read" --output-format json --max-turns 5 | jq -r '.result'
# Codex — CI-shaped
codex exec --skip-git-repo-check --sandbox workspace-write "apply the codemod"
codex exec --json "list the top 5 risky files" | jq
# Gemini CLI — simplest output contract
gemini -p "list the exported functions" --output-format json | jq -r '.response'On parallelism, Claude Code is in a category of its own. claude -w <name> starts a session in a managed git worktree branched from origin/HEAD, so several agents edit different branches without fighting over one checkout, and claude --bg detaches a session entirely, with claude agents and claude attach to monitor and rejoin. Codex answers the same need from the other side, shipping tasks to hosted cloud environments and pulling the finished diff back with codex apply. Gemini CLI's multi-repo story is --include-directories, which widens one session's workspace instead of running several.
claude -w feature-auth # session in its own git worktree
claude --bg "investigate the flaky test" # detached background agent
claude agents # monitor them
codex cloud # submit and track hosted tasks
codex apply 01jtask456cloud # pull the diff into your checkout## Openness
Codex CLI and Gemini CLI both develop in public GitHub repositories: you can read the source, file issues against actual code, and see behavior changes before they reach the docs. Gemini CLI goes furthest, publishing preview and nightly channels you can install directly and hosting its documentation in the same repo. Claude Code is documentation-first — the reference surface is the docs site, and extensibility happens through documented file formats rather than by patching the client. If "I can inspect and fork this" is a hard requirement, that narrows the field to two.
## Honest verdicts
- Deep multi-file refactors, long autonomous runs, and orchestrating several agents at once: Claude Code. Worktree sessions, background agents, subagents with isolated context, hooks that enforce rather than suggest, and hard turn and budget caps make it the most complete harness for work that runs unsupervised for a while.
- Open source, free-tier tinkering, and learning agentic coding without a bill: Gemini CLI. It is the only one you can use seriously at no cost, the source and docs are public, extensions make sharing setups easy, and the sandbox is one flag away.
- Sandbox-first work and anyone already living in the OpenAI ecosystem: Codex CLI. The orthogonal sandbox and approval dials give the most precise control over what an agent may touch, profiles switch whole postures cleanly, and
codex execslots into CI with the least ceremony. - Teams standardizing across tools: write a good
AGENTS.md. Codex reads it natively, Gemini CLI can be configured to, and the conventions translate toCLAUDE.mdwith minimal editing. - Locked-down environments: check the auth paths first. Claude Code can route through third-party providers, Gemini CLI through Vertex AI with service-account credentials, Codex through an API key.
## The gap is closing
Every distinction above is smaller than it was a release or two ago. Slash commands, MCP, plan modes, checkpoint-and-undo, JSON output, structured schemas, sandboxing — features appear in one CLI and turn up in the others within months, and the instruction-file formats are actively converging. Treat this as a snapshot, not a ranking. The practical advice is boring and correct: pick the one whose ecosystem you already pay for, keep your project instructions in a format the others can read, and re-check every few months. Switching cost is a few config files, which is how it should be.