Repository navigation
Releases: skillmds/skillmd
Release list
skillmds@1.3.3
See CHANGELOG.md
skillmds@1.3.2
skillmds@1.3.1
skillmds@1.3.0
skillmds@1.2.1
skillmds@1.2.0
skillmd add was rewritten. It no longer copies a skill into every agent folder it can find: it writes one canonical copy and links that copy into the agents you chose, in the scope you chose, and records what it did in a lock file.
Never litters your folders
- In a terminal,
addasks Installation scope: Project / Global before writing anything, then which of the detected agents to link into. The agent selection is remembered and pre-checked next time. - With
-y,--json, piped stdin, or inside a host agent (Claude Code, Cursor, Codex, Gemini CLI, CI) the scope is auto-detected: project when the current directory carries.git,package.json,pyproject.toml,Cargo.toml,go.mod,AGENTS.md,CLAUDE.md,skills-lock.jsonor an agent dot-dir, global otherwise. The run says which it picked. - A piped run with neither
-ynor a scope flag now exits 1 with a hint instead of guessing. Runningskillmd add owner/namefrom your Desktop no longer scatters.claude/,.cursor/,.codex/,.agents/there. - New
-p, --projectforces the current directory;-g, --globalis unchanged. Cancelling a prompt installs nothing. - Project installs only touch agents that are already present in the project (or named with
-a) —add -pnever creates a folder for an agent the project does not use.
One canonical copy, links everywhere
- The skill's files are written once to
.agents/skills/<name>(project) or~/.agents/skills/<name>(global). Each chosen agent directory gets a junction (Windows) or symlink (everywhere else) pointing at it; if the filesystem refuses, the CLI falls back to a copy and says so. --mode link|copypicks between the two (linkis the default). The old--copyspelling still works as a hidden alias.- Writes are staged and moved into place, so an interrupted install never leaves a half-written skill behind.
addrefuses to replace a skill installed from a different source, or a directory it does not track, unless you pass--force.- Local directory sources install all of the skill's files. GitHub and gist sources install
SKILL.mdonly for now; registry installs deliver the full bundle.
Lock files
- Project installs write
skills-lock.jsonnext to your code — sorted, no timestamps, designed to be committed and to produce clean diffs. Global installs write~/.skillmd/lock.json. - Each entry records the
source, thecommit_shait came from, adigestof the installed files, theagentsit is linked into, and the linkmodeper agent.list,update,checkandremoveall read it.
Real source grammar
One parser now decides what a <source> argument means, and every command uses it:
owner/name— a registry slug (GitHub is the fallback).owner/repo#ref— a branch, tag or commit.owner/repo/sub/path— a subdirectory of a repo.owner/repo@skill— one named skill inside a repo or pack.github:owner/repo/gh:owner/repo— force the GitHub reading of a bareowner/name.- GitHub
tree/andblob/URLs, with the ref in the URL preserved (ablobURL pointing at aSKILL.mdresolves to its directory). - Gist URLs.
--ref <ref>overrides the ref on any GitHub source;-l, --listprints the skills a source contains without installing anything.- GitLab and
git@/ssh://sources get a clear "clone it locally and runskillmd add ./path/to/skill" message instead of a confusing 404.
Production behaviour
list/ls— both scopes by default (-g,-pto narrow,-ato filter by agent,--json). Columns: name · scope · agents · mode · source. Skills that are on disk but not in a lock file — hand-made, or installed by 1.1.x — are taggeduntracked.remove/rm— takes[names...]or opens a picker; confirms unless-y.--allremoves everything in scope (not combinable with names).-aunlinks only those agents and leaves the canonical copy alone;-g/-pnarrow the scope, both are searched by default.--jsonsupported; exits 1 when nothing was removed.update [names]— lock-driven: it refreshes the full bundle from the source recorded for each skill, re-lints before writing, and short-circuits when the recordedcommit_shahas not moved.--checkreports without writing,-g/-pnarrow the scope,--jsonis supported, and any failure exits 1. Untracked skills are reported and skipped with "reinstall withskillmd add".- New
checkcommand —update --checkunder its own name. login/logout/initnever prompt off a TTY: they exit 1 naming the flags to pass instead of hanging an agent or a CI job. All three accept--json.- A stored token is now bound to the API host it was saved for, so a token for one registry is never sent to another.
http://bases are refused unless you pass--insecure-http. --tokenon a terminal prints a warning on stderr: it lands in shell history and in everypslisting — preferskillmd loginorSKILLMD_TOKEN.
Security
- Every file in a registry bundle must carry a sha256 and match it, including companion files delivered by URL. A missing or mismatched hash refuses the install rather than writing unverifiable content. The one exception is the bundle's inline
SKILL.md: the registry generates that file from the skill's stored record rather than storing it, so there is no hash to compare it against. Every other path, hashed or not, is either verified or refused. - Registry bundles are capped at 200 files / 20 MB. Every registry, GitHub raw and gist request carries a 30 s timeout; the repository download itself runs through
giget, which takes no deadline — it is bounded instead by the pre-download size check against the GitHub tree API and by the same 200 files / 20 MB caps once the files are on disk. Temp directories are cleaned up on both the success and the failure path. - Terminal escape sequences are stripped from registry text before it is printed, so a description can never repaint your terminal.
- Windows reserved device names (
con,nul,lpt1, …) are refused as skill or file names. - The install-count
POST /api/skills/<owner>/<name>/install(body{"via":"cli"}, nothing else) is documented in the README and skipped entirely whenSKILLMD_NO_TELEMETRY=1orDO_NOT_TRACK=1is set.
MCP server rewritten in TypeScript
- The server is now TypeScript on the same code path as the CLI — one installer, one source parser, one sanitiser, one set of schemas.
skillmd_installgainedscope,agents,mode,forceanddeny, and installs through the canonical-copy-plus-links model like the CLI.destis deprecated: it is accepted only when it points at a known agent skills directory. Usescope+agents.skillmd_lintdiagnostics declare the correct severity enum (warn, notwarning).skillmd_list_savedresults go through the same sanitiser as every other tool's output.
Agent table refreshed
- codex, goose, amp and zed use the cross-agent
.agents/skillsconvention; gemini-cli uses.gemini/skills; antigravity uses.agent/skills; droid uses.factory/skills. CLAUDE_CONFIG_DIRandCODEX_HOMErelocate those agents' global directories.- Project-only agents (eve, promptscript) no longer claim a global directory.
- Legacy directories stay in the detection list, so an existing install is still found.
Removed
--copyis now a hidden alias of--mode copy(still works, no longer advertised).- The
yamldependency — nothing imported it since the validation engine moved to@skillmds/core. lint's undocumentedcheckalias, which collided with the newcheckcommand. Useskillmd lint.
Upgrade notes
- A token saved by an earlier
skillmd login --api <other-host>is now treated as bound toapi.skillmd.com. If you use a different registry, re-runskillmd login --api <url>. - Skills installed by 1.1.x show as
untrackedinlistand are skipped byupdate. Re-runskillmd addon them once to bring them under the lock file. - If a script used
skillmd check .to lint, change it toskillmd lint .—checknow reports available updates.
skillmds@1.1.2
- MCP tool metadata. Every tool now declares a
title,annotations(all read-only exceptskillmd_install, none destructive), anoutputSchema, and a description on every parameter; list-returning tools respond withstructuredContent: { items },skillmd_lintandskillmd_installreturn structured results, and refusals are flaggedisError. - Server metadata.
initializereports a title, description, website URL, icons and usage instructions. - No behavior changes to what the tools do.
skillmds@1.1.1
- Releases are now published through npm Trusted Publishing (OIDC from GitHub Actions) with provenance; no long-lived npm tokens exist for this package.
- README: links to the registry's browse surfaces (search, categories, publishers, per-agent install guides, docs, stats) so the npm page points at where the skills live.
- No CLI or MCP behavior changes.
skillmds@1.1.0
- Open source.
skillmdsnow develops in the open at github.com/skillmds/skillmd, and a MITLICENSEfile ships in the package (the manifest always claimed MIT; now the text does too). - The validation engine is its own package. The lint/security/quality engine is published as
@skillmds/coreand consumed as a regular dependency. The bundledvendor/copy is gone — anything that deep-importedskillmds/vendor/index.js(an undocumented internal) should import@skillmds/coreinstead. - MCP setup snippets standardize on the server alias
skillmd(claude mcp add skillmd -- npx -y skillmds). Existing configs with other aliases keep working — the alias is client-side. - README correction: registry installs have not been gated on verification since 1.0.16.
- No CLI or MCP behavior changes.
@skillmds/core@1.0.0
-
Published under the
@skillmdsscope (matching theskillmdspackage and the github.com/skillmds org). Earlier docs referred to it as@skillmd/core; that name was never published. -
First public release. The engine that has powered the SkillMD registry, the
skillmdCLI, and theskillmdsMCP server (previously bundled insideskillmdsas a private vendor build) is now its own package. -
Exports:
parseSkillMd,lint,runRules/RULES,scanSecurity,qualityScore, thetoText/toJson/toSarif/toGithubformatters, and the registry helpersskillMdFor,reconstructSkillMd,isAllowedSourceUrl. -
ESM-only, typed, no runtime dependency beyond
yaml.