feat: Add sync command for Claude Code personal config (#123)

* feat: Add sync command for Claude Code personal config

Add `compound-plugin sync` command to sync ~/.claude/ personal config
(skills and MCP servers) to OpenCode or Codex.

Features:
- Parses ~/.claude/skills/ for personal skills (supports symlinks)
- Parses ~/.claude/settings.json for MCP servers
- Syncs skills as symlinks (single source of truth)
- Converts MCP to JSON (OpenCode) or TOML (Codex)
- Dedicated sync functions bypass existing converter architecture

Usage:
  compound-plugin sync --target opencode
  compound-plugin sync --target codex

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: address security and quality review issues

Security fixes:
- Add path traversal validation with isValidSkillName()
- Warn when MCP servers contain potential secrets (API keys, tokens)
- Set restrictive file permissions (600) on config files
- Safe forceSymlink refuses to delete real directories
- Proper TOML escaping for quotes/backslashes/control chars

Code quality fixes:
- Extract shared symlink utils to src/utils/symlink.ts
- Replace process.exit(1) with thrown error
- Distinguish ENOENT from other errors in catch blocks
- Remove unused `root` field from ClaudeHomeConfig
- Make Codex sync idempotent (remove+rewrite managed section)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: revert version bump (leave to maintainers)

* feat: bump root version to 0.2.0 for sync command

---------

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Terry Li
2026-02-09 07:00:48 +08:00
committed by GitHub
parent f7cab16b06
commit 1bdd1030f5
8 changed files with 381 additions and 2 deletions

View File

@@ -3,6 +3,7 @@ import { defineCommand, runMain } from "citty"
import convert from "./commands/convert"
import install from "./commands/install"
import listCommand from "./commands/list"
import sync from "./commands/sync"
const main = defineCommand({
meta: {
@@ -14,6 +15,7 @@ const main = defineCommand({
convert: () => convert,
install: () => install,
list: () => listCommand,
sync: () => sync,
},
})