Agent repos get messy fast. Skills get copied around, docs disagree, links go stale, and nobody remembers which file is actually canonical.
Skeleton is an SSOT linter for that layer. Define the contract once; Skeleton checks it locally and in CI. If a canonical doc disappears, SSOT markers drift, a skill index stops matching disk, or a local link breaks, the audit fails before merge.
Think ESLint — for the docs and skills your agents rely on. Primary CLI from src/cli.ts: audit, validate, route, catalog, init, and build-plugin. Commands dispatch through that entry file.
Skeleton is not a runtime agent harness. It doesn't execute tools, enforce permissions, or manage memory. It checks whether the repo around those systems still holds together.
Agents can read the repo. They can't reliably infer which of three conflicting docs wins, whether a synced skill should be edited here, or which validation command actually proves a change.
That needs to be explicit — and stay true after the next 50 PRs. Skeleton turns those conventions into checks:
| Code repos | Agent repos |
|---|---|
| ESLint catches broken imports, unused vars, style drift | Skeleton catches broken links, bad SSOT markers, stale doc-meta, deny.paths artifacts |
eslint --fix on changed files |
skeleton validate changed on changed docs, skills, and matching document dependencies |
| Pre-commit + CI gate | --staged pre-commit + --base CI gate |
Skill linters ask: "Is this SKILL.md well-formed?"
Skeleton asks the repo-level question: "Does this whole thing still agree with itself?"
npm install -D @csark0812/skeleton
npx skeleton init --skillsThat writes skeleton.toml, adds validation scripts, and writes .pre-commit-config.yaml.
Edit skeleton.toml for your repo layout, then verify:
npx skeleton catalog
npx skeleton audit docsFlag details: install.
- SSOT markers — opt-in
source-of-truth(comment or visible); dual/malformed forms fail; legacy banners accepted - Near-duplicate docs — shingle overlap + duplicate SSOT summaries (warn /
--strict) - SSOT summary fit — heuristic overlap between the one-liner and the body (warn /
--strict) - Link audit — broken refs, skill links, anchors in scanned markdown
- Skill index — disk matches taxonomy READMEs in detected skill roots
- deny.paths — globs for files that must not exist (often outside
scan.include) - Coverage gaps — markdown outside the scan perimeter (warn-only)
- Doc meta + stale dates — owner and
last-reviewedon indexes and SSOT-bearing files - Review proof — optional hashes bind a human review to exact document and
review-depsbytes - Dependency routing — changed repository files automatically pull matching documents into validation
- Prose policy (optional plugins) — YAML pattern rules; idle with no plugins
- Shell / JSON syntax — lightweight checks on changed
.shand.jsonfiles
Agents skim .skeleton/catalog.md (generated, gitignored) before opening full papers.
Shared reference files can live in any scanned path. Public repositories can link skills directly to GitHub-hosted references; Skeleton leaves those external links unchanged and does not check their remote reachability.
Skeleton doesn't replace your code gates. Keep TypeScript, Python, Nx, pytest, and the rest in the repo that owns them.
Config lives in skeleton.toml at the repo root (preferred). Optional under .skeleton/:
skeleton.toml # scan perimeter, deny.paths, docsLint, …
.skeleton/
├── catalog.md # generated by `skeleton catalog` (gitignored)
├── review-lock.json # generated review evidence when reviewProof.mode = "hash"
└── plugins/ # optional consumer audit plugins (.ts + built .mjs)
Legacy .skeleton/config.yaml still loads when no TOML is present.
Every canonical doc opts into the catalog with a marker:
<!-- source-of-truth: Backend API conventions -->Then refresh the agent index:
skeleton catalogEdit synced skills in the owning toolbox repo. Consumer copies stay read-only.
skeleton init [--skills]
skeleton catalog [--check] [--strict]
skeleton audit docs|skills|self [--strict] [--json] [--paths=a,b] [--fix[=doc-meta|anchors|ssot]] [--dry-run]
skeleton audit docs --paths=docs/a.md --fix=doc-meta --confirm-reviewed
skeleton build-plugin [path] [--check]
skeleton route [path…]
skeleton validate changed [--staged | --base <ref>] [paths…]Validate changed routes git diffs to the right audit:
| Path | Action |
|---|---|
| Docs in scan perimeter | path-scoped audit |
Owned skill bodies (SKILL.md trees) |
run audit skills |
| Foreign / lockfile-synced skill bodies | skip → lint in the owning skills/toolbox repo |
.sh, .bash, .zsh |
shellcheck or bash -n |
Other .json |
JSONC-tolerant syntax check |
| Any repository file | native gates where applicable + audit documents whose review-deps path or glob matched |
Pre-commit: skeleton validate changed --staged (index bytes, coverage, owning papers).
CI: skeleton validate changed --base origin/main (global rules first, then changed files, same coverage fail).
| Layer | Role |
|---|---|
| Skeleton | Defines and checks the SSOT contract |
| Shared skills | Reusable team or public skills. toolbox is one example |
| Consumer apps | Pull in the skills, run Skeleton on SSOT paths, and keep their own code gates |
Skeleton never calls Nx or another app task runner. Consumer repos keep ownership of test, typecheck, and build.
See tiers. Related work: Toolbox packages portable process skills, and Christopher's profile connects the broader builder story.
Requires Bun 1.2.x and Node ≥ 22. Agent cold-start: AGENTS.md.
bun install
bun run checkbun run check = lint + test + typecheck + build + audit:self.
validate:changed does not replace code tests. It classifies code separately and also audits every scanned document whose review-deps declaration matches a changed file. A coverage-candidate path with no owning paper fails on local and CI runs. Owned skill-body edits run the skills suite. --staged reads git index bytes.
For code: bun test, bun run typecheck, bun run build.
skeleton init writes .pre-commit-config.yaml. Install pre-commit once (brew install pre-commit or pipx install pre-commit), then pre-commit install.