Skills, For Real
I called them skills. The runtime never did. Three iterations, one cutover commit, and 46 markdown fragments finally became something a fresh agent could actually discover.
I — The folder that lied to me
For months, my repo had a folder it called a skills folder.
It looked like a skill library. It read like a skill library. It even shipped four production Marketplace apps.
There was just one problem.
Nothing in it was actually a skill.
No runtime auto-discovered any of it. The filenames were wrong. The metadata fields were wrong. The location was wrong. Every single file violated the agentskills.io spec — quietly, invisibly, and 46 times in a row.
The illusion held because this repo's commands knew exactly where to look. The day I tried installing the same files in a fresh agent session elsewhere, the trick collapsed: empty available-skills listing. Skill tool refusing to invoke. Four shipped apps' worth of knowledge, structurally dead.
II — The bake-off
Three attempts. Two screenshots. One survivor.
The lesson hiding inside the bake-off: when the loader refuses to give you nested folders, the prefix sort is the directory hierarchy.
III — The before / after
called “skills”
auto-discoverable
(per project snapshot)
is canonical?
in one plugin
(content-sdk · marketplace-sdk · blok · sitecoreai · setup)
per consumer
copies
IV — The cutover
Half-migrated is worse than not migrated. So the move was atomic.
V — The proof
Three throwaway reruns, the same week. Full pipeline, fresh scaffolds, no lifelines.
against the plugin
invocations
failures
patches captured
The friction loop finally compounded the right way. A patch from PageShot v1 landed in the published Agent skill. PageShot v2 picked it up automatically. No copy-paste. No re-discovery. The first build paid for the second.
VI — The takeaways
If it doesn’t announce itself, it’s not a skill.
Open a fresh session. Look at the available-skills listing. If your file isn’t there, it’s domain knowledge in costume — no matter how skill-shaped the markdown reads.
Naming is the architecture.
Flat loaders turn the prefix sort into the directory hierarchy. A long, domain-prefixed name isn’t verbose — it’s self-organising.
Whiteboards lie. CLI listings don’t.
Two of three packaging shapes looked right on paper. Both died the moment a real install + a real listing happened. The screenshot is the spec.
Migrate atomically — or don’t.
One commit. Every consumer rewired, the old source tree deleted, and the wrapper sync re-run together. The worst possible state is half-migrated and nothing failing loudly.
One channel strands half your audience.
The Claude Code plugin reaches this repo’s agents. The CLI installer reaches Cursor, Codex, Cline, and Gemini CLI. Dual-channel makes the same skill file portable everywhere with zero duplication.
Move the patch surface. Watch it compound.
Before: every patch copy-pasted into per-project snapshots that started rotting on contact. After: patches accrue in one published plugin, and every future install gets them for free.
Related case studies