Overview
I split my work between Claude Code and Codex so that hitting one subscription’s usage limit never stops me mid-task. That only pays off if switching is cheap, which is what this page covers: one copy of the workflows both can read, separate configuration where the products genuinely differ, and a way to catch the two drifting apart.
This document is the Codex half. The Claude Code half covers that side’s rules, agents, permission gates, and hooks, and has its own write-up. Each stands alone; read both if you want the parallel setup.
Both run inside a Windows 11 Pro virtual machine in Hyper-V on my desktop, which holds VS Code with the Claude Code and Codex extensions plus both command-line tools. There is no Codex desktop app in it, so my Codex configuration has no desktop-app settings.
Architecture
%USERPROFILE%\.claude
├── CLAUDE.md
├── agents\
├── settings.json
├── skills\ Canonical shared skills
├── config-parity\ Parity manifest
└── private Git repo: claude-config
%USERPROFILE%\.codex
├── AGENTS.md
├── config.toml
├── agents\
├── rules\
└── private Git repo: codex-config
%USERPROFILE%\.agents\skills
├── myapps-build-ship -> %USERPROFILE%\.claude\skills\myapps-build-ship
├── myapps-fleet-rollout -> %USERPROFILE%\.claude\skills\myapps-fleet-rollout
├── myapps-new-project -> %USERPROFILE%\.claude\skills\myapps-new-project
├── myapps-repo-setup -> %USERPROFILE%\.claude\skills\myapps-repo-setup
├── myapps-server -> %USERPROFILE%\.claude\skills\myapps-server
├── myapps-test-session -> %USERPROFILE%\.claude\skills\myapps-test-session
├── myapps-theme-ui -> %USERPROFILE%\.claude\skills\myapps-theme-ui
└── agent-config-parity -> %USERPROFILE%\.claude\skills\agent-config-parity
myapps- is a stand-in for whatever shared prefix you pick. A common prefix
keeps a family of skills sorted together; substitute your own throughout the
examples below.
The design choices that matter:
.claudeand.codexare separate private repositories..agentsis only a symlink layer and is not its own repository.- Shared skills have one canonical copy under
.claude\skills. - Claude-specific instructions, hooks, and settings remain under
.claude. - Codex-specific instructions, sandbox settings, custom agents, and rules
remain under
.codex. - A parity audit tracks translated behavior and intentional provider differences.
VS Code Extensions
Installed
- Claude Code
- Codex - OpenAI’s coding agent
- Extension ID:
OpenAI.chatgpt
- Extension ID:
- Codex Extras
- Extension ID:
netroforge.codex-extras
- Extension ID:
Install from the command line:
code --install-extension OpenAI.chatgpt
code --install-extension netroforge.codex-extras
The Codex command-line tool is installed separately, so Claude Code can hand it jobs (see delegating to Codex).
Why Codex Extras
The official Codex extension works, but I wanted a more normal editor-tab workflow. Codex Extras adds:
- a Codex Chats panel in the Activity Bar
- current-workspace chats grouped separately from other workspaces
- pinned Codex editor tabs when opening existing chats
- a visible New Codex Agent toolbar button
- automatic refresh when chats are created or renamed
It reads the local Codex session index and does not parse or copy transcript contents. The extension is unofficial and independent from OpenAI.
Codex Global Configuration
The Codex home directory is:
%USERPROFILE%\.codex
My tracked configuration currently includes:
.codex\
├── .gitignore
├── AGENTS.md
├── codex-setup.md
├── config.toml
├── agents\
│ ├── correctness_reviewer.toml
│ ├── explorer.toml
│ ├── plan_implementer.toml
│ ├── plan_reviewer.toml
│ └── proposal_reviewer.toml
├── rules\
│ └── default.rules
└── hooks.json
Runtime files such as authentication, sessions, logs, caches, databases, and sandbox state are excluded from Git.
Example config.toml
This is the general shape of my current configuration. Model names are account- and time-dependent, so replace them with models available to you.
model = "gpt-5.6-sol"
model_reasoning_effort = "medium"
review_model = "gpt-5.6-terra"
personality = "pragmatic"
approval_policy = "on-request"
sandbox_mode = "workspace-write"
[windows]
sandbox = "elevated"
[sandbox_workspace_write]
network_access = false
[memories]
generate_memories = false
use_memories = false
[analytics]
enabled = false
[agents]
enabled = true
max_concurrent_threads_per_session = 3
default_subagent_model = "gpt-5.6-terra"
default_subagent_reasoning_effort = "medium"
I also have trusted-project entries in config.toml. Those are
machine-specific and should not be copied blindly.
Windows sandbox choice
I use the native Windows elevated sandbox rather than WSL. This fits my
Windows-native repositories, PowerShell tooling, Python environments, and
desktop application testing.
The Codex elevated sandbox is a stronger native Windows sandbox
implementation. It does not mean every action is automatically approved or
that ordinary commands run as an unrestricted administrator.
The sandbox runs Codex’s commands under two separate local Windows accounts with fewer rights than mine. Codex creates them the first time it needs the sandbox, after one administrator prompt. It works the same inside a Hyper-V virtual machine.
MCP server tokens
An MCP server (a plug-in that gives Codex extra tools, such as access to my
hosting account) that needs an API token reads it from a Windows user
environment variable, so config.toml and the repo that backs it up never
hold the secret:
[mcp_servers.example]
url = "https://mcp.example.com/mcp"
bearer_token_env_var = "EXAMPLE_API_TOKEN"
A chat only sees MCP servers that existed when it started, so start a new chat after adding one.
Adapting Claude Code Behavior into AGENTS.md
Codex does not import Claude Code’s memory or configuration automatically. I had Codex perform a read-only audit of my Claude setup and translate the provider-neutral intent into:
%USERPROFILE%\.codex\AGENTS.md
I did not copy CLAUDE.md verbatim. The two products have different
instruction formats, permission systems, hooks, models, and sandbox
behavior.
The translated Codex guidance covers:
- my role as requirements owner and acceptance tester rather than the coder
- trust-but-verify behavior
- request scope and authority boundaries
- planning, implementation, and review responsibilities
- separate commit, merge, push, tag, build, and release approvals
- branch hygiene and status reporting
- testing and manual smoke-test expectations
- temporary-file cleanup
- no ownership, ACL, inheritance, or permission repair without approval
- no repository-local test temp fallback merely to bypass sandbox restrictions
- mixed CRLF/LF endings treated as cosmetic unless they violate policy or cause a real problem
- security and secret-handling rules
- provider-parity checks after global configuration changes
A typical high-level structure is:
Global Codex Rules
===================
## About Me
## Authority and Request Scope
## Coding Roles
## Planning and Implementation
## Reviews
## Git Workflow
## Files, Systems, and Remote Access
## Security
## Shared Configuration and Provider Parity
Codex reads global AGENTS.md at session startup, so start a new Codex chat
after changing it.
Custom Codex Agents
I created five Codex agent definitions:
%USERPROFILE%\.codex\agents\correctness_reviewer.toml
%USERPROFILE%\.codex\agents\explorer.toml
%USERPROFILE%\.codex\agents\plan_implementer.toml
%USERPROFILE%\.codex\agents\plan_reviewer.toml
%USERPROFILE%\.codex\agents\proposal_reviewer.toml
| Agent | Purpose | Read-only? |
|---|---|---|
| Explorer | Locates evidence, inspects repository structure, and identifies relevant files and symbols. Avoids acting as a code reviewer. | Yes |
| Correctness Reviewer | Independently reviews the actual diff for bugs and regressions, checks security, privacy, and failure handling, and identifies missing tests for changed non-UI behavior. Verifies findings before reporting them. | Yes |
| Plan Implementer | Implements an approved plan, validates the expected branch and scope, runs appropriate tests, and avoids unrelated changes. Stops before Git operations unless separately approved. | No |
| Plan Reviewer | Reviews the implementation against the user’s actual request, identifies missing scope, added scope, or a wrong interpretation, and reports findings without rewriting the implementation automatically. | Yes |
| Proposal Reviewer | Weighs a proposed plan, design, or approach before anything is built: its assumptions, likely failure modes, and simpler paths. Only Codex has this role, so the review comes from a different provider than the Claude senior that wrote the plan. | Yes |
The senior developer gives the implementer a small work order containing the desired outcome, owned files or edit surface, acceptance criteria, relevant source paths, required validation, and protected or out-of-scope areas.
Correctness and intent remain separate reviews, the same split covered on the site’s review model page. The correctness reviewer checks whether the change is technically sound. The plan reviewer checks whether it is the change the user actually requested.
The Claude and Codex agent files are separate translations. They are not symlinked because their syntax, model declarations, tool controls, and sandbox settings are provider-specific.
Codex Rules and Git Approval Behavior
Codex uses both:
- the Windows sandbox, which enforces filesystem and network boundaries.
prefix_ruleentries under.codex\rules, which control matching commands that request execution outside the sandbox.
My final Git rules are deliberately narrower than the first draft, since a
broad git remote, config, and tag rule prompted for approval even on
read-only commands like git remote -v. Splitting the rules keeps normal
reads quiet while mutations still gate.
| Prompts for approval | Runs without a prompt |
|---|---|
git commit |
git status |
git merge |
git log |
git push |
git branch --all |
git reset |
git remote -v |
git checkout |
git remote get-url |
git restore |
git config --get |
every form of git clean |
git config --list |
mutating git remote subcommands |
git tag --list |
destructive or forced git tag forms |
git stash list |
destructive git config options |
|
git stash drop |
|
git stash clear |
git clean stays intentionally broad because it can delete ordinary
untracked files inside the writable workspace, including when options are
reordered or combined.
Example:
prefix_rule(
pattern = ["git", ["commit", "merge", "push", "reset", "checkout", "restore"]],
decision = "prompt",
justification = "Git state-changing operations require explicit approval.",
)
prefix_rule(
pattern = ["git", "clean"],
decision = "prompt",
justification = "Git clean can delete untracked workspace files and requires explicit approval.",
)
prefix_rule(
pattern = [
"git",
"remote",
["add", "rename", "remove", "rm", "set-head", "set-branches", "set-url", "update", "prune"],
],
decision = "prompt",
justification = "Changing Git remote configuration or remote-tracking state requires explicit approval.",
)
Use match and not_match examples as inline rule tests, and validate rules
with:
codex execpolicy check --pretty `
--rules "$HOME\.codex\rules\default.rules" `
-- git remote -v
Rules are loaded at startup. Restart Codex after changing them.
Deletes and the shell version
Codex has no hook like Claude’s command gate, so the bulk-delete rule is an
instruction in AGENTS.md, not an enforced block. Codex never deletes
recursively or in bulk through shell commands, inline code, scripts, or
git clean. For a git-ignored build or cache folder inside a repository, it
uses the same safe-delete script Claude uses, with exact paths. If the script
refuses, Codex reports and stops; any other target stays in place and is named
in its final report. The sandbox keeps Codex’s writes to its working folder
and temp, but inside a repository working folder a recursive delete is still
possible, which is why the instruction exists.
The same file carries the PowerShell 7 rule: before any command that deletes, moves, or overwrites files, Codex confirms the shell is version 7 or later and stops if it is Windows PowerShell 5.1. The reason is in this field note.
Sharing Skills Between Claude Code and Codex
Canonical location
My provider-neutral skills live under:
%USERPROFILE%\.claude\skills
Codex user-skill location
Codex discovers user skills under:
%USERPROFILE%\.agents\skills
Codex supports symlinked skill directories, so each Codex-facing skill is a directory symbolic link to the canonical Claude-owned directory.
Why whole-directory symlinks
A whole-directory link exposes all current and future skill content:
SKILL.md, references\, templates\, scripts\, assets\, and any
tests and supporting files. There is no copy job, synchronization script, or
second source of truth.
Creating the links
Enable Windows Developer Mode or run an appropriately elevated shell.
Create the parent directory:
New-Item -ItemType Directory -Force "$HOME\.agents\skills"
Example using native mklink:
mklink /D "%USERPROFILE%\.agents\skills\myapps-build-ship" "%USERPROFILE%\.claude\skills\myapps-build-ship"
Repeat for each shared skill.
My shared skills are:
myapps-build-ship
myapps-fleet-rollout
myapps-new-project
myapps-repo-setup
myapps-server
myapps-test-session
myapps-theme-ui
agent-config-parity
Validation
Get-Item -Force "$HOME\.agents\skills\myapps-build-ship" |
Select-Object FullName, LinkType, Target, Attributes
Require:
LinkTypeisSymbolicLink- the target is the expected canonical directory
- the linked and source inventories match
- deleting the link never deletes the canonical target
Provider-neutral skill wording
Shared skills should describe the actor as the coding agent when the workflow applies to both products.
Do not neutralize genuinely provider-specific behavior. Examples:
- Claude model metadata stays Claude-specific.
- Codex sandbox behavior stays Codex-specific.
- Claude notification hooks stay Claude-specific.
- Shared testing, release, UI, and Git workflows can usually be provider-neutral.
Private Git Repositories
I track two private repositories:
%USERPROFILE%\.claude -> claude-config
%USERPROFILE%\.codex -> codex-config
I do not make %USERPROFILE%\.agents a repository. It contains only the
symlink layer.
Codex allowlist-style .gitignore
The Codex directory also contains credentials, sessions, logs, databases, caches, and sandbox state. Use an ignore-everything, include-only-known- config approach.
Example:
/*
!/.gitignore
!/AGENTS.md
!/codex-setup.md
!/config.toml
!/agents/
!/agents/**
!/rules/
!/rules/**
!/hooks.json
!/hooks/
!/hooks/**
Before the first commit:
Set-Location "$HOME\.codex"
git status --short --ignored
git add --dry-run .
Do not commit: authentication files, session JSONL files, local conversation indexes, logs, caches, SQLite databases, sandbox state, temporary files, or secret material.
The two config repositories are committed, merged, and pushed independently. Approval for one repository never authorizes changes in the other.
Preventing Claude and Codex Configuration Drift
See provider-parity for why this exists and what it deliberately does not do. The script itself is not published here, and it does not need to be: it’s a few hundred lines of standard-library Python, and the design matters more than the code. Hand this section to your own coding agent and have it build the script and its tests with you; the rest of this section is the specification.
Layout
%USERPROFILE%\.claude\
├── config-parity\
│ ├── parity-manifest.json
│ └── known-differences.md
└── skills\
└── agent-config-parity\
├── SKILL.md
├── scripts\
│ └── audit_config_parity.py
└── tests\
└── test_audit_config_parity.py
%USERPROFILE%\.agents\skills\agent-config-parity
-> %USERPROFILE%\.claude\skills\agent-config-parity
The audit lives in a shared skill, so both providers can run it through the same symlink.
Both CLAUDE.md and Codex AGENTS.md contain standing instructions to run
the read-only parity audit after changes to:
- global instructions
- agent definitions
- approval or permission behavior
- testing or cleanup policy
- Git or release policy
- shared cross-provider workflow behavior
Ordinary application-repository work does not require a parity audit.
Mapping types
The manifest classifies relationships as:
- shared canonical content through a symlink
- translated intent represented differently
- provider-specific intentional differences
- unmapped behavior
- manual review required
It records:
- source and target paths
- relevant sections
- reviewed hashes
- repository commits
- source-of-truth classification
- parity status
- provider-specific notes
known-differences.md
This file holds the results of the human comparison pass the audit cannot do itself: direct conflicts, and rules one provider has that the other does not. It holds open questions only. An entry is deleted once the difference is closed, either by making both sides match or by recording it in the manifest as intentional, so the file never becomes a history of settled arguments.
Audit command
python "$HOME\.claude\skills\agent-config-parity\scripts\audit_config_parity.py" `
--manifest "$HOME\.claude\config-parity\parity-manifest.json"
Exit codes
0 Reviewed state unchanged or intentionally different
1 Drift, dirty repository, or manual review required
2 Structural failure, invalid manifest, missing file, or broken link
3 Unsafe path resolution
Safety properties
The audit:
- uses Python’s standard library only
- resolves roots through
Path.home() - rejects paths outside
.claude,.codex, and.agents\skills - reads only explicitly mapped artifacts
- does not fetch
- does not edit
- does not stage, commit, merge, push, tag, or publish
- does not automatically copy configuration between providers
- requires separate human approval for any proposed counterpart change
Text hashes normalize LF, CRLF, bare CR, and mixed endings so ordinary Windows line-ending conversion does not create false drift. Binary or non-UTF-8 data remains byte-exact.
Normal Day-to-Day Workflow
- Open a repository in VS Code.
- Use either Claude Code or Codex.
- Both agents can invoke the same provider-neutral
myapps-*skills. - Provider-specific global instructions and permission systems remain separate.
- The agent implements and validates changes on an appropriate branch.
- Commit, merge, push, tag, build, and release remain separate approval steps.
- A global configuration change triggers the read-only parity audit.
- The audit explains whether the counterpart already shares the same canonical content, needs a translated change, should remain provider-specific, or requires human judgment.
- Changes to
.claudeand.codexare reviewed, committed, merged, and pushed separately.
Validation Checklist
After setting up a similar environment, verify:
Codex global setup
- A fresh Codex chat can summarize the loaded
AGENTS.md. config.tomlparses and the intended models and sandbox are active.- All custom agent TOML files load.
- The correctness reviewer remains read-only and separate from intent review.
- Memories and analytics match your intended privacy settings.
Rules
git status,git log,git remote -v, and file listing run without an unnecessary approval prompt.git commit,git merge,git push,git clean, and destructive operations still prompt.codex execpolicy checkpasses all inline tests.
Shared skills
- Every
.agents\skillsentry is a directory symbolic link. - Every target resolves to the intended
.claude\skillsdirectory. - Source and linked inventories match.
- A new Codex session discovers all expected skills.
Git repositories
.claudeand.codexare clean.- Both private remotes are synchronized.
.agentsis not a third repository.- No runtime, session, authentication, cache, database, or sandbox files are tracked.
Parity audit
- The audit runs twice with stable output.
- Exit code is
0at the reviewed baseline. - Tests pass.
- All shared-skill links report healthy.
- A deliberate global instruction change is detected and explained without being synchronized automatically.
VS Code UX
- Codex Extras shows the local chat list.
- Existing chats open in pinned editor tabs.
- New agents can be started from the toolbar.
- Claude Code remains available and unaffected.
What Not to Do
- Do not symlink all of
.claudeinto.codex. - Do not copy Claude hooks directly into Codex without translating the behavior.
- Do not force Claude and Codex to use identical provider-specific settings.
- Do not auto-sync global configuration based only on file hashes.
- Do not treat wording or syntax differences as drift when intent is equivalent.
- Do not permanently patch an installed VS Code extension unless you accept that updates may overwrite the change.
- Do not let either provider modify the other provider’s repository without separate approval.