ln-013-config-syncer

Syncs skills, MCP settings, and hooks from Claude Code to Gemini CLI and Codex CLI via symlinks and config conversion. Use when agent configs need alignment.

310 stars

Best use case

ln-013-config-syncer is best used when you need a repeatable AI agent workflow instead of a one-off prompt.

Syncs skills, MCP settings, and hooks from Claude Code to Gemini CLI and Codex CLI via symlinks and config conversion. Use when agent configs need alignment.

Teams using ln-013-config-syncer should expect a more consistent output, faster repeated execution, less prompt rewriting.

When to use this skill

  • You want a reusable workflow that can be run more than once with consistent structure.

When not to use this skill

  • You only need a quick one-off answer and do not need a reusable workflow.
  • You cannot install or maintain the underlying files, dependencies, or repository context.

Installation

Claude Code / Cursor / Codex

$curl -o ~/.claude/skills/ln-013-config-syncer/SKILL.md --create-dirs "https://raw.githubusercontent.com/levnikolaevich/claude-code-skills/main/skills-catalog/ln-013-config-syncer/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/ln-013-config-syncer/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How ln-013-config-syncer Compares

Feature / Agentln-013-config-syncerStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/A

Frequently Asked Questions

What does this skill do?

Syncs skills, MCP settings, and hooks from Claude Code to Gemini CLI and Codex CLI via symlinks and config conversion. Use when agent configs need alignment.

Where can I find the source code?

You can find the source code on GitHub using the link provided at the top of the page.

Related Guides

SKILL.md Source

> **Paths:** File paths (`shared/`, `references/`) are relative to skills repo root. Locate this SKILL.md directory and go up one level for repo root.

# Config Syncer

**Type:** L3 Worker
**Category:** 0XX Shared

Synchronizes skills (via symlinks) and MCP/hook settings from Claude Code (source of truth) to Gemini CLI and Codex CLI. Converts formats: JSON for Gemini, TOML for Codex.

---

## Input / Output

| Direction | Content |
|-----------|---------|
| **Input** | OS info, `disabled` flags per agent, `targets` (gemini/codex/both), `dry_run` flag, optional `runId`, optional `summaryArtifactPath` |
| **Output** | Structured summary envelope with `payload.status` = `completed` / `skipped` / `error`, plus per-target sync outcomes in `changes` / `detail` |

If `summaryArtifactPath` is provided, write the same summary JSON there. If not provided, return the summary inline and remain fully standalone. If `runId` is not provided, generate a standalone `run_id` before emitting the summary envelope.

---

## Config Paths by OS

| Agent | Windows | macOS / Linux |
|-------|---------|---------------|
| **Claude** (primary) | `%USERPROFILE%\.claude.json` | `~/.claude.json` |
| **Claude** (fallback) | `%USERPROFILE%\.claude\settings.json` | `~/.claude/settings.json` |
| **Gemini** | `%USERPROFILE%\.gemini\settings.json` | `~/.gemini/settings.json` |
| **Codex** | `%USERPROFILE%\.codex\config.toml` | `~/.codex/config.toml` |

---

## Workflow

```
Discover State  -->  Sync Skills  -->  Sync MCP  -->  Sync Hooks  -->  Report
```

### Phase 1: Discover State

1. Read Claude settings (source of truth):
   - `~/.claude.json` (primary) + `~/.claude/settings.json` (fallback)
   - Merge: primary overrides fallback by server name
2. Read target configs (if exist):
   - Gemini: `~/.gemini/settings.json` → extract `mcpServers`
   - Codex: `~/.codex/config.toml` → extract `[mcp_servers.*]`
3. Check existing symlinks: `~/.gemini/skills`, `~/.codex/skills`
4. Display current state table

### Phase 2: Sync Skills (symlinks/junctions)

For each target where `disabled` is not `true`:

| OS | Command |
|----|---------|
| Windows | `cmd /c mklink /J "{target}" "{source}"` |
| macOS/Linux | `ln -s "{source}" "{target}"` |

Decision logic:

| Condition | Action |
|-----------|--------|
| `disabled: true` for this agent | SKIP, report "disabled" |
| Link exists, points correctly | SKIP, report "already linked" |
| Link exists, points wrong | WARN, ask user before replacing |
| Real directory exists (not link) | WARN, skip (avoid data loss) |
| No link exists | Create link |

### Phase 3: Sync MCP Settings
IF agent `disabled: true` → SKIP for that target.

**3a: Claude to Gemini (JSON to JSON)**

| Claude Field | Gemini Field | Notes |
|---|---|---|
| `type: "http"` + `url` | `url` | HTTP (Gemini auto-detects streamable/SSE) |
| `command` + `args` | `command` + `args` | stdio (same format) |
| `env` | `env` | Same format |
| `headers` | `headers` | Same format |

Gemini-only fields (preserve during merge, not mapped from Claude):
`timeout`, `trust`, `includeTools`, `excludeTools`

**3b: Claude to Codex (JSON to TOML)**

| Claude JSON | Codex TOML | Notes |
|---|---|---|
| `command` | `command` | Same |
| `args` | `args` | JSON array to TOML array |
| `env` | `[mcp_servers.{name}.env]` | Nested table |
| `type: "http"` + `url` | `url` | Codex auto-detects by `url` presence |
| `headers` | `http_headers` | **Different key name** |

Codex-only fields (preserve during merge, not mapped from Claude):
`bearer_token_env_var`, `enabled_tools`, `disabled_tools`, `startup_timeout_sec`, `tool_timeout_sec`, `enabled`, `required`

**Merge strategy (both targets):** Claude servers override target by key name. Target-only servers preserved. Backup `.bak` before writing.

### Phase 4: Sync Hooks

**4a: Claude to Gemini (event name + tool name mapping)**

| Claude Event | Gemini Event | Notes |
|---|---|---|
| `PreToolUse` | `BeforeTool` | Same concept, different name |
| `PostToolUse` | `AfterTool` | Same concept, different name |
| `Stop` | `AfterAgent` | Agent completion |
| `SessionStart` | `SessionStart` | Same name |

Tool name mapping in hook matchers:

| Claude Tool Name | Gemini Tool Name |
|---|---|
| `Read` | `read_file` |
| `Edit` | `edit_file` |
| `Write` | `write_file` |
| `Grep` | `search_files` |

Hook scripts must support both tool name formats (same mapping as matchers above).

**4b: Claude to Codex**

Codex does NOT support hooks. SKIP hook sync for Codex. Report "hooks not supported by Codex CLI".

### Phase 4c: Gemini MCP Policy

Gemini CLI policy engine blocks MCP tool calls by default (error: "Tool execution denied by policy") even with `--yolo`. Fix: ensure `~/.gemini/policies/allow-mcp.toml` exists.

| Condition | Action |
|-----------|--------|
| File exists with `mcpName` allow rule | SKIP |
| File missing or no allow rule | Create `~/.gemini/policies/allow-mcp.toml` |

File content:

```toml
[[rule]]
mcpName = "*"
decision = "allow"
priority = 200
```

### Phase 5: Report

```
Config Sync:
| Action         | Target | Status                         |
|----------------|--------|--------------------------------|
| Skills symlink | Gemini | created -> ~/.claude/plugins   |
| Skills symlink | Codex  | already linked                 |
| MCP sync       | Gemini | 4 servers synced (2 new)       |
| MCP sync       | Codex  | 4 servers synced (1 new)       |
| Hooks sync     | Gemini | 3 events synced                |
| Hooks sync     | Codex  | skipped (not supported)        |
| MCP policy     | Gemini | allow-mcp.toml created         |
```

---

## Critical Rules

1. **Claude = source of truth.** Never write TO Claude settings. Read-only source
2. **Non-destructive merge.** Target-only servers and settings preserved. Only Claude servers added/updated
3. **No data loss.** Real directories (not symlinks) at target path → warn and skip, never delete
4. **Backup before write.** Create `.bak` copy before modifying any config file
5. **Respect `disabled` flags.** Skip all operations for disabled agents
6. **Idempotent.** Safe to run multiple times. Already-synced state is skipped

## Anti-Patterns

| DON'T | DO |
|-------|-----|
| Write TO Claude settings from targets | Claude is read-only source |
| Delete target-only MCP servers during sync | Preserve target-only servers |
| Create symlinks inside symlinks (circular) | Check link target before creating |
| Modify config files without backup | Always create `.bak` first |
| Try to sync hooks to Codex | Report "not supported", skip |
| Auto-replace mispointed symlinks | Ask user before replacing |

---

## Definition of Done

- [ ] Claude settings read successfully (both config locations)
- [ ] Skills symlinks created/verified for each non-disabled target
- [ ] MCP settings synced with correct format conversion (JSON for Gemini, TOML for Codex)
- [ ] Hook events and tool names mapped for Gemini
- [ ] Codex hooks skipped with report
- [ ] Gemini MCP policy file verified/created
- [ ] Backup files created before any config modification
- [ ] Final report table displayed

---

**Version:** 1.0.0
**Last Updated:** 2026-03-20

Related Skills

ln-773-cors-configurator

310
from levnikolaevich/claude-code-skills

Configures CORS policy for development and production environments. Use when setting up cross-origin access for APIs.

ln-771-logging-configurator

310
from levnikolaevich/claude-code-skills

Configures structured JSON logging with Serilog (.NET) or structlog (Python). Use when adding logging to backend projects.

ln-741-linter-configurator

310
from levnikolaevich/claude-code-skills

Configures ESLint, Prettier, Ruff, mypy, and .NET analyzers. Use when setting up linting and formatting for a project.

ln-733-env-configurator

310
from levnikolaevich/claude-code-skills

Configures environment variables and secrets protection. Use when setting up .env files and gitignore rules for a project.

ln-647-env-config-auditor

310
from levnikolaevich/claude-code-skills

Checks env var config sync, missing defaults, naming conventions, startup validation. Use when auditing environment configuration.

ln-012-mcp-configurator

310
from levnikolaevich/claude-code-skills

Installs MCP packages, registers servers in Claude Code, configures hooks, permissions, and migrations. Use when MCP needs setup or reconfiguration.

ln-914-community-responder

310
from levnikolaevich/claude-code-skills

Responds to unanswered GitHub discussions and issues with codebase-informed replies. Use when clearing community question backlog.

ln-913-community-debater

310
from levnikolaevich/claude-code-skills

Launches RFC and debate discussions on GitHub. Use when proposing changes that need community input or voting.

ln-912-community-announcer

310
from levnikolaevich/claude-code-skills

Composes and publishes announcements to GitHub Discussions. Use when sharing releases, updates, or news with the community.

ln-911-github-triager

310
from levnikolaevich/claude-code-skills

Produces prioritized triage report from open GitHub issues, PRs, and discussions. Use when reviewing community backlog.

ln-910-community-engagement

310
from levnikolaevich/claude-code-skills

Analyzes community health and delegates engagement tasks. Use when managing GitHub issues, discussions, and announcements.

ln-840-benchmark-compare

310
from levnikolaevich/claude-code-skills

Runs built-in vs hex-line benchmark with scenario manifests, activation checks, and diff-based correctness. Use when measuring hex-line MCP performance against built-in tools.