Extraction Pipeline¶
Discovery, filtering, and naming. This is the stage that decides what becomes a skill and what it is called.
Discovery¶
The generator walks a documentation root and collects candidate files from a fixed set of category directories. Each category maps one-to-one onto a plugin in the published marketplace.
skillgen \
--source ../adaptive-enforcement-lab-com/docs \
--output plugins \
--plugin-metadata ./plugin-metadata.json \
--release-manifest ./.release-please-manifest.json \
--templates skillgen/templates
| Flag | Default | Purpose |
|---|---|---|
--source |
required | Documentation root to scan |
--output |
./plugins |
Where generated plugin trees are written |
--marketplace |
./.claude-plugin/marketplace.json |
Marketplace catalog path |
--templates |
./templates |
Directory of Go templates |
--plugin-metadata |
./plugin-metadata.json |
Plugin descriptions, tags, shared author fields |
--release-manifest |
./.release-please-manifest.json |
Version source of truth |
--verbose |
false |
Raise log level from info to debug |
Only files named index.md are collected. Every other markdown file is invisible to the generator and serves as supporting documentation for human readers.
Why index.md Only
Keying on index.md makes the directory the unit of meaning. A concept with six explanatory pages produces one skill, not six fragments. That is what an agent actually wants to load.
Nesting depth is unlimited. A document six levels deep is collected on the same terms as one at the top of a category.
Filtering¶
Two rules remove documents from the candidate set.
Blog posts are skipped. A document is treated as a blog post when its frontmatter carries both a date and a non-empty authors list. Narrative content makes poor skill material, and this heuristic separates it without a manual exclusion list.
Documents without a title produce an error. The skill name is derived from the title, so an empty one cannot be processed. The document is logged, counted, and skipped; generation continues.
graph TD
A[index.md found] --> B{Has date AND authors?}
B -->|Yes| C[Skip: blog post]
B -->|No| D{Has title?}
D -->|No| E[Error: cannot derive name]
D -->|Yes| F{Under a category dir?}
F -->|No| G[Error: unknown category]
F -->|Yes| H[Extract skill]
Category Mapping¶
The plugin a skill belongs to is determined by directory, not configuration. The generator scans the path for the first segment matching a known category and uses it. A document outside every category directory produces no skill.
This has a consequence worth planning around: adding a new top-level documentation section does not create a new plugin. The category list is compiled into the generator, so a new section is invisible until that list is extended.
Skill Naming¶
The skill name is derived from the frontmatter title, not the directory name. Derivation lowercases the title, replaces spaces and separators with hyphens, drops remaining non-alphanumeric characters, collapses repeated hyphens, and trims the ends.
| Title | Skill name |
|---|---|
Idempotency |
idempotency |
GITHUB_TOKEN Permissions Overview |
github-token-permissions-overview |
CI/CD Integration |
ci-cd-integration |
Titles Must Be Unique Within a Category
Because the name comes from the title and the name becomes the output directory, two documents in the same category with identical titles silently overwrite each other. Uniqueness is a documentation convention the generator does not enforce.
Source URLs¶
Each generated skill links back to the page it came from. Building that URL correctly requires preserving every path segment from the category directory down to the document's parent, then dropping the filename. MkDocs serves index.md as its parent directory.
| Source path | Correct URL |
|---|---|
docs/patterns/efficiency/idempotency/index.md |
/patterns/efficiency/idempotency/ |
docs/secure/cloud-native/workload-identity/index.md |
/secure/cloud-native/workload-identity/ |
docs/enforce/index.md |
/enforce/ |
Truncating to a single segment after the category is a subtle failure. The URL still resolves to a real page, just the wrong one: the parent section rather than the document. Broken links announce themselves; wrong-but-valid links do not.
Verify URLs Against the Filesystem
A generated URL is checkable. For each emitted source URL, confirm the corresponding index.md exists in the documentation tree. This catches truncation, off-by-one segment errors, and stale links in a single pass.
Validation¶
Each extracted skill is checked before it is written. Findings are advisory. The skill is written regardless, and the finding is surfaced for correction at the source document.
| Check | Severity | Rationale |
|---|---|---|
| Name present, kebab-case, within length limit | Error | The name becomes a directory; an invalid one cannot load |
| Description present and within length limit | Error | The only field used for relevance routing |
| Category is a known plugin | Error | Determines output location |
| Description long enough to be distinctive | Warning | Very short descriptions rarely route well |
| At least one section mapped to a component | Warning | Otherwise the skill body is near-empty |
| Source URL present | Warning | The skill cannot link back to its documentation |
Validate what exists at the stage you are validating. Skill body content is rendered from templates after extraction, so a pre-write check on rendered output reports every skill as empty. Judge the extracted sections instead.
Next: Skill Anatomy covers what a generated skill directory contains.