@cogineai/skillsdock
v0.4.0
Published
CLI to scan, track, and sync AI skills across agents and IDEs.
Maintainers
Readme
SkillsDock
skillsdock is a CLI to discover, track, and sync AI skills across multiple agents and IDEs.
This repository is intentionally CLI-only.
What Changed In v0.4.0
v0.4.0 — Discovery & Updates:
- New commands:
find(search skills.sh ecosystem),check(detect available updates via GitHub Trees API),update(auto-reinstall outdated skills) sync --from node_modules— discover and sync skills from npm package dependenciesresolveGitHubToken()— automatic token resolution (GITHUB_TOKEN>GH_TOKEN>gh auth token)- Agent registry CI automation:
scripts/sync-agent-docs.mjsandscripts/validate-agent-registry.mjs
v0.3.0 — Remote Install:
- New commands:
add(install from GitHub/GitLab/local),remove(clean up skills and symlinks) - Project-level
skills-lock.json— deterministic, hash-based, no-timestamp lockfile parseSource()— unified source parser (GitHub/GitLab/SSH/shorthand/local)sanitizeSubpath()— path-traversal guard
Still relevant from v0.2.0:
- 42 curated built-in agents covering 40+ tools and IDEs
- Canonical
.agents/skills/as the universal skill storage directory - Read-only interop with
vercel-labs/skillslockfile metadata - Plugin ownership grouping for
.claude-plugindiscovered skills
Project Lockfile (skills-lock.json)
SkillsDock supports a project-level skills-lock.json that deterministically tracks installed skills, their sources, and content hashes. This file is designed for team collaboration:
- Git-friendly: keys are sorted alphabetically, no timestamps, deterministic output
- Hash-based integrity: each skill entry stores a SHA-256 hash computed from all files in the skill folder (path-aware, skips
.gitandnode_modules) - Merge-conflict safe: if the lockfile contains git conflict markers (
<<<<<<<), SkillsDock treats it as empty and prints a warning instead of crashing
Schema:
{
"version": 1,
"skills": {
"skill-name": {
"source": "owner/repo",
"sourceType": "github",
"sourceUrl": "https://github.com/owner/repo",
"computedHash": "sha256-hex-string",
"treeSha": "sha256-hex-string",
"skillPath": "relative/path/to/skill"
}
}
}computedHash: SHA-256 of local file contents (for integrity checking)treeSha: SHA-256 fingerprint derived from git blob SHAs (for remote freshness detection viaskillsdock check)
The lockfile lives at ${projectRoot}/skills-lock.json (auto-detected via detectProjectRoot()).
Design Principle
SkillsDock uses a curated local agent path registry as a pattern seed.
- It does not fetch skill content from external ecosystems at runtime.
- It does not treat Vercel (or any other ecosystem) metadata as the source of your skills.
- Source of truth remains your local files and configured source paths.
- External lockfiles are read-only interoperability inputs, never authoritative content stores.
Install
npm install -g @cogineai/skillsdockOr run directly:
npx @cogineai/skillsdock --helpQuick Start
# create or upgrade config + registry
skillsdock init
# scaffold a new SKILL.md in ./my-skill
skillsdock init skill my-skill
# scan configured sources
skillsdock scan
# governance view
skillsdock all-local-skills
# registry view
skillsdock list
# inspect one skill (path/key/id selector)
skillsdock skill-detail my-skill --all-copies
# mark a skill as frozen
skillsdock tag set my-skill --tag frozen --reason "manual lock"
# preview cleanup actions
skillsdock cleanup --plan
# dry-run sync to OpenClaw user scope
skillsdock sync --to openclaw --scope user --dry-run
# install skills from a GitHub repo
skillsdock add owner/repo --scope user
# install a specific skill from a repo
skillsdock add owner/repo@skill-name
# install from a local directory
skillsdock add ./path/to/skills --scope project
# preview what would be installed
skillsdock add owner/repo --dry-run
# check for skill updates
skillsdock check
# check for updates (JSON output)
skillsdock check --json
# update outdated skills
skillsdock update --scope project
# preview updates without installing
skillsdock update --dry-run
# inspect built-in agent compatibility + detection
skillsdock doctor --agentsCommands
skillsdock init [--config <path>] [--registry <path>]
skillsdock init skill [name]
skillsdock scan [paths...] [--config <path>] [--registry <path>]
skillsdock all-local-skills [--config <path>] [--registry <path>] [--source <name>] [--scope <user|project>] [--tag <tag>] [--all] [--json]
skillsdock skill-detail <selector> [--registry <path>] [--all-copies] [--json]
skillsdock tag set <selector> --tag <regular|disabled|frozen|deleted> [--reason <text>] [--all-copies] [--registry <path>]
skillsdock tag list [--registry <path>] [--source <name>] [--scope <user|project>] [--tag <tag>] [--all] [--json]
skillsdock cleanup --plan|--apply [--registry <path>] [--source <name>] [--scope <user|project>] [--all] [--json]
skillsdock cleanup --rollback <runId> [--registry <path>]
skillsdock list [--config <path>] [--registry <path>] [--source <name>] [--changed] [--all] [--json]
skillsdock inspect <id|key|path> [--registry <path>] [--json]
skillsdock sync --to <agent|target> --scope <user|project> [--config <path>] [--registry <path>] [--mode <symlink|copy>] [--fallback <copy|fail>] [--dry-run] [--all]
skillsdock remove <selector> [--scope <user|project>] [--dry-run] [--force] [--all-copies]
skillsdock remove --all --scope <user|project> [--dry-run] [--force]
skillsdock add <source> [--scope user|project] [--dry-run] [--copy]
skillsdock find [query] [--json]
skillsdock sync --from node_modules [--scope user|project] [--dry-run]
skillsdock check [--json]
skillsdock update [--scope user|project] [--dry-run]
skillsdock doctor [--config <path>] [--registry <path>] [--agents] [--skills-spec]
skillsdock versionScope And Target Resolution
For built-in dual-scope agents, --scope is required when using the agent name.
Examples:
# explicit user scope (required)
skillsdock sync --to codex --scope user
# explicit project scope (required)
skillsdock sync --to cursor --scope project
# direct target key also works
skillsdock sync --to openclaw-userskillsdock init now seeds 42 built-in agent presets (84 default source/target entries across user and project scopes).
skillsdock init skill [name] scaffolds a SKILL.md template with valid frontmatter plus Description, When To Use, and Instructions sections. If [name] is omitted, SkillsDock writes SKILL.md in the current directory and derives the default skill name from the directory name. Existing SKILL.md files are never overwritten.
For skill-md universal agents, the default config also seeds canonical scan sources:
agents-user->~/.agents/skillsagents-project->${projectRoot}/.agents/skills
Add Command
skillsdock add <source> installs skills from a remote repository or local directory into the canonical .agents/skills directory.
Source Formats
owner/repo— GitHub shorthand, installs all SKILL.md files from the repositoryowner/repo@skill-name— Install a specific skill from a repositoryhttps://github.com/owner/repo/tree/branch/path— Full GitHub URL with optional branch and subpathhttps://gitlab.com/owner/repo/-/tree/branch/path— Full GitLab URL./path/to/skillsor/absolute/path— Install from a local directory
Options
--scope user|project— Installation target (default:user)user: installs to~/.agents/skills/<skill-name>/project: installs to${projectRoot}/.agents/skills/<skill-name>/
--dry-run— Preview what would be installed without writing files--copy— Force copy mode; skip creating symlinks to non-universal agent directories
Behavior
- GitHub/GitLab sources are cloned with
git clone --depth 1 --single-branch - SKILL.md files are discovered in the root,
skills/, and.agents/skills/directories - Each skill is validated (frontmatter must include
nameanddescription); invalid files are skipped with a warning - Skills are copied to the canonical directory; by default, symlinks are created in non-universal agent directories
- The SkillsDock registry is updated with installed skill metadata
- The
.skill-lock.jsonlockfile is updated for the active scope - Temporary clone directories are always cleaned up
Examples
# install all skills from a GitHub repo to user scope
skillsdock add acme/awesome-skills
# install one specific skill
skillsdock add acme/awesome-skills@lint-check
# install from a specific branch + path
skillsdock add https://github.com/acme/skills/tree/v2/curated
# install from local directory to project scope
skillsdock add ./my-skills --scope project
# preview without writing
skillsdock add acme/awesome-skills --dry-runCheck Command
skillsdock check detects available updates for installed skills by comparing local content hashes against remote GitHub tree data.
How It Works
- Reads tracked skills from
skills-lock.jsonand the SkillsDock registry - For each GitHub-sourced skill, fetches the repository tree via the GitHub Trees API
- Skills from the same repository are batched into a single API call (avoids N+1)
- Computes a SHA-256 fingerprint from the remote tree and compares it to the locally stored hash
- Reports which skills are up to date, which have updates, and which were skipped
Options
--json— Output machine-readable JSON instead of human-readable text
GitHub Authentication
Token resolution (in priority order):
GITHUB_TOKENenvironment variableGH_TOKENenvironment variablegh auth tokenCLI command
Without a token, unauthenticated requests are used (60 requests/hour). When rate-limited, a helpful message is shown.
Examples
# check all tracked skills
skillsdock check
# machine-readable output
skillsdock check --json
# with authentication for higher rate limits
GITHUB_TOKEN=ghp_xxx skillsdock checkText Output
✓ 3 skills up to date
⚡ 2 skills have updates available:
- typescript-skill (vercel-labs/agent-skills)
- react-skill (vercel-labs/agent-skills)
⏭ 1 skill skipped (no source URL)JSON Output
{
"upToDate": [{ "name": "my-skill", "source": "owner/repo" }],
"updatesAvailable": [{ "name": "stale-skill", "source": "owner/repo", "currentHash": "...", "remoteHash": "..." }],
"skipped": [{ "name": "local-skill", "reason": "no source URL" }]
}Update Command
skillsdock update automatically re-installs skills that have available updates.
How It Works
- Runs the same freshness detection as
check - For each outdated skill, re-clones the source repository and re-installs the skill
- Updates
skills-lock.jsonwith the new content hash
Options
--scope user|project— Installation target (default:project)--dry-run— Preview which skills would be updated without writing files
Examples
# update all outdated project-scope skills
skillsdock update --scope project
# preview what would be updated
skillsdock update --dry-run
# update user-scope skills
skillsdock update --scope userFind Command
Search for skills in the skills.sh ecosystem.
Non-interactive mode
# search by keyword
skillsdock find typescript
# machine-readable JSON output
skillsdock find react --jsonResults are displayed as a formatted table with name, source, and description. Install a discovered skill with skillsdock add <source>.
Interactive mode
When run without a query in a TTY terminal, find launches an interactive search:
skillsdock find
# Search skills: _ (type to search, Enter to confirm, Ctrl+C to exit)The interactive mode uses debounced input (200ms) to show live results as you type.
Error handling
- Network unreachable: prints a connection error and exits with non-zero status
- API errors (non-200): prints the HTTP status and exits with non-zero status
- Timeout (5s): prints a timeout message and exits with non-zero status
Sync Modes
- Default mode:
--mode symlink - Fallback policy:
--fallback copy
Behavior:
- If format conversion is needed, sync auto-copies (symlink is not possible).
- Built-in
skill-mdtargets now sync canonical-first:- universal agents write directly into
.agents/skills - non-universal
skill-mdagents mirror from.agents/skillswith a symlink
- universal agents write directly into
- If symlink fails and fallback is
copy, SkillsDock copies and prints a warning. - Symlink mode resolves destination parent symlinks before computing the link target, so symlinked target roots do not produce broken links.
- If source and destination already resolve to the same real path, sync is a no-op for that item.
- Existing broken or circular destination symlinks are replaced safely during sync.
- Atomic copy writes are used (
tmp+rename).
Remove
skillsdock remove cleans up installed skill files, symlinks, and metadata:
# remove a single skill by id, key, or path
skillsdock remove my-skill --scope user
# dry run — preview what would be deleted
skillsdock remove my-skill --scope user --dry-run
# force remove a frozen skill
skillsdock remove my-skill --scope user --force
# remove all skills in a scope
skillsdock remove --all --scope projectBehavior:
- Deletes the canonical skill directory under
.agents/skills/<skill-name>/. - Scans non-universal agent directories and removes symlinks pointing to the canonical skill.
- Sets the registry tag to
deleted(soft delete). - Removes the skill entry from
skills-lock.jsonif present. frozenskills are skipped unless--forceis used.--dry-runprints all planned actions without writing to disk.--allrequires--scopeand removes every (non-frozen) skill in that scope.
Syncing Skills From node_modules
SkillsDock can discover and install skills published as npm packages:
# discover and sync all skills from node_modules (project scope)
skillsdock sync --from node_modules
# preview what would be synced without writing files
skillsdock sync --from node_modules --dry-run
# sync to user scope instead of project
skillsdock sync --from node_modules --scope userHow It Works
- Discovery: scans
node_modulesfor packages containingSKILL.mdfiles. Each package is checked at three locations: package root,skills/, and.agents/skills/. Scoped packages (@org/pkg) are fully supported. - Incremental diff: computes a SHA-256 hash of each discovered skill directory and compares it against
skills-lock.json. Skills with unchanged hashes are skipped. - Install/Update: new or changed skills are copied into
.agents/skills/<skill-name>/and the lockfile is updated withsourceType: "node_modules". - Lockfile tracking: each synced skill is recorded in
skills-lock.jsonwith the npm package name assource.
Output
The command prints a summary showing:
- Total skills discovered
- Skills skipped (unchanged)
- Skills installed (new)
- Skills updated (hash changed)
Supported Formats
skill-md(SKILL.md,.skill)mdc(*.mdc)openclaw-md(*.md)opencode-md(*.md)
skill-md Parsing Rules (v0.2.0)
SkillsDock v0.2.0 aligns local SKILL.md parsing with the conventions used by vercel-labs/skills:
SKILL.mdmust include YAML frontmatter.- Frontmatter must include string
nameand stringdescription. metadata.internal: trueis treated as internal and skipped by default.- Set
INSTALL_INTERNAL_SKILLS=1(ortrue) to include internal skills inscan.
- Set
- Discovery prioritizes common skills directories and
.claude-pluginmanifest-declared paths, then recursively scans as fallback. .claude-plugin/marketplace.jsonand.claude-plugin/plugin.jsonownership is persisted aspluginNameon matching registry items.scanalso readsvercel-labs/skillsglobal lock metadata from$XDG_STATE_HOME/skills/.skill-lock.jsonor~/.agents/.skill-lock.jsonin read-only mode.- matched
~/.agents/skills/<name>/SKILL.mdfiles retain additive external metadata (externalSourceUrl,externalHash,externalPluginName, etc.) - unmatched lock entries do not create synthetic skills; local files still control visibility
- matched
- Frontmatter parsing uses gray-matter for compatibility and YAML edge cases.
Grouped Text Views
skillsdock listprints stable sections in this order:Ungrouped- each plugin name in lexical order
Mixed Plugin Ownership(only when an aggregated row spans multiple plugin owners)
skillsdock all-local-skillsuses the same grouped section ordering.--jsonremains backward compatible:- top-level shape is still
{ "count": number, "items": [...] } - registry items may now include
pluginName - registry items may now include
externalSourceUrl,externalHash,externalPluginName,externalSourceType, and related read-only interop fields - aggregated
all-local-skillsrows may now includepluginNameandpluginNames
- top-level shape is still
Skills Spec Validation
Use doctor --skills-spec to validate local skill-md sources against the Agent Skills specification conventions:
- validates
SKILL.mdparseability and required frontmatter fields - validates name style (recommended lowercase + hyphen, up to 64 chars)
- validates
.claude-plugin/marketplace.jsonand.claude-plugin/plugin.jsonpath safety and local-path conventions
Config (v2)
Default config file: ~/.skillsdock/config.json
{
"version": 2,
"sources": [
{
"name": "agents-user",
"agent": "agents",
"scope": "user",
"path": "~/.agents/skills",
"format": "skill-md",
"optional": true
},
{
"name": "openclaw-user",
"agent": "openclaw",
"scope": "user",
"path": "~/.openclaw/skills",
"format": "openclaw-md",
"optional": true
},
{
"name": "agents-project",
"agent": "agents",
"scope": "project",
"path": "${projectRoot}/.agents/skills",
"format": "skill-md",
"optional": true
}
],
"targets": {
"openclaw-user": {
"name": "openclaw-user",
"agent": "openclaw",
"scope": "user",
"path": "~/.openclaw/skills",
"format": "openclaw-md",
"layout": "flat",
"extension": ".md"
}
},
"scan": {
"maxDepth": 8,
"ignoreDirs": ["node_modules", ".git", ".next", "dist", "build", ".turbo", ".cache"]
}
}Registry
SkillsDock stores metadata in ~/.skillsdock/registry.json.
Registry version 2 includes:
- canonical keys (
path:/abs/path/to/skill/SKILL.md) - compatibility indexes:
index.byCanonicalPathindex.byLegacyKey
- item policy fields:
policy.tagpolicy.reasonpolicy.updatedAt
- plugin ownership field:
pluginName
- optional read-only interop fields:
externalSourceexternalSourceTypeexternalSourceUrlexternalSkillPathexternalHashexternalPluginNameexternalInstalledAtexternalUpdatedAt
- structure manifest fields:
structureManifest.entryFilestructureManifest.includedFilesstructureManifest.fileHashesmanifestHash
- cleanup history:
cleanupHistory[].runIdcleanupHistory[].actions[]
Compatibility Matrix
See COMPATIBILITY.md.
Built-In Agent Registry
| Agent Name | ID | User Scope Path | Project Scope Path | Install Family |
|---|---|---|---|---|
| OpenClaw | openclaw | ~/.openclaw/skills | ${projectRoot}/skills | dedicated |
| Codex | codex | ~/.codex/skills | ${projectRoot}/.codex/skills | universal |
| Claude | claude | ~/.claude/skills | ${projectRoot}/.claude/skills | dedicated |
| Cursor | cursor | ~/.cursor/rules | ${projectRoot}/.cursor/rules | universal |
| Cline | cline | ~/.cline/rules | ${projectRoot}/.cline/rules | universal |
| CodeBuddy | codebuddy | ~/.codebuddy/skills | ${projectRoot}/.codebuddy/skills | dedicated |
| Trae | trae | ~/.trae/skills | ${projectRoot}/.trae/skills | dedicated |
| OpenCode | opencode | ~/.opencode/skills | ${projectRoot}/.opencode/skills | universal |
| Amp | amp | ~/.config/agents/skills | ${projectRoot}/.agents/skills | universal |
| Antigravity | antigravity | ~/.gemini/antigravity/skills | ${projectRoot}/.agents/skills | universal |
| Augment | augment | ~/.augment/skills | ${projectRoot}/.augment/skills | dedicated |
| Command Code | command-code | ~/.commandcode/skills | ${projectRoot}/.commandcode/skills | dedicated |
| Continue | continue | ~/.continue/skills | ${projectRoot}/.continue/skills | dedicated |
| Cortex Code | cortex | ~/.snowflake/cortex/skills | ${projectRoot}/.cortex/skills | dedicated |
| Crush | crush | ~/.config/crush/skills | ${projectRoot}/.crush/skills | dedicated |
| Deep Agents | deepagents | ~/.deepagents/agent/skills | ${projectRoot}/.agents/skills | universal |
| Droid | droid | ~/.factory/skills | ${projectRoot}/.factory/skills | dedicated |
| Gemini CLI | gemini-cli | ~/.gemini/skills | ${projectRoot}/.agents/skills | universal |
| GitHub Copilot | github-copilot | ~/.copilot/skills | ${projectRoot}/.agents/skills | universal |
| Goose | goose | ~/.config/goose/skills | ${projectRoot}/.goose/skills | dedicated |
| Junie | junie | ~/.junie/skills | ${projectRoot}/.junie/skills | dedicated |
| iFlow CLI | iflow-cli | ~/.iflow/skills | ${projectRoot}/.iflow/skills | dedicated |
| Kilo Code | kilo | ~/.kilocode/skills | ${projectRoot}/.kilocode/skills | dedicated |
| Kimi Code CLI | kimi-cli | ~/.config/agents/skills | ${projectRoot}/.agents/skills | universal |
| Kiro CLI | kiro-cli | ~/.kiro/skills | ${projectRoot}/.kiro/skills | dedicated |
| Kode | kode | ~/.kode/skills | ${projectRoot}/.kode/skills | dedicated |
| MCPJam | mcpjam | ~/.mcpjam/skills | ${projectRoot}/.mcpjam/skills | dedicated |
| Mistral Vibe | mistral-vibe | ~/.vibe/skills | ${projectRoot}/.vibe/skills | dedicated |
| Mux | mux | ~/.mux/skills | ${projectRoot}/.mux/skills | dedicated |
| Neovate | neovate | ~/.neovate/skills | ${projectRoot}/.neovate/skills | dedicated |
| OpenHands | openhands | ~/.openhands/skills | ${projectRoot}/.openhands/skills | dedicated |
| Pi | pi | ~/.pi/agent/skills | ${projectRoot}/.pi/skills | dedicated |
| Qoder | qoder | ~/.qoder/skills | ${projectRoot}/.qoder/skills | dedicated |
| Qwen Code | qwen-code | ~/.qwen/skills | ${projectRoot}/.qwen/skills | dedicated |
| Replit | replit | ~/.config/agents/skills | ${projectRoot}/.agents/skills | universal |
| Roo Code | roo | ~/.roo/skills | ${projectRoot}/.roo/skills | dedicated |
| Trae CN | trae-cn | ~/.trae-cn/skills | ${projectRoot}/.trae-cn/skills | dedicated |
| Warp | warp | ~/.agents/skills | ${projectRoot}/.agents/skills | universal |
| Windsurf | windsurf | ~/.codeium/windsurf/skills | ${projectRoot}/.windsurf/skills | dedicated |
| Zencoder | zencoder | ~/.zencoder/skills | ${projectRoot}/.zencoder/skills | dedicated |
| Pochi | pochi | ~/.pochi/skills | ${projectRoot}/.pochi/skills | dedicated |
| AdaL | adal | ~/.adal/skills | ${projectRoot}/.adal/skills | dedicated |
Each registry entry includes:
- native
user+projectscope source/target presets detectInstalledpaths fordoctor --agentsinstallFamilyandcanonicalDirmetadata for follow-up universal-agent logic
Publish
npm run pack:check
npm publish --access publicLicense
MIT
