How to Sync Personal Claude Code Skills to OpenCode via Symlinks

The compound-engineering-plugin CLI creates symbolic links between ~/.claude/skills and ~/.config/opencode/skills, enabling live editing without file duplication or data loss.

The EveryInc/compound-engineering-plugin repository provides a dedicated sync command that bridges your personal Claude Code configuration with OpenCode. By parsing your Claude home directory and generating safe symbolic links, the tool ensures that any modifications to your original skill files are immediately reflected in OpenCode's environment.

How the Sync Command Works

The synchronization process runs entirely within the plugin CLI and follows a six-step pipeline defined in src/commands/sync.ts. Each step includes specific safety checks to prevent path traversal and data loss.

Loading Claude Code Configuration

The process begins with loadClaudeHome() in src/parsers/claude-home.ts, which scans ~/.claude/ and returns an object containing the skills array. Each skill entry includes a name and sourceDir pointing to the original skill location.

Validating Skill Names

Before creating any links, the system validates skill names using isValidSkillName() in src/utils/symlink.ts (lines 36-43). This function blocks path-traversal attempts like ../, empty strings, and characters that could escape the target ~/.config/opencode/skills directory.

The forceSymlink(sourceDir, targetPath) function in src/utils/symlink.ts (lines 7-23) handles the actual link creation with the following safety protocol:

  • Removes existing symlinks at the target location
  • Deletes regular files if they block the path
  • Refuses to delete real directories, throwing an error instead to prevent accidental data loss

Merging MCP Servers

If your Claude configuration contains MCP server definitions, convertMcpForOpenCode() in src/sync/opencode.ts (lines 26-33) transforms them into OpenCode's format and merges them into opencode.json (lines 48-74).

Step-by-Step Sync Process

Install the Plugin

bun install @everyinc/compound-engineering-plugin

# or globally with npm

npm i -g @everyinc/compound-engineering-plugin

Run the Default Sync

npx compound-engineering-plugin sync opencode

This command syncs all skills from the default Claude home (~/.claude) into ~/.config/opencode/skills as symbolic links.

Specify a Custom Claude Home

If your Claude configuration resides elsewhere:

npx compound-engineering-plugin sync opencode --claude-home /path/to/custom/.claude

Safety Mechanisms

The plugin implements three critical safety layers to protect your data:

  • Path traversal prevention: The isValidSkillName() utility blocks ../ patterns and absolute paths that could escape the skills directory
  • Directory protection: The forceSymlink() function explicitly refuses to overwrite existing directories, ensuring you cannot accidentally delete project folders
  • Secret detection: Before merging MCP configurations, the CLI scans for potential API keys or tokens and prints a warning via hasPotentialSecrets to prevent credential leakage

The decision to use symbolic links rather than file copies provides two primary advantages:

  • Live editing: Modifying a skill in ~/.claude/skills/my-skill immediately updates the OpenCode view because the target is merely a pointer to the original file
  • Zero duplication: No additional disk space is consumed, and the source of truth remains exclusively within your Claude Code home directory

Summary

  • The compound-engineering-plugin sync command bridges Claude Code and OpenCode configurations using symbolic links
  • The process loads skills from ~/.claude/, validates names against path traversal, and creates safe symlinks in ~/.config/opencode/skills
  • Safety mechanisms prevent directory overwrites and detect potential secrets in MCP server configurations
  • Symlinks enable live editing without file duplication, keeping the Claude home as the single source of truth

Frequently Asked Questions

What happens if a skill name contains invalid characters?

The isValidSkillName() function in src/utils/symlink.ts rejects names containing path traversal patterns like ../, absolute paths, or empty strings. The sync command will skip these invalid entries and continue processing valid skills, preventing any escape from the target directory.

Can the sync command delete my existing directories?

No. The forceSymlink() utility explicitly refuses to delete real directories. If a directory exists at the target path where a symlink should be created, the command throws an error and halts rather than risk data loss. It will only remove existing symlinks or regular files blocking the path.

Do I need to re-run the sync after editing my Claude Code skills?

No. Because the sync creates symbolic links rather than file copies, any changes you make to files in ~/.claude/skills/ are immediately reflected in ~/.config/opencode/skills/. You only need to re-run the sync when you add new skills or rename existing ones in your Claude configuration.

How does the plugin handle MCP server secrets?

Before merging MCP server definitions into opencode.json, the CLI scans for potential secrets using hasPotentialSecrets. If detected, the command prints a warning to the console to alert you that credentials may be exposed in the configuration file, allowing you to review the output before committing it to version control.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →