Beskar
Managing agent skills across projects without copy-paste
Every coding agent today has some notion of "skills": folders of instructions, prompts, scripts, and reference assets that teach the agent how to work in a specific way. They are genuinely useful — and genuinely unmanageable. This is the story of how my skills ended up in six divergent copies across repositories, and what replaced the treadmill.
The problem: skills drift
The failure mode is familiar to anyone who has maintained dotfiles across machines. You write a skill for one project, it works, and the next project needs "the same thing, slightly different." You copy the folder. You tweak it. Three months later, the copy in project A has a fix that B and C never got, C has a rewrite that A would break on, and nobody knows which one is authoritative.
With agents this is worse than with dotfiles, because the drift is invisible: a stale skill does not error out. It silently produces worse agent behavior, and you debug your prompts for an afternoon before realizing the agent is reading a months-old instruction set.
- No source of truth. The "best" version lives wherever you last fixed something.
- No review step. Copying a folder into a workspace overwrites whatever was there, including local edits.
- No composition. Every project reimplements its combination of skills, prompts, and tools.
The requirements that fell out
Before writing code, I wrote down what "solved" means, and the list turned out to be short:
- One library, curated, versioned by git like any other source.
- Named profiles: project A composes skills differently than project B, from the same library.
- Deploy by copy into the formats each agent framework expects — no daemon, no server, no path magic.
- A change-tracking step that tells me exactly what differs between the library and the workspace before I overwrite anything.
- Offline-first. Skills are local assets; managing them should not require network round-trips.
Alternatives I rejected
Git submodules. The obvious candidate, and the first one out. Submodules pin one revision for the whole tree, per repository — but the unit I needed was per skill, per project. And every agent framework expects skills in its own directory format, so a raw checkout does not land where agents read from.
A shared dotfiles-style repo with symlinks. Symlinks break on Windows, confuse some file watchers, and make "what does the agent actually read" dependent on filesystem topology. Copy-deployment is dumber and survives everywhere.
Per-agent registries. Some frameworks ship their own skill marketplaces. Locking my skill library to one agent's registry format recreates the original problem one level up — I would be copy-pasting between registries instead of between projects.
What Beskar actually does
Beskar is a Rust CLI that implements the five requirements above, and not much else:
# Initialize the library (a git-tracked directory)
beskar init
# Add a skill to the library
beskar library add ./my-skill
# Compose a profile for this kind of work
beskar profile create coding my-skill
# Register a workspace and deploy
beskar repo add .
beskar repo enable coding
The library is a plain directory with a manifest per skill — curated by hand, versioned by git, portable by being boring. Profiles are named sets of skills; a workspace enables one profile at a time. Deployment copies skills into the workspace in the layout the target framework expects.
Why fingerprints instead of version numbers
The interesting design decision was change tracking. The naive approach — semantic versions per skill — fails immediately in practice, because skills get edited in place inside workspaces, and those edits are valuable work, not noise. Version numbers cannot tell you what changed, only that something did.
Beskar fingerprints every deployed skill — content-derived hashes over the skill's files and metadata — and compares workspace fingerprints against the library's. The status command answers the real question: is this workspace copy identical, locally modified, or stale relative to the library? Updating becomes a review step, not a blind overwrite.
Versioning tells you a skill changed. Fingerprints tell you whether yours did.
Failures and lessons
Failure: trying to sync instead of copy. An early design synced library state into workspaces automatically. It felt clever and made local edits terrifying — the sync could clobber a fix made five minutes ago. Deploy-on-command with fingerprint review is more manual and strictly safer.
Failure: one global profile. The first implementation had no profiles, just "the library." Within two weeks I needed different skill sets for different kinds of repos. Profiles were the smallest change that fixed it.
Lesson: boring deployment wins. Every clever mechanism — symlinks, sync daemons, import hooks — failed someplace. Copying files, recording fingerprints, and letting git version the library has failed nowhere yet.
Lesson: agent-agnostic is a requirement, not a feature. The library must outlive any single framework. Skills are assets; deployment formats are details.
Where this goes
Beskar is open source and in daily use here. The roadmap is deliberately short: more deployment targets, better diff output for the review step, and profile inheritance for the "same but slightly different" cases that started all of this.
If you want the usage documentation — install, commands, file formats — that lives on the Beskar site, deliberately not duplicated here.