Problem
Hey there, first off thanks for building skills — it’s a really nice abstraction!
I’ve been digging into the lock file behavior, hoping it might offer something like a “reproducible state” mechanism across machines.
Current behavior (as I understand it)
-
The global lock file lives at ~/.agents/.skill-lock.json and has the shape defined in src/skill-lock.ts (and redefined in src/cli.ts):
skills: Record<string, SkillLockEntry> keyed by skill name
- Each
SkillLockEntry stores:
source (normalized identifier, e.g. owner/repo)
sourceType (github, mintlify, huggingface, local, …)
sourceUrl (the URL actually used with skills add)
- optional
skillPath
skillFolderHash (GitHub tree SHA for the skill folder)
installedAt / updatedAt timestamps
-
Global installs (via runAdd in src/add.ts) update the lock file by calling addSkillToLock, which writes/updates an entry for the installed skill.
-
skills check (runCheck in src/cli.ts):
- Reads the lock file.
- Builds a
CheckUpdatesRequest using only entries that have a skillFolderHash.
- POSTs to
https://add-skill.vercel.sh/check-updates.
- Prints which skills have updates available, but does not install or modify anything.
-
skills update (runUpdate in src/cli.ts):
- Does the same lock-file →
CheckUpdatesRequest → API call.
- If there are updates, it reinstalls only those updated skills, using the
sourceUrl and skill name from the lock entry:
- Roughly:
npx -y skills <entry.sourceUrl> --skill <name> -g -y.
- It does not attempt to install all skills in the lock file, only those whose
skillFolderHash differs from the server’s latestHash.
-
Listing actual installed skills is done via the filesystem (e.g. .agents/skills/<skill-name> and agent-specific directories in installer.ts / list.ts), not via the lock file.
So the lock file is currently acting as a global registry + update-tracking database, rather than a declarative “install manifest” like package.json or a fully deterministic package-lock.json.
Pain point
Because the lock file is global and already contains:
- the skill names,
- the original
sourceUrl used to install,
- and the provider/path information,
it feels like the perfect place to drive reproducible installs across machines or after deletion.
However, in practice:
Right now, I’d need to manually re-run npx skills add ... for each repository, or write my own script around the lock file structure.
Proposed Solution
I’d love a first‑class command, something like:
skills install (or skills sync, skills restore, etc.)
that:
-
Reads ~/.agents/.skill-lock.json (and/or a project-local lockfile, if that ever exists).
-
For each entry in lock.skills:
-
Optionally supports some modes/flags, for example:
--missing-only: only install skills that are not currently present on disk (according to installer.ts / listInstalledSkills).
--all: reinstall everything in the lock file regardless of hash (useful for a completely fresh machine).
--dry-run: show what would be installed/reinstalled, using lock entries as the source of truth.
This would provide:
- A reproducible global skill set across machines by simply:
- syncing
~/.agents/.skill-lock.json via dotfiles, and
- running
npx skills install on a new machine.
- A way to recover from manual deletions of skill directories without having to remember all original
skills add commands.
And this fits the design because:
- The lock file already holds everything needed to reconstruct the install command:
sourceUrl (exact URL originally used),
source / sourceType / skillPath (for future flexibility),
- and the skill’s logical name (the key in
lock.skills).
skills update already uses this data to drive a reinstall step for updated skills.
skills install/sync would just generalize this from “only updated skills” to “all skills (or all missing skills) in the lock file”.
- It keeps the mental model cohesive:
skills add: install new skills and write them to the lock file.
skills check: read lock file to detect which tracked skills could be updated.
skills update: read lock file + update only out-of-date skills by reinstalling.
skills install / skills sync: read lock file + ensure all tracked skills are present on the local machine.
Alternatives Considered
No response
Additional Context
Possible open questions
Some questions I’m not presuming to answer, but worth considering:
- Should
skills install:
- only operate on global skills (current lock file), or
- support a future project-level lock file as well?
- How should it behave if:
- the lock file references a skill whose repo is now gone or private?
sourceUrl has changed or is invalid?
- Should it integrate with
listInstalledSkills to detect “missing” skills more robustly?
Problem
Hey there, first off thanks for building
skills— it’s a really nice abstraction!I’ve been digging into the lock file behavior, hoping it might offer something like a “reproducible state” mechanism across machines.
Current behavior (as I understand it)
The global lock file lives at
~/.agents/.skill-lock.jsonand has the shape defined insrc/skill-lock.ts(and redefined insrc/cli.ts):skills: Record<string, SkillLockEntry>keyed by skill nameSkillLockEntrystores:source(normalized identifier, e.g.owner/repo)sourceType(github,mintlify,huggingface,local, …)sourceUrl(the URL actually used withskills add)skillPathskillFolderHash(GitHub tree SHA for the skill folder)installedAt/updatedAttimestampsGlobal installs (via
runAddinsrc/add.ts) update the lock file by callingaddSkillToLock, which writes/updates an entry for the installed skill.skills check(runCheckinsrc/cli.ts):CheckUpdatesRequestusing only entries that have askillFolderHash.https://add-skill.vercel.sh/check-updates.skills update(runUpdateinsrc/cli.ts):CheckUpdatesRequest→ API call.sourceUrland skill name from the lock entry:npx -y skills <entry.sourceUrl> --skill <name> -g -y.skillFolderHashdiffers from the server’slatestHash.Listing actual installed skills is done via the filesystem (e.g.
.agents/skills/<skill-name>and agent-specific directories ininstaller.ts/list.ts), not via the lock file.So the lock file is currently acting as a global registry + update-tracking database, rather than a declarative “install manifest” like
package.jsonor a fully deterministicpackage-lock.json.Pain point
Because the lock file is global and already contains:
sourceUrlused to install,it feels like the perfect place to drive reproducible installs across machines or after deletion.
However, in practice:
If I sync only
~/.agents/.skill-lock.jsonvia dotfiles onto a new machine:skills checkandskills updateon that machine can now see those skills and their hashes.skills updatewill only reinstall skills that the API considers “out of date”. If the storedskillFolderHashalready matches the remote hash, that skill is not included inupdates, so it does not get reinstalled—even if it’s completely missing on disk on that machine.There is currently no command that says “install everything from this lock file”.
Right now, I’d need to manually re-run
npx skills add ...for each repository, or write my own script around the lock file structure.Proposed Solution
I’d love a first‑class command, something like:
skills install(orskills sync,skills restore, etc.)that:
Reads
~/.agents/.skill-lock.json(and/or a project-local lockfile, if that ever exists).For each entry in
lock.skills:Uses
entry.sourceUrlandnameto reinstall that skill via the existing CLI pipeline, e.g.:Optionally supports some modes/flags, for example:
--missing-only: only install skills that are not currently present on disk (according toinstaller.ts/listInstalledSkills).--all: reinstall everything in the lock file regardless of hash (useful for a completely fresh machine).--dry-run: show what would be installed/reinstalled, using lock entries as the source of truth.This would provide:
~/.agents/.skill-lock.jsonvia dotfiles, andnpx skills installon a new machine.skills addcommands.And this fits the design because:
sourceUrl(exact URL originally used),source/sourceType/skillPath(for future flexibility),lock.skills).skills updatealready uses this data to drive a reinstall step for updated skills.skills install/syncwould just generalize this from “only updated skills” to “all skills (or all missing skills) in the lock file”.skills add: install new skills and write them to the lock file.skills check: read lock file to detect which tracked skills could be updated.skills update: read lock file + update only out-of-date skills by reinstalling.skills install/skills sync: read lock file + ensure all tracked skills are present on the local machine.Alternatives Considered
No response
Additional Context
Possible open questions
Some questions I’m not presuming to answer, but worth considering:
skills install:sourceUrlhas changed or is invalid?listInstalledSkillsto detect “missing” skills more robustly?