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:

  1. .claude and .codex are separate private repositories.
  2. .agents is only a symlink layer and is not its own repository.
  3. Shared skills have one canonical copy under .claude\skills.
  4. Claude-specific instructions, hooks, and settings remain under .claude.
  5. Codex-specific instructions, sandbox settings, custom agents, and rules remain under .codex.
  6. 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
  • Codex Extras
    • Extension ID: netroforge.codex-extras

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:

  1. the Windows sandbox, which enforces filesystem and network boundaries.
  2. prefix_rule entries 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.

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.

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:

  • LinkType is SymbolicLink
  • 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

  1. Open a repository in VS Code.
  2. Use either Claude Code or Codex.
  3. Both agents can invoke the same provider-neutral myapps-* skills.
  4. Provider-specific global instructions and permission systems remain separate.
  5. The agent implements and validates changes on an appropriate branch.
  6. Commit, merge, push, tag, build, and release remain separate approval steps.
  7. A global configuration change triggers the read-only parity audit.
  8. The audit explains whether the counterpart already shares the same canonical content, needs a translated change, should remain provider-specific, or requires human judgment.
  9. Changes to .claude and .codex are 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.toml parses 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 check passes all inline tests.

Shared skills

  • Every .agents\skills entry is a directory symbolic link.
  • Every target resolves to the intended .claude\skills directory.
  • Source and linked inventories match.
  • A new Codex session discovers all expected skills.

Git repositories

  • .claude and .codex are clean.
  • Both private remotes are synchronized.
  • .agents is 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 0 at 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 .claude into .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