Dev.to AI 🤖 Ai 👁 0 📖 3 min read

Your AI agent skills are an unversioned dependency

Your AI agent skills are an unversioned dependency A skill is a prompt that lands in a model's system context. Most teams install them the way we installed libraries in 2009: clone a repo, copy a folder, hope nobody to

Your AI agent skills are an unversioned dependency

A skill is a prompt that lands in a model's system context. Most teams install
them the way we installed libraries in 2009: clone a repo, copy a folder, hope
nobody touches it. Then the folder drifts and the agent quietly loads something
nobody reviewed.

I maintain Skillporter, a package manager for AI agent skills. This is the design
problem behind it, not a feature tour.

The real problem is paths, not prompts

Every harness reads skills from a different directory:

Claude Code        .claude/skills
OpenAI Codex       .agents/skills
Cursor             .agents/skills
GitHub Copilot     .github/skills
Windsurf           .windsurf/skills
Cline              .cline/skills
OpenCode           .opencode/skills
Hermes Agent       $HERMES_HOME/skills

Eight harnesses share .agents/skills as their primary project path, and six more
read it as a documented compatibility path. That directory is the trap. Remove a
skill to clean up Cursor and you have just broken Codex, Gemini CLI, Zed, OpenHands
and Goose for the rest of the team.

Two other approaches fail in predictable ways. Symlinks break inside Docker
builds, git worktrees and Windows checkouts. Copy scripts drift, because nothing
records what the copy was supposed to be.

Treat the skill as a dependency

The package manager model maps cleanly:

  • a manifest you commit, listing skills and target harnesses
  • a resolution step that fetches sources and validates structure
  • a static scan before anything is written
  • one install per harness path, with shared paths written once
  • a lockfile with a content hash per skill
  • snapshots, so rollback is possible after a bad upstream change

    uvx skillporter add anthropics/skills --skill pdf --harness all

Real output from a clean workspace:

+ Installed pdf across 19 harness(es) (+12 created, ~0 updated, =7 deduplicated/unchanged)
  + Claude Code          created    (copy via .claude/skills)
  + GitHub Copilot       created    (copy via .github/skills)
  + Hermes Agent         created    (copy via .hermes/skills)

Twelve directories, seven shared paths deduplicated. That tally is the whole
argument for a resolver: a copy script would have written nineteen copies and
called it success.

Drift is the thing worth detecting

Once a skill is pinned, the interesting question stops being what is installed and
becomes what changed.

skillporter sync          # reconcile workspace with manifest, write the lock
skillporter lock --check  # exit 1 on drift, exit 2 if the check could not run
skillporter outdated      # compare version, commit and tree hash upstream
skillporter rollback pdf  # restore the last snapshot

The exit code split matters more than it looks. A pipeline needs to distinguish a
failed check from a check that never ran, otherwise a broken tool reads as a pass.

Skills are a supply chain input, so be honest about scanning

A static scanner finds known dangerous patterns: curl piped to shell, base64
payloads, credential reads, risky permission requests. It reports finding codes
and a risk score, and it never executes skill code during install.

What it cannot do is catch novel prompt injection written in ordinary prose. A URL
can serve harmless content when inspected and something else when the agent fetches
it later. If a vendor tells you their scanner proves a skill is safe at runtime,
they are selling you certainty they do not have. The docs for this one say so
explicitly, which is the main reason I trust the rest of them.

Read-only by default when a model is the caller

The MCP mode is worth a paragraph. An MCP server is designed to be called by a
model, which means its arguments may be hostile. So the server exposes detect,
diagnose, scan, inspect and matrix, and denies add, install, sync and remove unless
started with --allow-writes. The workspace root comes from a flag or an environment
variable, not from tool arguments, and traversal, escaping symlinks and UNC paths
are rejected.

What this is not

Not a marketplace. Not a sandbox. It does not run skills, and it cannot tell you
what a skill will do when a model follows it. What it does is make the set of
skills deterministic, visible and reversible.

Status, honestly

v3.2.0, MIT, Python 3.9+, zero runtime dependencies, single maintainer. Nineteen
adapters, of which 1 is runtime verified, 3 are integration tested and 15 are
fixture tested. The docs state the tier per harness because pretending otherwise
would be the fastest way to lose the trust of the people who hit the bugs.

Install, if you want to try it in a throwaway repo:

uvx skillporter demo
uvx skillporter diagnose .

Site: https://skillporter.dev

Repo: https://github.com/Shanmukh-l33t/skillporter

If a harness path is wrong on your machine, that is the bug report I want most.

📰 Read the original article on Dev.to AI

Originally published by Dev.to AI. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.