How we lint
Agent Skills are folders with a SKILL.md file. The format is an open specification, now a project of the Agentic AI Foundation under the Linux Foundation. The body is free Markdown, which is why quality varies so widely. A score of 100 is also the Listed certificate. What that certificate does and does not cover is on Certification.
In From Anatomy to Smells, Hong, Imani, and Ahmed at UC Irvine studied 238 real skills sampled from a public marketplace. Over 99 percent — 237 of the 238 — contained at least one skill smell. Smells introduced early rarely disappeared in later commits. Popularity did not clean them up.
Agentpedia vendors tools/skill-lint, a dependency-free Python checker for the spec, for progressive-disclosure smells, for broken relative links, and for a small set of safety patterns. The catalog build runs it on every skill. An error or a warning fails the build. Info findings are recorded and lower the score. This shelf has 0 of them.
The score
A skill starts at 100. Each error subtracts 25, each warning subtracts 8, and each info finding subtracts 2. The floor is 0. The badge reads clean when errors and warnings are both zero, noted when there are warnings but no errors, and blocked when any error remains. Blocked and noted entries do not ship in this catalog.
Spec
| Rule | Severity | What it checks |
|---|---|---|
| spec.frontmatter.missing | error | File must start with YAML frontmatter between --- lines. |
| spec.frontmatter.invalid | error | Frontmatter must parse as simple YAML keys. |
| spec.filename.case | error | The file must be named SKILL.md. Linux treats the name as case-sensitive. |
| spec.name.missing | error | name is required and must be non-empty. |
| spec.name.invalid | error | name is lowercase letters, numbers, and single hyphens. No leading, trailing, or doubled hyphens. |
| spec.name.too-long | error | name is at most 64 characters. |
| spec.name.directory-mismatch | error | name must match the parent folder exactly. |
| spec.description.missing | error | description is required and must be non-empty. |
| spec.description.too-long | error | description is at most 1024 characters. |
| spec.compatibility.too-long | error | compatibility is at most 500 characters. |
Smells
| Rule | Severity | What it checks |
|---|---|---|
| smell.name.unclear | warn | Name is generic (helper, misc, skill, …) or shorter than 3 characters. |
| smell.description.no-when | warn | Description does not say when to use the skill. |
| smell.description.vague | warn | Description is under 40 characters. |
| smell.description.not-third-person | info | Description uses I/you phrasing. Third person matches more reliably. |
| smell.description.xml | error | Description contains XML or HTML tags. |
| smell.body.too-long-lines | warn | Body is longer than 500 lines. Move detail into references/. |
| smell.body.too-long-words | warn | Body is longer than 5000 words. |
| smell.body.huge-inline-blob | warn | A fenced block is 80 lines or longer. Move it to references/ or scripts/. |
| smell.example.missing | warn | Body has no example of an input, an output, or a usage. |
| smell.workflow.stepless | warn | A longer body has no numbered steps. |
| smell.validation.missing | info | Body never mentions a check, a test, or validation. |
| smell.scripts.missing | info | Many shell commands and no scripts/ helpers. |
| smell.detail.undelegated | warn | A very long body does not delegate detail to references/. |
Links
| Rule | Severity | What it checks |
|---|---|---|
| link.relative.missing | error | A relative link or scripts/, references/, assets/, or lib/ path does not exist. |
| link.path.backslash | warn | A path uses backslashes. Skill trees are POSIX. |
Safety
| Rule | Severity | What it checks |
|---|---|---|
| security.secret | error | A hardcoded credential, token, or private key. |
| security.curl-pipe-sh | error | A download piped directly into a shell. |
| security.rm-rf | warn | rm -rf. This is an error when aimed at /, /*, or the home directory. |
| security.absolute-path | warn | A machine-specific absolute path such as /Users, /home, or a drive letter. |
| security.exfil-url | warn | A URL that looks like a webhook, tunnel, or paste-site sink. |
Scan
| Rule | Severity | What it checks |
|---|---|---|
| scan.path.missing | error | The path passed to the linter does not exist. |
| scan.skill.not-found | error | No SKILL.md file was found under the path. |
| scan.file.unreadable | error | A skill file could not be read as UTF-8. |