skillforge: Import Your Agent Skills Instead of Copying Them

mds everywhere...

"TOoling"

I spend most of my day in coding agents, and every repo I touch now has a .claude/skills/ folder. Open a few of them side by side and they're mostly the same files. Same explainer skill, same review checklist, same "write docs like this" rules. The only differences are the bits that actually matter to that repo: the test command, the languages in use, the one rule the team argued about once.

The drift

A skill is usually 90% general and 10% specific to your repo. Here's how that goes:

  • You write a good skill in one repo. It works, so you copy it into the next one.
  • You tweak the copy. Different test command, a line about your monorepo layout. Now there are two versions.
  • You fix a real bug in the original. The fix reaches nobody. Repo C is still on v1 and will be forever.
  • You use more than one agent. Claude Code reads .claude/skills/, Codex and Gemini CLI read AGENTS.md, Copilot wants .github/instructions/, Cursor wants .cursor/rules/. Four hand-maintained copies of every skill, per repo.

Copying works for about a week. After that every copy drifts, and you can't tell which differences were on purpose and which were just neglect.

skillforge

skillforge is a library of portable agent skills plus a build tool that composes them into other repos. Skills are written once in the open Agent Skills format. Consumers don't fork them. They declare what they want in a skillforge.yaml and patch only the 10%.

skills:
  - from: lib/eli5
    params:
      audience: a new hire on their first day
      max_words: 300
    patches:
      - point: after-intro
        op: insert
        content: "> Assume the reader has seen our architecture diagram and nothing else."

targets:
  claude-code: {}
  agents-md: {}
uvx --from git+https://github.com/ya222/skillforge skillforge build

The design choice that makes this work is that the rendered output is committed. Everything clever happens at build time, and what lands on disk is a plain SKILL.md. Anyone who clones the repo gets working skills without installing anything, and a change to a skill shows up as a diff you can review.

What it actually handles

  • Params. A base skill leaves blanks like {{ params.max_words }} and you fill them with values. Values only, never logic.
  • Anchors. The author marks the spots you're allowed to change: a block you can replace, or a point you can insert at. Try to patch anything else and the build refuses, naming the anchors that do exist.
  • Skills you don't control. You can patch by heading path instead, but every heading patch has to pin the target section's content hash. If upstream edits that section, the build fails loudly instead of patching the wrong place.
  • Layers. An org config, then a team config, then the project, each one extends-ing the last. If two layers patch the same thing, the build fails until the later one writes force: true, so every override is on record as deliberate.
  • Every harness. Adapters for Claude Code, AGENTS.md (Codex, Gemini CLI, opencode), Copilot and Cursor. They copy, never symlink.
  • Drift checks. skillforge.lock records a hash of every generated file and the exact upstream commit. skillforge check rebuilds in memory and compares, and it runs in the pre-commit hook, so if someone hand-edits generated output it gets caught before it lands.
  • An escape hatch. skillforge eject copies a skill into your repo and cuts the link. A deliberate, visible exit, not a slow drift.

Composition, not templating, on purpose

The obvious version of this is Jinja inside SKILL.md. I didn't want that. Full templating makes the base unreadable as a skill, invites logic into prose, and has no natural stopping point. skillforge is Kustomize-shaped instead: a plain base, plus overlays that declare operations. Params are values, anchors are structure, and the two never mix.

The other rule is that nothing degrades quietly. A missing anchor, an unknown param, a drifted heading or an absent ref stops the build with an error naming the file, the skill and the target. A silently skipped patch is worse than a failed build, because the skill still looks right.

Agents building agent tooling

skillforge was built with coding agents: Fable 5 for most of the design and Opus 5.5 for most of the implementation. The repo also builds its own skills with its own tool, so its root skillforge.yaml isn't a test fixture. When the tool is awkward, that's where I feel it first. The "how it works in five pictures" section of the README was written by the library's own eli12 skill.

Where this really pays off: one library, every project

Set claude-code: { user: true } in a config kept in your dotfiles and skillforge writes to ~/.claude/skills/, so every project on your machine picks the skills up. That folder is also where you keep skills you wrote by hand, which is why the ownership rule is so blunt: every rendered skill is prefixed sf-, and skillforge only creates, rewrites or prunes sf- entries. Naming what it owns turned out to be simpler than tracking it, and it means a build can't wipe your own skills.

The library currently ships 15 skills, including eli5 and eli12 explainers, dev-style for Google-style developer docs, grill-me and handoff for planning and context hand-offs, isometric-system-map, architecture-designer and architect-review, markdown-kanban boards, cloudflare-quick-tunnel, Claude Code session limits and session export, and an Obsidian vault skill. Fix one upstream and every repo gets it on the next skillforge update.

Have a go

It's Python, run straight from git with uv. There's no registry, no publish step and no install.

uvx --from git+https://github.com/ya222/skillforge skillforge init     # starter skillforge.yaml
uvx --from git+https://github.com/ya222/skillforge skillforge build    # render and write the lockfile
uvx --from git+https://github.com/ya222/skillforge skillforge check    # fail if anything drifted
uvx --from git+https://github.com/ya222/skillforge skillforge update   # pull upstream and rebuild
GitHub - ya222/skillforge: Portable agent skills, composed per repo

GitHub - ya222/skillforge: Portable agent skills, composed per repo

Portable agent skills, composed per repo. Contribute to ya222/skillforge development by creating an account on GitHub.

Reach out, let me know what you think.