skills-lock-valid¶
skills-lock.json files must be valid and portable project lockfiles
| Severity | error (auto) |
| Autofix | - |
| Since | v0.20.0 |
| Repo Types | skills-lock |
| Category | Vercel |
Why¶
The Vercel skills CLI records each
project's installed skills in skills-lock.json. The lockfile tells later
skills update and restore operations where a skill came from, which source
dialect to use, which SKILL.md was selected, and what content hash was
installed. A lockfile can remain valid JSON while a wrong field type or an
unusable path quietly makes those operations unreliable.
This rule follows the project-lock structure implemented by the CLI's
src/local-lock.ts:
- the root is an object with numeric
versionand an object-valuedskills; - each skill has non-empty
sourceandsourceTypestrings; computedHash, when present, is a lowercase, 64-character SHA-256 hex digest. The CLI reads it only to detect drift, so an entry without one is a warning rather than an error;- optional
sourceUrl,ref,skillPath, andwellKnownDigestfields have the string shape their consumers expect; - optional
subagentsis an array of strings. An empty string is valid here: the CLI uses it for a source's root agent; skillPathcannot be absolute or traverse above the downloaded source, and ends inSKILL.md;- a
wellKnownDigest, when present, usessha256:followed by 64 lowercase hex characters.
Known sourceType values are github, gitlab, git, local,
well-known, node_modules, and download. A newer CLI may add another one,
so an unknown value is information rather than an error and can be accepted
immediately with extra-source-types.
Validation is offline and structural: computedHash is checked for format
(a lowercase 64-character SHA-256 hex digest) rather than recalculated over
the network. Because lockfiles are generated by package managers, defects are
reported for human review without autofix.
Detection¶
Every exact skills-lock.json filename is discovered recursively. This
supports monorepos where the root and individual packages each run the skills
CLI. Vendored directories and paths excluded through skillsaw configuration
are not attached. A global .skill-lock.json or singular skill-lock.json
is a different file and is not claimed by this rule.
The rule auto-enables whenever at least one non-excluded project lockfile is present. A lockfile is structured JSON rather than agent prose, so content rules never read it.
skillsaw also uses valid lock entries as provenance for installed skill
directories. A remote, package-managed, unknown, or repository-external
local source marks the matching installed skill as externally sourced.
Those payloads are linted by default, but skillsaw fix never rewrites them.
Set the top-level lint-external-content: false configuration key to omit them
from rule discovery while continuing to validate skills-lock.json itself.
A local source that resolves inside the lint root remains repository-owned.
Severity¶
Errors identify data the CLI cannot reliably interpret: invalid or non-strict
JSON (including bare NaN or Infinity), the wrong top-level shape, missing
or wrong-typed required fields, malformed digests, malformed optional fields,
or a skillPath that escapes its source or does not point to SKILL.md.
Warnings identify a lockfile that remains readable but is not portable or may not restore correctly:
- a schema version newer than this skillsaw release;
- an entry without
computedHash, whichnpx skills checkcannot verify; - a bare
gitorgitlabshorthand without thesourceUrlthe CLI's update path needs; - an absolute local source path;
- backslashes in
skillPath, which are not portable path separators.
An unknown sourceType is informational because it may come from a newer or
custom skills CLI.
Examples¶
Good:
{
"version": 1,
"skills": {
"release-notes": {
"source": "vercel-labs/skills",
"sourceType": "github",
"computedHash": "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
"sourceUrl": "https://github.com/vercel-labs/skills.git",
"ref": "main",
"skillPath": "skills/release-notes/SKILL.md"
}
}
}
Bad:
{
"version": 1,
"skills": {
"release-notes": {
"source": "/Users/alice/src/skills/release-notes",
"sourceType": "local",
"computedHash": "not-a-sha256",
"skillPath": "../README.md",
"subagents": "reviewer"
}
}
}
The absolute source only works on one machine, the digest has the wrong
shape, skillPath escapes the downloaded source and does not end in
SKILL.md, and subagents must be an array.
How to fix¶
Regenerate a damaged lockfile with the same skills CLI release used by the
project, or correct the reported structural fields and rerun the CLI command
that consumes it. Prefer project-relative local sources and / separators.
If a legitimate source type was added after this skillsaw release, accept it without disabling the rest of the rule:
Configuration¶
| Parameter | Description | Default |
|---|---|---|
extra-source-types |
Additional sourceType values to accept when a newer or custom skills CLI writes sources this skillsaw release does not know | [] |
Run skillsaw explain skills-lock-valid to see this documentation and the rule's effective configuration in your terminal.