knack
← all posts

Claude Skill Versioning: How to Actually Track Versions of a Skill

There is no built-in version field in SKILL.md. How people actually version skills: git on the folder, a changelog, the metadata version convention, and real semver in plugin manifests.

Start with the part nobody says out loud. The open Agent Skills format does not have a required version field in SKILL.md frontmatter. Claude skill versioning is something you build yourself, with git and a changelog. The spec does not hand it to you. If you came here looking for the canonical line of YAML that stamps a version on your skill, I'll save you the search: it does not exist.

Here is the verified frontmatter spec as of June 2026. The Agent Skills specification at agentskills.io requires exactly two fields: name and description. It allows four optional ones: license, compatibility, metadata, and an experimental allowed-tools. That is the whole list. The Claude Code frontmatter reference adds its own client-specific fields (disable-model-invocation, model, context, and others) and it also has no version field. Same answer on platform.claude.com: required fields are name and description, full stop.

So where do people get the idea there's a version field?

The claude skill version field that isn't a field

The confusion comes from one line in the spec's own example. It shows metadata with a child key called version:

---
name: pdf-processing
description: Extract PDF text, fill forms, merge files. Use when handling PDFs.
license: Apache-2.0
metadata:
  author: example-org
  version: "1.0"
---

Read what metadata actually is. The spec calls it an arbitrary key-value mapping that clients can use to store properties the standard does not define. A version stuffed in there is a note to humans, plus a hook for whatever tooling chooses to read it. No Claude surface treats metadata.version as authoritative. Bump it from 1.0 to 2.0 and nothing in Claude Code, claude.ai, or the API changes behavior. It is documentation in a YAML costume.

I still set it. A skill md version string in metadata is a cheap, honest signal of which iteration someone is looking at, and it travels inside the file when the skill gets copied around. Think of it as a label that records a version without enforcing one.

Claude skill versioning for a skill people actually rely on

The real unit of versioning for a skill is the folder, and the tool for the job is git. A skill is a directory: SKILL.md plus whatever scripts, references, and templates you bundle. Commit that directory. Now every change carries a SHA, a diff, a timestamp, and an author, which beats any hand-typed version string for precision. When you share project skills, the official Claude Code guidance is to commit .claude/skills/ to version control. That is the supported path.

Pair the git history with a CHANGELOG.md next to SKILL.md. Git tells you what bytes changed, while a changelog tells a human why, and which behavior to expect to differ. For a skill a team depends on, the changelog is the gap between "the deploy skill got smarter" and "the deploy skill now refuses to run if the test suite is red, here is the date that started." Tag releases in git if you want named points to roll back to. None of this is skill-specific ceremony, though. It is the same discipline you would apply to any small library, because a shared skill is exactly that.

If you want a real, enforced version with update semantics, ship the skill inside a plugin.

Plugins are where versioning gets teeth

A Claude Code plugin has a plugin.json manifest, and that manifest carries a genuine version field. Semantic versioning, MAJOR.MINOR.PATCH, the whole convention. This is the one place a skill's version string does real work.

The mechanics: Claude Code resolves a plugin's version from the first of these it finds, the version in plugin.json, then the version in the marketplace entry, then the git commit SHA of the source, then unknown. It uses that resolved version as a cache key. When a user runs /plugin update, Claude Code compares versions and skips the update if they match. The behavior then splits two ways. Set an explicit version and users only get changes when you bump the field, even after you have pushed ten commits since. Leave it unset and every new commit to the git source counts as a new version, so users track your latest automatically.

That second mode is the gotcha. People set "version": "1.0.0", push fixes for a week, and then wonder why /plugin update keeps reporting "already at the latest version." Anthropic's own reference spells out the fix: if you pin a version, you have to bump it every time you want changes to land. For a skill under active internal development, leaving the version unset and riding the commit SHA is usually the saner default.

Updating an installed or shared skill

For a filesystem skill in Claude Code, updating means editing the files. Claude Code watches ~/.claude/skills/, the project .claude/skills/, and any --add-dir skills directory, and it picks up SKILL.md text changes within the running session, no restart. A shared project skill updates the way any committed file does: someone pushes, teammates pull, done. Your git history doubles as the version log.

For a plugin skill, the update goes through /plugin update, governed by the version rules above. For a skill uploaded to claude.ai or the Claude API, there is no auto-sync. The docs are explicit that custom skills do not sync across surfaces, so re-uploading to each one is on you.

A take on keeping team versions sane

Pick one source of truth and make it git. Do not let four people keep four lightly-edited copies of the same SKILL.md in their personal ~/.claude/skills/ and call the newest one "v3." That is how you end up with a skill that behaves differently for everyone on the call. Put shared skills in the repo, review changes in pull requests the way you review code, keep a one-line changelog entry per meaningful change, and reserve a real semver string for the moment you wrap the skill in a plugin and publish it. Keep the metadata.version line as a label if you like it, but remember that the commit is what actually pins your version.

Authoring from scratch? The field rules and description craft matter more than the version note. See Claude skill best practices for that, and where to publish a SKILL.md for getting it in front of a team.

You can also skip the YAML entirely. Knack turns a short interview into a valid SKILL.md folder you can drop straight into git, which means your first commit is your first version and you never hand-edit frontmatter to get there.