Skip to content

Standards Linter

FieldValue
TypeSkill Resource
Source~/.copilot/skills/skill-forge/references/standards-linter.md
DescriptionNot specified

Source Content

Standards Linter

How scripts/standards_linter.py gates every skill in this repo to the consolidation plan’s standards.

What it checks

Run python3 scripts/standards_linter.py <skill-dir> before every commit:

CheckSeverityFix
Frontmatter present and valid YAMLerrorEnsure --- opening and closing around key-value pairs
name field presenterrorAdd name: <folder-name> (must match directory name exactly)
description field presenterrorAdd a paragraph describing what triggers the skill
name matches directory name exactlyerrorRename directory or edit frontmatter to match
description under ~1,200 characterserrorTrim; move detail to references/
All relative links in SKILL.md resolveerrorCheck referenced files exist; fix typos in paths
SKILL.md under 500 lineserror (for large skills)Push detail into references/
Routing table present (if >2 references)warningAdd “Route by task” table; see skill-authoring.md
Every referenced path exists on diskerrorreferences/foo.md must be a real file
scripts/ entrypoint exists and executableerrorCheck your validation script is in scripts/ and has execute bit set
No cross-skill invocation languagewarningDon’t write “invoke the X skill” outside agent files and AGENTS.md

Exit codes

  • 0 — skill passes all checks.
  • 1 — one or more checks failed (see the error output for details).

Running the linter

On a single skill:

Terminal window
python3 scripts/standards_linter.py /path/to/skill-dir

Output:

✅ name matches directory: helm
✅ description present (856 chars)
✅ all 14 referenced references/scripts/templates paths exist
✅ SKILL.md is 278 lines (under 500)
✅ routing table detected (12 rows)
✅ scripts/ entrypoint (scripts/lint_chart.sh) is executable

On multiple skills:

Terminal window
for skill in ~/.copilot/skills/*/; do
python3 scripts/standards_linter.py "$skill" || exit 1
done

The routing table rule

Any skill with more than two references/ paths should have a “Route by task” table in its SKILL.md. The linter warns if a skill has 3+ references but no visible routing table.

Example of a good routing table (from technical-writing):

| You're… | Read | Gate with |
| --- | --- | --- |
| Drawing a diagram only | `references/mermaid.md` + `references/mermaid/` | `scripts/mermaid_lint.py` |
| Fixing Markdown mechanics only | `references/markdown.md` | `scripts/markdown_lint.py` |
| Writing or editing a full document | `references/pipeline.md` — mode, template, workflow | `scripts/lint.py --git-changed` |

The routing table signals that this is a front door skill — the reader can quickly navigate to what they need instead of scrolling through a monolithic SKILL.md.

The script entrypoint rule

If a skill has a scripts/ directory, the linter checks that:

  1. An entrypoint exists: check.sh, lint.py, or similar.
  2. It is executable (has the +x bit).
  3. It is documented in SKILL.md as the validation/gating step.

Example from technical-writing/SKILL.md:

| You're… | Read | Gate with |
| --- | --- | --- |
| Validating anything already written | - | `scripts/lint.py --git-changed` (or explicit files) |

The entrypoint should accept a target path and exit 0 on success, non-zero on failure.

Frontmatter caps

  • description length: Max ~1,200 characters. Longer descriptions hurt trigger accuracy because the LLM pays less attention to tail text. Move detail into references/.
  • SKILL.md line count: Max 500 lines. This is a gating rule enforced by the linter and the consolidation plan.

The linter parses Markdown links in SKILL.md (ignoring code spans and fenced blocks — those are examples, not real links) and checks:

  • Broken link (relative path that does not resolve) → error; blocks the skill from passing validation.
  • Escaping link (points outside the skill folder, e.g., ../adr/references/index.md) → warning; does not block but flags portability risk for isolated --dir copies.

Cross-skill invocation

The linter looks for phrases like “invoke the X skill” or “use the Y skill” outside of agent files and AGENTS.md. These are warnings: front-door skills should not call each other — any cross-domain handoff happens at the agent level, or as a plain “see also” pointer with no invocation language.

How the linter is run

This repo’s task lint fan-out includes lints:skills:

Terminal window
task lint
lints:skills
python3 ~/.copilot/skills/skill-forge/scripts/standards_linter.py ~/.copilot/skills/*

Every commit via the post-commit hook runs this, so the repo’s skills always stay valid.