How to Manage Skills Across Multiple Repos with a Centralized Registry
Open SourceScore: 72

How to Manage Skills Across Multiple Repos with a Centralized Registry

Use symlinks and a dispatch skill to share Claude Code skills across projects without plugin namespacing overhead.

Ggentic.news Editorial·5h ago·4 min read·4 views
Share:
Source: dev.tovia devto_claudecodeSingle Source

The Problem: Skills Drift Across Repos

If you use Claude Code across multiple repositories, you've faced this: you create a custom /review-pr skill in one project, then copy it to another. A week later, you improve the skill in the second repo but forget to update the first. Your skills drift apart, and maintaining consistency becomes impossible.

This developer's solution? A centralized skill registry using symlinks instead of Claude Code's plugin system.

Why Plugins Aren't Always the Answer

Claude Code plugins solve distribution—they package skills for sharing across projects or teams. But they introduce friction for multi-repo workflows you control:

  1. Namespacing overhead: Instead of /develop PROJ-123, you type /my-plugin:develop PROJ-123. When you're the only consumer, this extra typing adds up.
  2. No cross-repo coordination: Plugins work per-project. They can't route a Jira ticket to the correct repository.
  3. Configuration complexity: Different repos need different skill configurations (build commands, review thresholds). Plugins store config inside themselves, forcing forks or external config logic anyway.
  4. Update delays: Plugin updates require reinstallation. When iterating on a skill, you want changes to propagate instantly.

The Registry Solution: Symlinks + Dispatch

Here's the actionable setup:

1. Create a Central Repository

mkdir ~/claude-registry
cd ~/claude-registry
mkdir -p projects/project-a/skills
mkdir -p projects/project-a/agents
mkdir -p projects/project-b/skills
# etc.

Each project directory contains:

  • skills/ - Your shared skill files
  • agents/ - Shared agent configurations
  • config.json - Project-specific settings

2. Add a Registry File

Create registry.json in the root:

{
  "projects": [
    {
      "name": "project-a",
      "repo_path": "/Users/you/code/project-a",
      "profile": "projects/project-a",
      "tech_stack": ["react", "typescript"],
      "jira_components": ["frontend"],
      "jira_labels": ["ui"],
      "keywords": ["component", "hook"]
    },
    {
      "name": "project-b",
      "repo_path": "/Users/you/code/project-b",
      "profile": "projects/project-b",
      "tech_stack": ["python", "fastapi"],
      "jira_components": ["backend"],
      "jira_labels": ["api"],
      "keywords": ["endpoint", "model"]
    }
  ]
}

3. Create a Dispatch Skill

In your central repo, create dispatch/skill.md:

# /dispatch

Routes Jira tickets to the appropriate repository based on registry scoring.

## Scoring Logic
- Component match: +10 points
- Label match: +5 points
- Keyword match: +2 points (capped at +10)

If top score >= 10 and >= 2x runner-up: auto-route
Otherwise: ask user

## Usage
`/dispatch PROJ-123 "Fix login button alignment"`

The skill reads registry.json, scores the ticket against each project, and either routes automatically or prompts for confirmation.

4. Setup Script for Symlinks

Create setup.sh:

#!/bin/bash
REGISTRY="registry.json"
CENTRAL_PATH="$(pwd)"

for project in $(jq -r '.projects[] | .name' "$REGISTRY"); do
  repo_path=$(jq -r ".projects[] | select(.name == \"$project\") | .repo_path" "$REGISTRY")
  profile=$(jq -r ".projects[] | select(.name == \"$project\") | .profile" "$REGISTRY")
  
  if [ -d "$repo_path" ]; then
    # Backup existing skills directory
    if [ -d "$repo_path/.claude/skills" ] && [ ! -L "$repo_path/.claude/skills" ]; then
      mv "$repo_path/.claude/skills" "$repo_path/.claude/skills.backup.$(date +%s)"
    fi
    
    # Create symlinks
    ln -sfn "$CENTRAL_PATH/$profile/skills" "$repo_path/.claude/skills"
    ln -sfn "$CENTRAL_PATH/$profile/agents" "$repo_path/.claude/agents"
    
    echo "Linked $project"
  else
    echo "Warning: $repo_path not found"
  fi
done

Run it once per project, or whenever you add a new repo.

5. Add Project-Specific Config

Each project's config.json can override skill behavior:

{
  "review_threshold": 3,
  "build_command": "npm run build",
  "default_branch": "main",
  "branch_prefix": "feat/"
}

Skills read this config at runtime via {{config.review_threshold}}.

When This Beats Plugins

Use this pattern when:

  • You control all target repositories
  • You need cross-repo routing (like /dispatch)
  • You want bare skill names (/develop not /plugin:develop)
  • You need instant skill updates across all projects
  • Per-project configuration must be separate from skill logic

Stick with plugins when:

  • Distributing to the community (namespacing prevents conflicts)
  • You need versioned releases with changelogs
  • Skills are self-contained with no cross-repo coordination
  • You're bundling MCP servers or hooks

The Hybrid Approach

Nothing stops you from using both. Use plugins for generic skills (/explain-code, /refactor) that don't need project context. Use the registry pattern for workflow skills (/develop, /review-pr) that need cross-repo awareness and project-specific configuration.

This follows Claude Code's plugin system release earlier this year, which solved distribution but left coordination gaps for multi-repo workflows. The registry pattern fills those gaps while maintaining Claude Code's core simplicity.

AI Analysis

Claude Code users managing multiple repositories should implement this registry pattern immediately. Start by creating a central directory for your skills, then use the setup script to symlink `.claude/skills` directories back to it. This gives you: 1. **Single source of truth**: Edit a skill once, all projects get the update instantly via symlinks. 2. **Cross-repo routing**: Build a `/dispatch` skill that reads your registry.json to route Jira tickets or tasks to the correct repository automatically. 3. **Project-specific config without forking**: Store build commands, branch naming, and review thresholds in each project's config.json while sharing the same skill logic. For teams, this is a game-changer. New members clone the registry repo, run the setup script, and immediately have all standardized skills across every project. No more copying skill files or dealing with plugin namespacing when you're the only consumer. If you've been copying `.claude/skills` directories between projects, stop today. The symlink approach eliminates drift while keeping the bare skill names you're used to typing.
Enjoyed this article?
Share:

Related Articles

More in Open Source

View all