skillhash

skills.toml and skills.lock

Two files, like package.json and package-lock.json. Commit both.

skills.toml

[settings]
targets = [".claude/skills", ".agents/skills"]
min_grade = "C"

[skills.pdf]
source = "github:anthropics/skills/skills/pdf"

[skills.deploy]
source = "registry:acme/deploy@1.4.0"
  • targets: folders each skill is copied into. Use .claude/skills for Claude Code, .agents/skills for Codex and other agents that read the shared folder, .cursor/skills and .gemini/skills when you need them.
  • min_grade: the lowest scan grade add and verify accept. A is strictest, F accepts anything.
  • skills.NAME.source: where the skill comes from. NAME is the folder it is installed as.

skills.lock

{
  "version": 1,
  "skills": {
    "pdf": {
      "source": "github:anthropics/skills/skills/pdf",
      "requested": "github:anthropics/skills/skills/pdf",
      "resolved": "dbd4588f9e10...",
      "hash": "sha256:5c1e0b...",
      "grade": "A",
      "score": 100,
      "files": 12,
      "findings": {}
    }
  }
}

How the hash is computed

For every file in the skill folder (ignoring .git, node_modules, __pycache__ and symlinks) Skillhash takes the SHA-256 of its bytes, then hashes the sorted list of path, NUL, file hash, newline. Renaming, adding, removing or editing any file changes the result. The same algorithm runs in the CLI, the registry and the web scanner, so the hash on a report page matches your lockfile.

Updating

skillhash update resolves each ref again and prints the old and new commit with the grade change. Review the diff, then skillhash install and commit the lockfile.