Overview
I run Claude Code and Codex side by side, and I split my work between them on purpose. Each subscription has usage limits, and leaning on one until it hits its usage limit means stopping mid-task. Alternating spreads the load across both, so I keep working. That only pays off if switching between them is cheap, which is the whole point of what follows: 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.
Goals for Codex in this setup:
- the same reusable build, test, release, UI, and repository workflows;
- similar planning, implementation, review, and Git approval boundaries;
- separate provider-specific configuration where Claude and Codex work differently;
- private Git tracking for both global configurations;
- a read-only parity audit that detects drift without synchronizing anything automatically;
- normal editor tabs and a usable local chat history inside VS Code.
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
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
├── config.toml
├── agents\
│ ├── correctness_reviewer.toml
│ ├── explorer.toml
│ ├── plan_implementer.toml
│ └── plan_reviewer.toml
└── rules\
└── default.rules
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.
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 four 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
| 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. | No |
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; and
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.
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.
References
- OpenAI Codex IDE extension
- OpenAI Codex AGENTS.md guidance
- OpenAI Codex skills
- OpenAI Codex rules
- OpenAI Codex Windows sandbox
- Codex Extras on the Visual Studio Marketplace
Closing Notes
This is a deliberate separation of concerns, not a one-click Claude-to-Codex import. That balance lets me use Claude Code and Codex side by side in VS Code without maintaining two independent copies of every workflow or pretending the products have identical capabilities.