From Authored Folders to a Verifiable Registry

For Tech Leads Club's Agent Skills repository, the registry is the boundary between human-maintained expertise and machine-mediated delivery. The question here is what the registry adds to an ordinary directory tree, and how its file list and aggregate hash help runtime tools retrieve a bounded, identifiable package. The answer explains both the repository's strength and its limit: a registry can make a payload correspond to a description without making the advice inside that payload automatically correct.

A directory tree is readable; a registry is addressable

A human maintainer can browse a category folder, open a skill's SKILL.md, and follow its references. A CLI or MCP server needs a more explicit contract. It needs to know which names are valid, which category a skill belongs to, where its files sit in the published package, which files are part of the skill, and whether a requested name has been deprecated. Walking arbitrary folders at runtime would make every consumer responsible for reproducing the catalog's interpretation. The generated registry centralizes that interpretation.

The generator scans the skills catalog, looking for category directories and skill directories that contain the required main instruction file. It parses the frontmatter, assigns the category and relative publication path, gathers the skill's files recursively, and records the result as a registry entry. The entry carries the name and description used by discovery, the relative path used for retrieval, the complete file list used for bounded access, and optional author and version metadata. Category metadata gives the marketplace and runtime tools a shared vocabulary, while deprecation entries give the update path a way to explain that an old name should no longer be used.

This is not valuable because JSON is inherently better than folders. It is valuable because the registry is a shared point of interpretation. The CLI can ask which remote skills exist without downloading every skill. The MCP server can build a search index from descriptions and triggers without opening each supporting file. A marketplace can render listings and detail pages from the same catalog data. Each consumer gets a consistent identity model instead of making a private guess about what a folder means.

The registry also preserves a distinction that is easy to lose in a casual file-based system: the index is not the payload. A description can tell a user that a skill covers accessibility or architecture, but the description is not the skill's complete working material. The file list says what else belongs to the package. That lets a runtime consumer expose the main instructions first and retrieve a specific reference later, while still knowing that the reference is part of the same published object.

The generation step therefore performs several transformations at once. It converts author-facing names and frontmatter into runtime metadata. It converts a nested file tree into a relative list. It converts category folders into stable category identifiers. It turns deprecation notes into machine-readable migration information. It also normalizes names that do not fit the catalog's slug convention, and the current implementation can write that corrected name back into the source SKILL.md. That last behavior matters: registry generation is a publication step with a source-tree side effect, not merely a read-only report.

The generator's rules also define what does not become a published skill. A directory without the required main file is not treated as a complete entry. Hidden or explicitly ignored files do not silently expand the package's identity. A category folder contributes its identifier and metadata, while a skill at the catalog root can be treated as uncategorized. These choices keep the runtime contract narrower than “everything that happens to be somewhere below the repository,” which is essential when consumers later use the file list as an allowlist.

For maintainers, that makes generation a point where content structure becomes operational behavior. A misplaced file can be absent from the registry. A description parsed incorrectly can change discovery without changing the main instructions. A name normalized during generation can affect the address users search for. The generator is therefore part of the system's interface, and its output deserves the same attention as the skill prose it summarizes.

That also explains why the repository keeps the generated registry beside the published skill files rather than asking each client to reconstruct it. The registry is a compact, inspectable summary of the package; the files remain the authoritative material to retrieve and verify. Keeping those two outputs connected lets a client fail when they disagree instead of silently choosing whichever view is easiest to parse.

The complete flow is easier to see when the registry and the runtime consumer are treated as participants in one lifecycle.

sequenceDiagram participant A as Authored catalog participant G as Registry generator participant R as Published registry participant C as Runtime client participant F as Published files A->>G: Scan skill folders and frontmatter G->>G: Collect files and compute content hash G->>R: Write identity, file list, metadata, and hash C->>R: Resolve a named skill R-->>C: Return path, files, and expected hash C->>F: Fetch the listed files F-->>C: Return file bytes C->>C: Recompute aggregate hash C-->>C: Accept matching payload or reject mismatch

The sequence shows why a generated registry is more than a convenience for browsing. It is the object that tells the runtime client what to fetch and what successful verification means. Without it, a client could fetch a file named SKILL.md, but it would have no authoritative answer about whether a reference file belonged to the same skill or whether a newly added script should be included in the integrity check.

The hash binds the description to the complete package

The repository computes each skill's contentHash from its complete file set. It sorts the relative paths, then feeds each path and the corresponding file bytes into a SHA-256 calculation. The same basic algorithm is implemented in the runtime consumers. This detail is important because hashing only the main instruction file would leave the supporting material outside the identity check. A reference or script could change while the visible SKILL.md remained identical, and a consumer would have no way to tell that the package had changed.

By including paths as well as bytes, the hash captures two kinds of change. Editing a file changes the bytes. Adding, removing, or renaming a bundled file changes the set of path inputs. A registry entry thus identifies a particular arrangement of content, not merely a text blob. When the client downloads the listed files and computes the same result, a match supports a precise claim: the bytes it received correspond to the file set and hash that the registry advertised.

This is why a reference file is not an informal appendix once it is bundled. Its path and bytes participate in the package identity, so changing the reference can legitimately trigger the same update logic as changing the main instructions.

That claim supports several useful operations. A client can decide whether a cached skill is current by comparing its recorded hash with the registry's hash. An MCP server can refuse to return instructions or stage references when the downloaded set does not match. An installer can record the hash associated with a local installation so an update command has a content identity to compare later. The same identity signal can therefore connect publication, retrieval, caching, and maintenance without making each consumer invent a different version test.

It also gives failure a useful shape. If a file download fails, the client knows that the package is incomplete rather than treating the main file as sufficient. If a reference is added to the published skill, the new path enters the sorted input and produces a different identity. If an old cached copy has the wrong recorded hash, the consumer can treat it as stale and refresh it. These outcomes are more informative than a simple timestamp because they refer to the package the user is actually about to read or install.

The hash does not answer every question that users may reasonably ask. A matching hash does not show that the author intended the content, that the recommendations are technically sound, or that a script is safe to run. It does not independently authenticate the publisher, prove that the registry was obtained through a trusted channel, or show that a third-party skill's license permits a particular reuse. It confirms correspondence between an expected byte set and a received byte set. Those are valuable but narrower claims than “the skill is safe.”

The registry itself remains part of the trust boundary. If an attacker or an accidental build error changes both the file list and the advertised hash in a registry that the client accepts, the client may verify a payload against a bad description and still report a match. The repository's later CDN pinning and integrity checks reduce some delivery risks, but they do not turn the generated metadata into an independently signed statement. The system is strongest when registry generation, publication, and retrieval are treated as linked responsibilities rather than when the hash is asked to carry all of them.

The file list also determines what a runtime client is allowed to retrieve. That is useful for containment: a client can reject a request for a path the registry does not declare instead of accepting arbitrary path construction. But it creates a dependency on generation quality. If an author forgets to include a needed reference in the package or the registry is stale, the client may faithfully refuse to fetch something the workflow requires. A bounded contract can fail safely while still being incomplete.

The same contract supports more than integrity checks. A search index can use the description and category without reading the full package. A marketplace can show a human-readable entry and its detail page from the generated data. An update tool can recognize that a deprecated or missing name needs attention instead of reporting an undifferentiated network error. These consumers do not need to agree on every user experience, but they do need to agree on the identity and boundaries of the skill they are presenting.

This is why deprecations and metadata belong in the same system. A name can remain recognizable to a user while no longer being the right entry to install. A category can help discovery without being a guarantee of technical compatibility. An author field can provide provenance without proving authority. The registry makes these distinctions available to clients, but each field still needs to be interpreted at its proper strength.

Publication is a control point, not a final verdict

The generated registry gives Agent Skills a stable intermediate language. Authors think in terms of workflow files and supporting evidence; clients think in terms of names, paths, file sets, hashes, and categories. The registry lets both sides meet without forcing the runtime to understand the entire repository layout.

It also creates a useful place to inspect change. A new reference changes the package's file set. A renamed skill changes its address and may trigger a source correction. A deprecation changes how update tooling should treat an installed name. A changed description can alter which tasks the search index considers relevant. These are not merely editorial edits once the content is distributed through an automated system; they can change routing, retrieval, or maintenance behavior.

But the registry remains a contract about delivery, not a verdict about meaning. The next problem is selection: once the system knows which skills exist and which files belong to them, how can it choose a plausible skill for a natural-language task without loading the entire catalog or treating a fuzzy match as permission to act?

References