AI News HubLIVE
In-site rewrite5 min read

Show HN: Sync Claude Code and Codex configs, with a board that shows the drift

ai-config-sync-manager is a CLI tool for continuously bidirectional syncing of configurations between Claude Code and Codex. It features a diff-first workflow, strict YAML round-trip, risk-tagged operations, automatic backups, and a visual board, aiming to keep configurations consistent across the two AI coding assistants.

SourceHacker News AIAuthor: slash9494

Notifications You must be signed in to change notification settings

Fork 4

Star 21

BranchesTags

Open more actions menu

Folders and files

NameName

Last commit message

Last commit date

Latest commit

History

212 Commits

212 Commits

.github

.github

.husky

.husky

assets

assets

bin

bin

docs

docs

integrations

integrations

rules

rules

schemas

schemas

scripts

scripts

snapshots

snapshots

tests

tests

.gitignore

.gitignore

.lintstagedrc.mjs

.lintstagedrc.mjs

.prettierignore

.prettierignore

.prettierrc.json

.prettierrc.json

AGENTS.md

AGENTS.md

CHANGELOG.md

CHANGELOG.md

CLAUDE.md

CLAUDE.md

LICENSE

LICENSE

README.md

README.md

eslint.config.mjs

eslint.config.mjs

package-lock.json

package-lock.json

package.json

package.json

setup

setup

tsconfig.check.json

tsconfig.check.json

Repository files navigation

Continuous bidirectional sync between Claude Code and Codex — round-trip lossless, not a one-shot migrator.

Highlights

Continuous bidirectional sync — claude → codex and codex → claude, run as often as the two hosts drift; not a one-shot migration.

Strict YAML round-trip — Claude lenient YAML and Codex YAML 1.2 strict frontmatter both preserved across repeated syncs without loss or oscillation.

Diff-first workflow — status to compare → sync --dry-run to preview → --apply to write.

Risk-tagged operations — permissions, hooks, custom commands labeled safe / partial / manual.

Backup-on-write — every overwrite snapshotted under .backups/, FIFO retention (30).

Apply ledger — every --apply writes a per-item sha256 attestation (before/after hash, backup path) to ~/.ai-config-sync-manager/ledgers/.

Selector syntax — --include skills:code-writer,instructions --exclude mcp style filtering.

Native semantic mapping — Claude Write → Codex sandbox_mode = "workspace-write", etc.

Prose-level token rewriting — Claude-only tokens (Read, Bash, TaskCreate, headless claude -p) and Codex-only tokens (spawn_agent, codex exec) auto-translate across hosts and round-trip back.

Zero runtime dependencies — single ESM file, Node built-ins only.

Thin host plugins — /config-manager:* for Claude, config-manager-* for Codex.

Visual inventory board — board renders a self-contained HTML page of every skill, agent, hook, and MCP server on both hosts, colored by sync status (in-sync / conflict / one-host-only) and grouped into per-area tabs and by agent harness. Jump to the board →

Why this exists

Claude Code and Codex use the same concepts (instructions / skills / mcp / permissions / hooks) but in different files, formats, and names:

Concept Claude Codex

Instructions ~/.claude/CLAUDE.md ~/.codex/AGENTS.md

Skills ~/.claude/skills/ ~/.codex/skills/

Settings ~/.claude/settings.json ~/.codex/config.toml

MCP ~/.claude/.mcp.json [mcp_servers.*] in config.toml

Hand-rolling the sync invites drift, semantic loss, and accidental secret leaks. This CLI keeps the two hosts aligned while preserving host-native meaning.

This tool is built for two hosts in continuous use — where drift accumulates daily and round-trip integrity matters across repeated syncs — not for a one-shot, one-way migration.

One-shot migrators typically copy Claude-only vocabulary (tool names like Read / Bash, prose like Use the Bash tool, in-line Agent({...}) calls) into the generated file as prompt guidance and flag it for manual review. This CLI instead auto-rewrites those tokens to their host equivalents (Read → workspace-write, TaskCreate → spawn_agent, claude -p → codex exec, …) and round-trips them back when syncing the other direction — so the same content stays correct for both hosts with no manual fix-ups.

Quick Start

npm install -g ai-config-sync-manager ai-config-sync connect # register the plugin for any detected host (Claude / Codex) ai-config-sync status # show drift across global + project scopes ai-config-sync sync # preview changes (--dry-run by default) ai-config-sync sync --apply # apply with automatic backups

connect only registers plugins for hosts it actually finds (~/.claude for Claude, ~/.codex or ~/.agents for Codex). Hosts that are missing are reported as skipped and no directories are created — install the host first, then rerun connect.

Requirements

Node.js ≥ 20

Claude Code and/or Codex CLI installed (host plugins are auto-registered by connect when the matching host directory exists)

Table of Contents

Category Sections

Commands Bundled CLI · Host plugin commands · Flags · Board

Workflow Selector syntax · Ignore rules · Sync direction · Scopes

Safety Safety defaults · Risk levels · Retention

Mapping Native mapping · Areas · Paraphrase · Hidden markers · Unsupported

Reference Install resolution · Local dev · Gotchas · API surface · What's next

Commands

Bundled CLI

After npm install -g, the same binary is on PATH as ai-config-sync — equivalent to ./bin/ai-config-sync.mjs from a source clone.

ai-config-sync connect ai-config-sync status ai-config-sync status --json ai-config-sync status --scope global ai-config-sync status --scope project ai-config-sync status --include skills:code-writer,instructions --exclude mcp ai-config-sync sync --dry-run ai-config-sync sync --scope project --dry-run ai-config-sync sync --scope global --apply ai-config-sync sync --include instructions,skills:code-writer --exclude mcp --dry-run ai-config-sync sync --from claude --to codex ai-config-sync sync --from codex --to claude ai-config-sync board ai-config-sync board --scope global --no-open ai-config-sync reference ai-config-sync paraphrase

Command Purpose

connect Detect installed hosts and register the matching plugin

status Compare global + project config across both hosts

status --json Machine-readable diff

sync --dry-run Preview the merge plan without writing

sync --apply Apply the plan, snapshot to .backups/

board Render an HTML inventory board of both hosts, colored by sync status

reference Emit / persist a self-generated markdown reference

paraphrase Line-level override archive for instruction wording

Host plugin commands

Host Connect Status Sync Paraphrase

Claude /config-manager:connect /config-manager:status /config-manager:sync /config-manager:paraphrase

Codex config-manager-connect config-manager-status config-manager-sync config-manager-paraphrase

Flags

Per-subcommand flag reference, mirroring --help output. Shared flags (--include / --exclude / --scope / --map) get a one-line summary; full syntax lives in the linked section.

connect

Flag Description

-h, --help Show connect help

ai-config-sync connect

status

Flag Description

--json Print the full status report as JSON

--compact One compact line per diff entry

--tree Scope/area/item tree output

--scope global|project|all Limit scope (default: all = global + project)

--include area[:item][,...] Include selector — see Selector syntax

--exclude area[:item][,...] Exclude selector — see Selector syntax

-h, --help Show status help

ai-config-sync status --scope project --tree --include skills:code-writer

board

Renders a self-contained HTML inventory board — every skill, agent, hook, and MCP server on both hosts, split into per-area tabs, colored by sync status: green = in sync, red = conflict, blue = Claude only, purple = Codex only, amber = unsupported. Agents are grouped under their harness (subfolder) where they have one. Type in the filter box to narrow rows; click a row for the full description, paths, and status detail. The file is written to ~/.ai-config-sync-manager/board/ with no external requests, so it works offline, and opens in your default browser automatically (pass --no-open to skip). (Screenshot at the top.)

Flag Description

--scope global|project|all Limit scope (default: all = global + project)

--include area[:item][,...] Include selector — see Selector syntax

--exclude area[:item][,...] Exclude selector — see Selector syntax

--no-open Only write the file; do not open a browser

-h, --help Show board help

ai-config-sync board --scope global

sync

Flag Description

--dry-run Preview without writing (default; mutually exclusive with --apply)

--apply Apply with backups

--plan-json Print the sync plan as JSON

--ledger-json Print the apply ledger as JSON to stdout (--apply only)

--ledger Write the apply ledger JSON to (--apply only)

--from claude|codex Source host (overrides AI_CONFIG_SYNC_HOST)

--to claude|codex Target host (overrides AI_CONFIG_SYNC_HOST)

--scope global|project|all Limit scope (default: all = global + project)

--include area[:item][,...] Include selector — see Selector syntax

--exclude area[:item][,...] Exclude selector — see Selector syntax

-h, --help Show sync help

When --from / --to are omitted, direction follows Sync direction.

ai-config-sync sync --scope project --include mcp:notion --apply

reference

Flag Description

--output Write the reference markdown to (parent directories created)

-h, --help Show reference help

ai-config-sync reference --output ~/.ai-config-sync-manager/reference.md

paraphrase

Flag Description

--apply Rewrite files + register overrides + persist new map entries (default: dry-run)

--register Skip rewriting; only register overrides where the effective map already equates both sides — see Paraphrase

--map token=paraphrase[,...] Inline token-to-paraphrase pairs (free-form prose accepted) — see --map syntax

--non-interactive Skip TTY prompts for tokens missing from paraphrase-map.json

--json Print the result as JSON

--scope global|project|all Limit scope (default: all = global + project)

--include area[:item][,...] Include selector — see Selector syntax

--exclude area[:item][,...] Exclude selector — see Selector syntax

-h, --help Show paraphrase help

ai-config-sync paraphrase --map "Read=read the file,Write=write to the file" --apply

Selector syntax

--include narrows the plan first, then --exclude removes matches. Both accept area or area:item syntax; itemized areas (skills, permissions, hooks, agents, mcp, commands) accept glob items.

ai-config-sync sync --include skills:code-writer,instructions --exclude mcp --dry-run ai-config-sync sync --include "permissions:Write*" --exclude "permissions:Bash(rm:*)" --dry-run

Areas

Area Itemized? Apply granularity

instructions — file merge

skills yes per skill

agents yes per agent

mcp yes per server

permissions yes item-by-item patch

hooks yes item-by-item patch

commands yes per command

plugins yes status only (read-only diff; sync skips this area)

Ignore rules

Persistent ignore lives at one of:

/.ai-config-sync-manager/status-ignore.json (project scope, checked first)

~/.ai-config-sync-manager/rules/status-ignore.json (global)

Each exclude entry is a string selector (area:item or path glob) or an object whose fields combine with AND. term is a line-level mask — lines containing the substring are removed from both sides before the diff, so the conflict can disappear without hiding unrelated changes.

{ "version": 1, "exclude": [ "skills:legacy-skill", "permissions:Bash", "~/.codex/agents/archive-*.toml", { "scope": "global", "area": "agents", "item": "refactor-*" }, { "area": "skills", "host": "claude", "path": "~/.claude/skills/coderabbit-review" }, { "area": "skills", "term": ".claude/docs/repo-analysis/" }, { "area": "agents", "host": "claude", "path": "~/.claude/agents/*.md", "term": "TODO: do not sync" } ] }

The active path and rule count are echoed in status output as Status ignore: rules: [...] (N hidden).

Sync direction

Trigger Default direction

AI_CONFIG_SYNC_HOST=codex (Codex plugin invocation) codex → claude

Otherwise (Claude plugin / direct CLI) claude → codex

--from --to Explicit override

Scopes

Scope Path coverage

global ~/.claude/, ~/.codex/

project /.claude/, /.codex/, /AGENTS.md, /CLAUDE.md

default / all global +

[truncated for AI cost control]