SSD Nodes Learn 🎉 VPS from $5.50/mo
How to do am Matt ConnorBy Matt Connor · Updated 2026-08-13

How to Share Agent Skills Across Repos Without Drift

No dey copy skills into 8 repos and watch versions drift. Use one shared repo, pin a version per project, add smoke tests, and review every update like dependency bumps.

How to share agent skills across repos

To share agent skills across repos, no dey copy the file again and again. Instead, make other repos depend on am. Keep one skills repository, tag am, and make each project pin one tag. Then add one smoke test for each skill, and review every version bump the same way you review dependency bump.

That one get four parts: one shared source of truth, one pinned version for each repository, one smoke test for each skill, and one review process. Everything below explain why each part dey exist, wetin the tools wey ship for 2026 do about am, and how to build the complete setup for self-hosted git remote without any outside service.

An agent skill na folder wey hold one SKILL.md file, plus any scripts and reference files wey e need. If that unit dey new, first read wetin be agent skill and how SKILL.md dey work. This page na about the supply chain around that unit.

Where skill dey live, and why sharing am hard

Claude Code dey load skills from three places, and the skills documentation name each path.

  • ~/.claude/skills/<skill-name>/SKILL.md na personal. E dey load for all your projects, but e no dey load for anybody else.
  • .claude/skills/<skill-name>/SKILL.md na project level. E dey load for anybody wey checkout that repository.
  • <plugin>/skills/<skill-name>/SKILL.md dey inside plugin. E dey load anywhere wey that plugin dey enabled.

The middle one na the useful option for team, because e dey committed and everybody wey clone the repo go get am. Na there wahala start too. Skill wey dey inside .claude/skills/ belong to one repository. You get eight repositories. So dem go copy the skill eight times.

The frontmatter no fit help. Agent Skills spec allow six keys, and the distribution paths wey enforce am dey print the list when you use another one:

Unexpected key(s) in SKILL.md frontmatter: argument-hint. Allowed properties are: allowed-tools, compatibility, description, license, metadata, name

Notice wetin no dey there: no version key dey. Nothing inside the file record which copy dey newer. This one make sense, because skill na document, no be package. But e mean say versioning must come from the layer around the file, and na you go manage that layer.

Problem one: eight copies wey dey quietly drift

Copy-paste dey work for day one. By day sixty, e don fail. Person fix one wrong instruction for payments repo but no touch the other seven. Another person add pagination rule for orders. Now the same skill name dey give two different reviews, depending on which directory the agent start from, and neither developer know.

The failure dey silent because no error state dey. Skill na prose. Stale instruction fit produce confident but wrong answer, and na this kind answer dey cost pass. Nothing for the agent dey compare your copy with other people own, so the only signal na when person notice say two repos no agree.

Problem two: no version dey pinned

Even when team keep skills for one place, the normal sharing method na copy step: setup script, one curl line for onboarding doc, or shell alias wey sync one folder. All of dem install anything wey dey at the head of the branch at that time.

This mean two developers fit dey use the same commit for the same application but different instructions, because dem run the sync on different days. E also mean say after bad agent run, you no fit answer the important question: which version of the skill produce this? If no revision dey recorded, you no fit reproduce the run, so the bug report no actionable.

Problem three: nobody know whether the skill still dey work

Skill no get compiler. Na instructions wey dem aim at model, so e fit stop to work while the file remain exactly the same byte for byte. Model upgrade fit change how well e dey follow long instruction. Command line tool wey the skill dey call fit rename a flag. URL for reference file fit start return 404, and agent go work from the error page.

None of these cases go fail loudly. Agent go still answer. Na just say the answer don worse pass how e be last month, and na hard thing to notice one pull request at a time.

Wetin di tools wey release for 2026 dey solve

Several answers dey land now, and dem no agree on where di version suppose dey.

Lockfiles. Di skills command line tool from Vercel Labs (vercel-labs/skills, MIT licensed, v1.5.22 as of 5 August 2026) dey install skills from git repository go any directory wey your agent expect, and e sabi di layout for more than seventy agents. npx skills add <repo> dey install, npx skills update dey upgrade, and npx skills list dey show wetin you get. Di record of wetin dey installed dey kept once per user instead of once per repository, and one open request for that project (issue 283) dey ask for skills install command wey go reinstall every tracked skill from di lock file, so second machine go end up with di same set. Take that request as status report. Di lockfile idea don settle. Di per-project part still dey build.

Specs and tests. SkillSpec dey take di other angle. E dey treat SKILL.md as contract wey you fit check, instead of prose wey you suppose trust, with di stated goal to make skills "followable, testable, and provable". skillspec doctor <path> dey report where agent likely go lose di thread. skillspec boundary map <path> dey report wetin di skill fit reach, and skillspec boundary assess <path> dey rank those findings by risk. Na Rust crate, e get dual license MIT or Apache 2.0, and version 0.2.2 as of 29 July 2026. Install di pinned version instead of di newest one:

cargo install skillspec --version 0.2.2 --locked
skillspec --version

--locked dey build with di dependency versions wey dem publish di crate with, so build no go drift underneath you. skillspec --version suppose print 0.2.2. If e show different number, e mean say older binary earlier for your PATH dey win.

Vendor practice. Google describe how e dey build di skills for google/skills inside one post about how e dey build, test and scale agent skills. If you remove di scale, di mechanism na ordinary continuous integration (CI). Every skill dey pass linters for frontmatter metadata, line count, directory layout, and naming before e merge. Link checker dey fail di build for any URL wey return 404, and this dey catch plausible link wey agent invent. Authors must provide evaluation prompt suite and scoring rubric together with di skill. Scheduled evaluation jobs dey run every week against di whole library to catch regressions, and every skill get named owner wey suppose fix am when quality drop.

The pattern under all three answers

You no need pick any of dem. Underneath dem, one single shape dey, and plain git give you everything wey you need.

  1. One source of truth. The skill get exactly one home, and every repository refer to that home instead of keeping copy.
  2. One pinned version for each repository. Every project record the exact revision wey e dey use, so upgrade na commit for that project with author and date.
  3. One smoke test for each skill. Na one runnable check wey prove say the skill still dey produce the result wey e promise.
  4. One review path. Change to shared skill go through review, and every consumer go see diff before e take am.

Na this be the shape of dependency. Skills become shared artifact faster than tooling grow around dem, so the tooling wey you already trust na the safest one to use.

Layout wey small team fit use for self-hosted git remote

One repository go hold the skills. Nothing else go dey inside am, so the history go read like changelog of instructions.

agent-skills/
  skills/
    api-review/
      SKILL.md
    release-notes/
      SKILL.md
  tests/
    api-review.sh
    release-notes.sh
  CHANGELOG.md

Releases na tags. Use annotated tags, because dem carry message and date. Write the message as the reason wey consumer go want make the version increase:

git tag -a v1.4.0 -m "api-review: require pagination on list endpoints"
git push origin v1.4.0

If your remote na Gitea, Forgejo, GitLab, or bare repository over SSH for your own VPS, nothing for wetin follow go change. Everything here na git plus symlink.

Pinning with a git submodule

Submodule dey record one exact commit from another repository inside your repository. Na that record be the pin. For each project wey dey use am:

git submodule add https://git.example.com/team/agent-skills.git vendor/agent-skills
git -C vendor/agent-skills fetch --tags
git -C vendor/agent-skills checkout v1.4.0
mkdir -p .claude/skills
ln -s ../../vendor/agent-skills/skills/api-review .claude/skills/api-review
git add .gitmodules vendor/agent-skills .claude/skills/api-review
git commit -m "Pin shared agent skills to v1.4.0"

The symlink na the part wey make this arrangement work. Skill entry for project level fit be symlink to directory for another place for disk, and Claude Code go follow am and read SKILL.md from the target. So the skill go load like normal project skill, while the bytes dey inside the submodule for the commit wey you choose.

Check the pin:

git submodule status

Healthy line dey start with one space, then the commit, then the path, then the nearest tag:

 4d1a7c2f0b93e5a1c8d6f2b40e7a95c3d1f8b602 vendor/agent-skills (v1.4.0)

Leading - mean say dem never initialise the submodule, so .claude/skills/api-review dey point to nothing and the skill no go load without any clear error. Fix am with git submodule update --init. Leading + mean say the checked-out commit different from the one wey dem record, so that developer dey run instructions wey nobody else get. New clones need git clone --recurse-submodules, and that line suppose dey inside the README, because plain clone go leave vendor/agent-skills empty and e no go print error.

Upgrade na deliberate action, and na the main reason for this setup:

git -C vendor/agent-skills fetch --tags
git -C vendor/agent-skills diff v1.4.0 v1.5.0 -- skills/
git -C vendor/agent-skills checkout v1.5.0
git add vendor/agent-skills
git commit -m "Bump shared agent skills to v1.5.0"

The diff line na the review path. E show the same change wey every other consuming repo go see, and e fit enter one pull request.

Pinning with a plugin marketplace instead

If you no wan ask every developer to learn submodules, Claude Code plugin system go handle the distribution for you, and e dey work with a self-hosted remote. Put catalog for .claude-plugin/marketplace.json inside the skills repository:

{
  "name": "acme-agents",
  "owner": { "name": "Platform team", "email": "platform@example.com" },
  "plugins": [
    {
      "name": "team-skills",
      "description": "Shared review and release skills",
      "version": "1.4.0",
      "source": {
        "source": "url",
        "url": "https://git.example.com/team/agent-skills.git",
        "ref": "v1.4.0",
        "sha": "4d1a7c2f0b93e5a1c8d6f2b40e7a95c3d1f8b602"
      }
    }
  ]
}

Two different sources dey involved here, and na common mistake to mix dem up. Marketplace source, meaning where the catalog itself dey fetched from, accepts ref for branch or tag, but e no accept sha. Plugin source inside the catalog accepts both, and when you set both, sha na the pin wey actually apply. So exact-commit pin suppose dey for the catalog entry.

Each repository wey dey use am then declare the marketplace inside the committed .claude/settings.json:

{
  "extraKnownMarketplaces": {
    "acme-agents": {
      "source": {
        "source": "url",
        "url": "https://git.example.com/team/agent-skills.git",
        "ref": "v1.4.0"
      }
    }
  },
  "enabledPlugins": {
    "team-skills@acme-agents": true
  }
}

Teammate wey trust the project folder go see prompt to install the marketplace, and the plugin go enable for dem without any wiki page telling dem to do am. The skills then dey answer to /team-skills:api-review, because plugin skills get namespace based on plugin name and dem no fit clash with project skill wey get the same name. After you push new tag, consumers refresh with /plugin marketplace update acme-agents, then run /reload-plugins if the install summary ask for am.

Writing one skill for smoke test

Smoke test na be scripted agent run against fixture wey get known fault, plus one assertion. Claude Code dey run non-interactively with -p, and skill wey user invoke dey work there: put /skill-name inside the prompt string, and e go expand before the run start.

#!/usr/bin/env bash
set -euo pipefail

claude -p "/api-review Read fixtures/orders-api.md and list the rule ids it breaks." \
  --allowedTools "Read" \
  --output-format json \
  --json-schema '{"type":"object","properties":{"rule_ids":{"type":"array","items":{"type":"string"}}},"required":["rule_ids"]}' \
  | jq -e '.structured_output.rule_ids | index("pagination-required")' > /dev/null

fixtures/orders-api.md na short file wey get one deliberate fault. The assertion na say skill go name the fault. jq -e go exit non-zero when its filter produce null, so any skill wey stop catching the seeded fault go fail the script. claude itself go exit non-zero when the run fail, and set -euo pipefail go turn either failure into failed test.

Model fit reword its answers between runs, so never assert on complete sentence. Assert on identifier wey the skill suppose emit, or on field for schema wey you request, and keep the fixture small so the run no cost much.

For CI, add --bare. Without am, claude -p go load the same context wey interactive session for load, including hooks, plugins, and CLAUDE.md from the machine wey e dey run on. This mean say teammate personal configuration fit change the result. Bare mode dey skip all auto-discovery, so e also skip the skill wey you dey test. Load that one explicitly. Bare mode no dey read your subscription login too, so set ANTHROPIC_API_KEY for the environment first:

claude --bare -p "/team-skills:api-review Read fixtures/orders-api.md and list the rule ids it breaks." \
  --plugin-dir vendor/agent-skills \
  --allowedTools "Read" \
  --output-format json

With --output-format stream-json, the first event for the run go report which plugins load, and e go carry plugin_errors array for the ones wey no load. Make CI job fail when plugin_errors no empty. This go catch pin wey point to revision wey no longer exist. Without this check, agent fit just ignore your house rules quietly.

Shared skill na executable instruction

Two features dey make that statement literal, and both matter when file come from another team.

First, a SKILL.md fit run shell commands before model read anything. A line like this for the body na preprocessing:

- Current branch: !`git rev-parse --abbrev-ref HEAD`

Command go run for the machine wey dey load the skill, and e output go replace the placeholder for the text wey model receive. A fenced block wey open with three backticks followed by ! go run several commands the same way. Nobody approve any of this when e dey run. To read shared skill mean say you dey read the command substitutions inside am.

Second, frontmatter fit pre-approve tools. allowed-tools dey grant the listed tools without permission prompt for the turn wey invoke the skill. For project skill, that grant go take effect once person accept the workspace trust dialog for the folder. Claude Code documentation talk the consequence clearly: review project skills before you trust repository, because skill fit grant itself broad tool access.

So handle skill bump exactly like dependency bump. Pin am with exact commit wherever the mechanism allow am, because person fit move tag and branch dey move by definition. For locked-down machine, "disableSkillShellExecution": true for settings dey replace every command substitution with literal text [shell command execution disabled by policy] instead of running am, and when managed settings apply am, user no fit override am. Bundled and managed skills no dey affected by that setting.

The same care apply to wetin skill read. Skill wey run env or open config file dey pull anything wey e find enter model context. Na this be the failure wey how to keep secrets out of the agents you run cover. Skill wey fetch page or run query na the same exposure wey point outward, because retrieved text land for context and look exactly like instructions wey you write. Na boundary wey worth reading about before you point agent at your own SearXNG instance for web search.

Wetin to read when version change

  • The diff of every SKILL.md body, because na that text your agent go follow as instruction.
  • Every command substitution, because dem dey run for your machine when the skill load.
  • Any change to allowed-tools, because that line dey grant tools without prompt.
  • The test run behind the tag. If the shared repository dey run its own smoke tests for CI, the tag wey you dey pin to suppose get green run attached.

If reviewer no fit read the whole diff within ten minutes, e dey look at skill wey don grow too big. Split am. The same thing apply to repository documents wey your agents dey read: keep durable rules for the files wey dem describe for the AGENTS.md and HUMAN.md split, and keep architectural reasoning for a DESIGN.md written for agents, while skills remain narrow procedures.

When model or tool change break skill

Plenty things fit change underneath skill without anybody edit am. Model upgrade fit change how well e dey follow long instruction. Because of that, skill wey depend on model to reach step nine fit stop before e reach there. Command line tool fit rename flag. Then agent go run old flag, read error, and improvise. Referenced URL fit start return 404. Agent harness fit change how e dey choose skills. So a description wey dey win the match before fit stop to win am.

Na why smoke test dey carry the main weight for this arrangement. Run each skill test on schedule and after push too. Google dey run evaluation jobs every week against the whole library for this reason. Weekly cron job for small VPS dey enough for team wey get ten skills. Na only this way you go hear about the breakage before developer notice am.

Portability dey help too. Agent Skills spec keep frontmatter to six keys. So skill wey follow that spec fit load for tools beyond the one wey you write am for. But every harness-specific key wey you add na bet on one vendor. Writing skills wey fit survive model swap na separate discipline. making skill work for any model cover am.

FAQ

How I fit share one agent skill across plenty repositories?

Put the skill for one dedicated git repository, tag releases for there, and make each project wey dey use am reference a tag instead of copying the file. Two mechanisms dey work. A git submodule records exact commit, and symlink from .claude/skills/<name> enter the submodule make e load like normal project skill. A plugin marketplace do the same work through /plugin, with the pin declared for the repository wey dey use am inside .claude/settings.json. Both put the version for git history, so you fit answer which instructions produce one particular agent run.

I fit pin agent skill to specific version?

No be from inside SKILL.md, because that frontmatter no get version key. The layer around the file must provide the pin. A git submodule dey pin exact commit by design. For Claude Code plugin marketplace, plugin source accept ref for branch or tag and sha for exact commit, and sha dey win when both dey present. The marketplace source itself accept ref only. Prefer commit pin, because person fit move tag after you don review am.

Wetin skill smoke test suppose assert?

Assert on something wey stable. Run the skill non-interactively against fixture wey get known fault, then check say specific identifier appear for the output, like rule id wey the skill suppose report. Requesting structured output with --output-format json and --json-schema make the check exact, and jq -e make script fail when the value no dey. Never assert on full sentence, because model fit reword the answer between runs.

E safe to install shared skill from another team repository?

Treat am like code dependency, because na executable instruction. A SKILL.md fit run shell commands when e load through ! command substitution form, and frontmatter allowed-tools field fit pre-approve tools without prompt. Read the diff for every bump, pin to exact commit instead of branch, and prefer source wey your own team control. For managed machines, "disableSkillShellExecution": true for settings stop command substitutions from running at all.

Shared skill go work for agents wey no be Claude Code?

E depend on the frontmatter wey you use. Agent Skills spec define six keys: name, description, license, compatibility, metadata and allowed-tools. Skill wey use only those keys go load across tools wey implement the spec, and e go also load for Claude Code without changes. Harness-specific keys and body features beyond the spec dey ignored or rejected elsewhere, so keep dem out of any skill wey you plan to share widely.

#agent-skills#versioning#claude-code#team-standards#self-hosting