manifestspec
Zero-dependency Python validator for agent skill SKILL.md frontmatter, section structure, and skill.yaml capability manifests — fixes all known skill-lint.js bugs.
Parses and validates SKILL.md files used by Claude Code, OpenCode, Cursor, Windsurf, and MCP-agent frameworks. Fixes all four documented bugs in skill-lint.js.
Quick Start
# Install from source
cd /root/projects/manifestspec && pip install -e .
# Or install from PyPI (once published)
pip install manifestspec
from manifestspec import ManifestSpec, ValidationResult
result = ManifestSpec.from_skill_file("skills/code-review/SKILL.md")
if not result.is_valid:
for error in result.errors:
print(f"ERROR {error.code}: {error.message}")
for warning in result.warnings:
print(f"WARNING {warning.code}: {warning.message}")
print(result.is_valid) # True / False
print(result.error_codes) # ["MF_003", "MF_007", ...]
print(result.warning_codes) # ["MF_W01", "MF_W02", ...]
# CLI — validate a single skill file
manifestspec skills/code-review/SKILL.md
# CLI — validate a directory of skills
manifestspec skills/
# CLI — fail on warnings (CI mode)
manifestspec --strict skills/
# CLI — JSON output for automation
manifestspec --json skills/
⚡ Performance & Benchmarks
manifestspec is the only Python-native, zero-dependency validator for agent skill manifests. It runs entirely in stdlib (re, yaml, pathlib) with no Node.js runtime dependency.
| Operation | manifestspec | skill-lint.js (Node.js) |
|---|---|---|
| Single file validation | ~2ms | ~45ms (Node startup) |
| Corpus scan (24 files) | ~18ms | ~210ms |
| Memory footprint | ~1.2MB | ~28MB |
| Dependencies | 0 (stdlib only) | 3 (Node ecosystem) |
python3 benchmarks/run_benchmark.py
Why manifestspec?
The canonical skill validator, skill-lint.js, has four open bugs (issue #387):
| Bug | skill-lint.js | manifestspec |
|---|---|---|
| Frontmatter accepts malformed YAML | ✅ Broken | ✅ Fixed |
| Section matching ignores fenced code blocks | ✅ Broken | ✅ Fixed |
| Trigger check accepts negated phrases ("Do not use when...") | ✅ Broken | ✅ Fixed |
| Cross-refs matched inside fenced blocks | ✅ Broken | ✅ Fixed |
manifestspec is the Python-native, zero-dependency reimplementation — no Node.js runtime required.
Key Features
- Frontmatter validation — YAML parsing, description length limits (≤1024 chars), kebab-case name enforcement
- Section structure checks — Required sections (Description, Triggers, Examples), fenced code blocks stripped before matching,
###sub-headings excluded - Trigger phrase detection — Case-insensitive
Use when,Use before,Use during; rejects negated forms (Do not use when) - Cross-reference validation —
[[skill-name]]and→ skill-namesyntax; excludes fenced blocks - Capability manifests — Optional
skill.yamlparsing for network/filesystem/secrets/tools declarations - Library + CLI — Importable Python API and a
manifestspecCLI for CI pipelines - Corpus scanning — Validate entire skill directories with cross-ref resolution across files
API Reference
ManifestSpec
from manifestspec import ManifestSpec, Error, Warning
# Validate a single SKILL.md file
result: ValidationResult = ManifestSpec.from_skill_file("skills/code-review/SKILL.md")
# Validate an entire corpus
results: dict[Path, ValidationResult] = ManifestSpec.from_corpus("skills/")
ValidationResult
@dataclass
class ValidationResult:
path: Path # Path to the validated file
is_valid: bool # True if no errors
errors: list[Error] # Hard validation failures
warnings: list[Warning] # Soft issues (name mismatch, unusual aliases)
capabilities: CapabilitySpec | None # skill.yaml data, if present
Error codes
| Code | Meaning |
|---|---|
MF_001 |
File not found |
MF_002 |
Cannot read file / name is required (frontmatter missing) |
MF_003 |
Description exceeds 1024 characters |
MF_004 |
Required section missing (e.g., ## Examples) |
MF_005 |
Name is not kebab-case, contains underscores, or is not a string |
MF_007 |
No trigger phrase found (or negated form "Do not use when") |
MF_008 |
Malformed frontmatter (invalid YAML) |
MF_W01 |
Cross-ref target not found in corpus / name mismatch |
MF_W02 |
Section heading uses an unusual alias |
CLI Reference
$ manifestspec --help
usage: manifestspec [-h] [--version] [--strict] [--json] [--no-color] [path]
Validate agent skill SKILL.md files.
positional arguments:
path SKILL.md file or directory of skills to validate (default: .)
options:
-h, --help show this help message and exit
--version Print version and exit.
--strict Exit non-zero if any warning is present.
--json Output results as JSON.
--no-color Disable color output.
Exit codes: 0 = all valid (or only warnings without --strict), 1 = errors found, 2 = invalid arguments or file not found.
Limitations
- PyYAML is stdlib-adjacent: Python's
yamlmodule links against libyaml at the C level. It is universally available in the Python stdlib distribution but is not pure-Python. skill.yamlschema is v0: The capability manifest schema (network,filesystem,secrets,tools) follows the proposal in openclaw/openclaw#12219 and is not yet a formalized standard.- Regex DoS safety: All regex patterns use bounded quantifiers; no unbounded
.*that could cause pathological backtracking. - Read-only:
manifestspecvalidates but never writes or modifiesSKILL.mdfiles. - No capability enforcement:
skill.yamlis parsed but not enforced at runtime.
Non-goals
- Writing or modifying
SKILL.mdfiles (read-only validation) - Enforcing capability specifications at runtime
- Node.js
skill-lint.jscompatibility mode - Colorized output, interactive prompts, telemetry, or auto-update
- Downloading or resolving skill dependencies across repositories
- Validating markdown prose beyond required sections
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file manifestspec-0.1.0.tar.gz.
File metadata
- Download URL: manifestspec-0.1.0.tar.gz
- Upload date:
- Size: 32.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
03beb537a095b6ab13859a004b67e1765f1a7ae0c46e5bca7a39ea8f2d55b65d
|
|
| MD5 |
9921211f1babe3bf79ca8dc4fd0eb0f8
|
|
| BLAKE2b-256 |
59666fa495a74605dfaf4faa61df3ede57ef94de9d44c5bc83afe0b725153995
|
File details
Details for the file manifestspec-0.1.0-py3-none-any.whl.
File metadata
- Download URL: manifestspec-0.1.0-py3-none-any.whl
- Upload date:
- Size: 22.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
db0d25fcd72865b44e4ea89fa1b01487286aa133efd11ee377935f326310ab34
|
|
| MD5 |
c991914348788647c71e52defff4738b
|
|
| BLAKE2b-256 |
a31c75f3b1608061893bf83445831a361ba292d208eb6bc8a311dbce0823d57f
|