Skip to content

Conversation

@terry-li-hm
Copy link
Contributor

@terry-li-hm terry-li-hm commented Jan 26, 2026

Summary

Add compound-plugin sync command to sync ~/.claude/ personal configuration to OpenCode or Codex.

Problem: The current convert command only handles .claude-plugin/ directories. Users with personal skills in ~/.claude/skills/ or MCP servers in ~/.claude/settings.json cannot sync these to OpenCode/Codex without manual work.

Solution: New dedicated sync command that:

  • Parses ~/.claude/skills/ for personal skills (supports symlinks)
  • Parses ~/.claude/settings.json for MCP servers
  • Syncs skills as symlinks (single source of truth, instant updates)
  • Converts MCP to JSON (OpenCode) or TOML (Codex)

Usage

# Sync to OpenCode
compound-plugin sync --target opencode

# Sync to Codex
compound-plugin sync --target codex

# Custom Claude home path
compound-plugin sync --target opencode --claude-home /path/to/.claude

Files Changed

File Purpose
src/parsers/claude-home.ts Parse ~/.claude/ for skills and MCP
src/commands/sync.ts New sync command
src/sync/opencode.ts Dedicated OpenCode sync
src/sync/codex.ts Dedicated Codex sync
src/utils/symlink.ts Safe symlink + path validation utils
src/index.ts Register sync command
README.md Document sync command

Security Considerations

  • Path traversal validation: isValidSkillName() rejects ../, /, \, null bytes
  • Secrets warning: Warns when MCP servers contain potential secrets (API keys, tokens)
  • Restrictive permissions: Config files written with mode 600
  • Safe symlink: Refuses to delete real directories (only replaces symlinks/files)
  • TOML escaping: Proper escaping for quotes, backslashes, control characters

Design Decisions

  1. Dedicated sync functions instead of modifying existing converters — keeps existing code clean, sync only needs skills + MCP (not agents/commands/hooks)
  2. Always symlinks — single source of truth, changes in Claude Code reflected immediately
  3. Separate parser (ClaudeHomeConfig) — doesn't pollute ClaudePlugin type with home directory semantics

Testing

$ bun run src/index.ts sync --target opencode
⚠️  Warning: MCP servers contain env vars that may include secrets...
Syncing 47 skills, 1 MCP servers...
✓ Synced to opencode: /Users/terry/.config/opencode

All 34 tests pass after rebase on upstream/main.


Compound Engineered 🤖 Generated with Claude Code

terry-li-hm and others added 3 commits January 26, 2026 10:56
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>
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>
@terry-li-hm terry-li-hm force-pushed the feat/claude-home-sync branch from 8c6c3dd to 34f3f91 Compare January 26, 2026 02:56
@kieranklaassen
Copy link
Collaborator

Ohh sick! Will try tomorrow!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants