Skill Provenance
The Problem This Solves
Skill projects move between sessions, surfaces (Chat, IDE, CLI, Cowork),
platforms (Claude, Gemini CLI, Codex, Copilot), and local storage
(Obsidian, working directories, git repos). Version identity gets lost
when it lives only in filenames. A file renamed from SKILL_v4.md to
SKILL_v5.md with no internal record of what changed creates ambiguity.
This skill establishes three conventions that prevent that:
- 1. Version identity lives inside files when their format allows it, and
always in the manifest.
- 2. A recent changelog travels with the skill bundle, while longer history
can live in the source repo.
- 3. A manifest lists all files in the bundle so any session can verify completeness.
What Gets Versioned
A skill bundle is a SKILL.md plus all associated files. Typical contents:
- - SKILL.md (the skill definition)
- evals.json (evaluation suite)
- Generation scripts (e.g., generate.js, generate.py)
- Output artifacts (.docx, .pdf) produced by evals or real use
- Handoff notes
- Source material provided by the user (tracked but not versioned)
The skill itself (SKILL.md) and evals are the primary versioned artifacts.
Scripts and outputs are tracked by the manifest but version with the bundle
rather than independently. Handoff notes are optional convenience artifacts.
Internal Version Header
Files that can safely carry YAML frontmatter begin with a YAML frontmatter
block (or extend an existing one) containing these fields:
CODEBLOCK0
Rules
version is an integer for per-file tracking. It counts revisions to
that specific file within the bundle. The bundle-level version
(bundle_version in MANIFEST.yaml) uses semver.
change_summary is required for every version after v1. One to three
sentences. It must describe what changed, not just that something changed.
previous_version creates a chain. Any session can trace the lineage.
file_role values:
- -
skill — the SKILL.md itself - INLINECODE4 — the evals.json file
- INLINECODE5 — generation scripts, utility scripts
- INLINECODE6 — rendered artifacts (.docx, .pdf)
- INLINECODE7 — session handoff notes
- INLINECODE8 — user-provided source material (tracked, not versioned)
- INLINECODE9 — documentation in references/ loaded on demand
- INLINECODE10 — templates, images, fonts in assets/ used in output
- INLINECODE11 — platform UI metadata (e.g., Codex's agents/openai.yaml)
For files that cannot safely carry YAML frontmatter (binary files and
strict-format files such as .json or executable .sh), the manifest
tracks their version and its version field is authoritative.
SKILL.md frontmatter constraint: The Agent Skills open standard
(agentskills.io) requires name and description. Different platforms
enforce different rules about additional fields:
| Platform | Allowed SKILL.md frontmatter |
|---|
| agentskills.io spec | INLINECODE17 , description, license, metadata, compatibility, INLINECODE22 |
| Claude Chat / Settings UI |
Same as spec. Claude's settings importer rejects unrecognized fields. |
|
Claude Code | Spec fields plus extensions:
disable-model-invocation,
user-invocable,
context,
agent,
model,
hooks,
argument-hint. These are Claude Code features, not part of the base spec. |
|
Claude API | Skills uploaded via
/v1/skills. Validates
name and
description. Supports
metadata. |
|
Gemini CLI (Google) |
name and
description only. Extra fields not officially supported. |
|
Codex (OpenAI) |
name and
description only. Extra fields rejected. |
|
GitHub Copilot / VS Code | Follows agentskills.io spec. |
|
Cursor, Roo Code, Junie, others | Follows agentskills.io spec. See agentskills.io for the full adopter list (30+). |
For maximum portability, keep SKILL.md frontmatter to name and
description only. If the canonical bundle needs attribution or visible
SKILL.md metadata, use the spec's metadata field there and generate a
derived minimal copy for strict platforms:
CODEBLOCK1
If targeting Codex or other strict platforms directly, omit metadata
from SKILL.md entirely. The manifest tracks SKILL.md's version either
way, so no version information is lost.
Note on spec support: The agentskills.io spec formally supports
metadata as an arbitrary key-value map, with version shown as an
example use. This means the metadata.version approach is now
spec-blessed, not a Claude-only extension. However, the spec's version
is a static label — it does not address staleness tracking, changelogs,
or bundle integrity. Prefer manifest-based tracking as the default and
use metadata only when you need version info visible in the file
itself.
Manifest
The manifest is a YAML file named MANIFEST.yaml at the root of the skill
bundle directory — the same level as SKILL.md. When the bundle is
packaged as a .skill ZIP, the manifest lives inside the ZIP. It is the
single source of truth for what the bundle contains.
CODEBLOCK2
Rules
bundle_version uses semver (MAJOR.MINOR.PATCH). Bump MAJOR for
breaking changes to the skill's model or interface, MINOR for new
features or capabilities, PATCH for fixes and documentation updates.
Per-file version fields remain integers — they are revision counters,
not release identifiers.
hash is sha256 of the file contents. This is how a new session verifies
that the file it received matches what the manifest claims. Compute on save,
verify on load.
deployments is optional. Use it to record deployed or installed copies
of the same bundle when you want traceability across surfaces. Keep
bundle_version as the author-side semver source of truth. Platform-native
versions (for example API timestamps) stay in deployments, not in
bundle_version.
version: null for source files. They are tracked for completeness but
not versioned by this system.
Paths are relative to the bundle root. No absolute paths.
MANIFEST.yaml is not listed in files. Self-hashing is recursive. Treat
the manifest as the bundle's control file and verify it via git, transport
checksums, or the surrounding package when needed.
The .skill Package Format
Claude's settings UI exports and imports skills as .skill files. These
are standard ZIP archives containing a directory named after the skill.
The versioning artifacts (MANIFEST.yaml, CHANGELOG.md, README.md)
live inside this directory at the same level as SKILL.md:
CODEBLOCK3
Claude's settings importer only looks for SKILL.md and the directory
structure it expects (references, assets). It ignores files it doesn't
recognize. This means the versioning artifacts travel safely inside the
.skill ZIP without affecting import/export behavior.
When bootstrapping or updating a bundle, always include the versioning
artifacts in the .skill ZIP so they survive round-trips through
Claude's settings UI.
Some uploaders only accept .zip or .md. In those cases, rename the
archive from .skill to .zip without changing its contents.
The spec recommends keeping SKILL.md under 500 lines and moving detailed
reference material to separate files. Provenance artifacts fit naturally
into that model: MANIFEST.yaml and CHANGELOG.md are load-on-demand
resources, not always-loaded instructions.
Claude Code provides a ${CLAUDE_SKILL_DIR} variable for bundle-relative
paths. Other platforms may not. Direct relative paths like
./validate.sh work when the working directory is the bundle root.
The .skill ZIP only carries the skill definition and its references.
Bundles can still track evals, scripts, rendered outputs, and handoff
notes outside the archive. The manifest remains the complete inventory,
not just the package inventory.
Changelog
The changelog is a file named CHANGELOG.md at the root of the skill
bundle directory, alongside SKILL.md and MANIFEST.yaml. In the
bundle, it carries recent history with newest entries at the top. If the
canonical source lives in git, older entries can be archived in a
repo-level changelog outside the bundle.
CODEBLOCK4
Rules
Each entry names every file that changed and what changed in it.
Files that are stale get called out. If SKILL.md changes but evals.json
was not updated to match, the changelog says so. This prevents the silent
drift that caused the v4/v5 confusion.
Entries are human-written prose, not auto-generated diffs. The point is
to communicate intent, not enumerate line changes. Git diffs are available
when the bundle is in git.
Bundle changelogs can be trimmed. Keeping the last 5-15 entries in
the bundle is reasonable if the source repository maintains a full
append-only changelog elsewhere.
Session Protocol
Opening a session
When a skill bundle is loaded into a new session:
- 1. Read
MANIFEST.yaml first. - Verify all listed files are present. Report any missing files.
- For files with hashes, verify hashes match. Flag mismatches. In
local environments, users can run
validate.sh before uploading
for reliable hash verification without LLM computation.
- 4. Read
CHANGELOG.md to understand recent changes. - Check for staleness: if any file's version is lower than the bundle
version, or if
deployments clearly show a deployed copy behind the
local bundle, flag it and ask the user whether it needs updating.
- 6. If
MANIFEST.yaml is missing, treat the bundle as unversioned. Offer
to create one by inventorying the files and asking the user for version
context.
Saving / closing a session
When work is complete and files are being delivered:
- 1. Update internal version headers for changed files that use them.
- Update
MANIFEST.yaml with new versions and hashes for every changed
versioned file, including manifest-only files. If the user deployed or
reinstalled the skill this session, update any relevant
deployments
metadata too.
- 3. Add a new top entry to
CHANGELOG.md. - If any versioned file was changed but another dependent file was not
updated (e.g., SKILL.md changed but evals.json was not updated), note
the staleness explicitly in the changelog entry.
- 5. Deliver the full bundle to the user, or at minimum the changed files
plus the updated MANIFEST.yaml and CHANGELOG.md.
- 6. If the user indicates the bundle is destined for a git repo, provide
a ready-to-use commit message derived from the changelog entry. Format:
CODEBLOCK5
Return the message inline by default. Only write a transient
git_commit.txt file if the user explicitly asks for a file or if the
environment makes file output materially more convenient.
Handoff between sessions
A handoff note is a snapshot of project state for the next session. It
should include:
- - Current bundle version
- What was accomplished this session
- What is stale and needs attention
- What the next session should do first
- Any decisions made that are not yet reflected in the files
- Per-file change summaries: for each file modified this session, a
brief description of what changed (section added, field removed,
logic rewritten, etc.). This is more granular than the changelog
entry and helps the next session verify the work without re-reading
every file.
Create a handoff note only when crossing a non-persistent boundary or when
the user explicitly asks for one. In filesystem-native environments with a
current manifest, changelog, and git history, it is usually unnecessary.
When created, it replaces the previous handoff note; previous handoffs live
in changelog history.
Conflict resolution
When a session finds version conflicts (e.g., a file claims v5 but the
manifest says v4, or two files claim different bundle versions):
- 1. Present the conflict to the user with the specific discrepancy.
- Show what each version claims via its changesummary.
- Default recommendation: trust the most recent versiondate.
- Always ask the user for explicit confirmation before proceeding.
Never silently resolve a version conflict. The whole point of this system
is to make conflicts visible.
Cross-Surface and Cross-Platform Considerations
Treat one skill as moving through three states:
- - Canonical source bundle: The working copy in git or local storage.
Keep
MANIFEST.yaml and the active
CHANGELOG.md here. This is the
author-side source of truth. If you maintain a full archive in git,
keep it at repo root or another repo-level path outside the bundle.
- - Strict-platform install copy: A derived copy for Codex, Gemini CLI,
Perplexity, or other loaders that only accept
name and
description.
Strip the
metadata block from SKILL.md, set
frontmatter_mode:
minimal, recompute hashes in that copy, and leave the canonical bundle
unchanged unless you intentionally promote the derived copy.
- - Registry or settings package: A consumer package such as a INLINECODE89
ZIP or ClawHub upload. It may omit development-only files, but its
MANIFEST.yaml must describe exactly what the package contains. Update
deployments only after a real publish, reinstall, or redeploy.
Surface notes:
- - Claude Chat: Stateless upload/download boundary. Verify on open and
consider a handoff note.
- - Claude Cowork / Claude Code / Claude Agent SDK: Persistent
filesystem. The manifest and changelog live with the bundle.
- - Claude API: Deployment versions live in
deployments, not in
bundle_version.
- - Other agentskills clients: Unknown files are ignored safely.
.agents/skills/ can act as a neutral install path.
General principle: the manifest and changelog stay authoritative, and
transformed install or publish copies are derived artifacts, not silent
edits to the canonical bundle.
Trust and Audit
Use the manifest, changelog, hashes, and optional deployment metadata to
verify what belongs in the bundle, whether files still match their
recorded state, what changed, and which installed or deployed copies may
now be stale. If a bundle comes from an untrusted source, verify it first.
File Naming
Versioned files use stable names without version numbers:
- -
SKILL.md (not SKILL_v5.md) - INLINECODE97 (not
evals_v3.json) - INLINECODE99 (not
generate-v4.js)
The version lives inside the file (via the header) and in the manifest,
not in the filename. Version-numbered filenames are how we got into
trouble in the first place.
Exception: if a user's local storage requires version-in-filename for
their workflow, the manifest is the tiebreaker for which version is
canonical. Internal version identity must still match.
Bootstrap
To version an existing unversioned skill bundle:
- 1. Inventory all files present — read the directory structure or uploaded
file list. Do not ask the user to list files; determine this yourself.
- 2. Ask the user what version number to assign. If there's a handoff note
or other context, propose a number based on the history.
- 3. Add internal version headers to files that can safely carry them and
record manifest-only versions for strict-format files.
- 4. Generate
MANIFEST.yaml with hashes. - Create
CHANGELOG.md with a single entry summarizing known history. - Deliver the versioned bundle.
This is a one-time operation per skill bundle.
Origin
Developed for PAICE.work PBC. Canonical source:
https://github.com/snapsynapse/skill-provenance
技能溯源
解决的问题
技能项目在会话、界面(聊天、IDE、CLI、Cowork)、平台(Claude、Gemini CLI、Codex、Copilot)和本地存储(Obsidian、工作目录、Git仓库)之间流转。当版本标识仅存在于文件名中时,版本身份会丢失。将文件从SKILLv4.md重命名为SKILLv5.md,但内部没有记录更改内容,会造成歧义。
本技能建立了三个约定来防止这种情况:
- 1. 当文件格式允许时,版本标识存在于文件内部,并且始终存在于清单中。
- 最近的变更日志随技能包一起传递,而更长的历史记录可以保存在源仓库中。
- 清单列出包中的所有文件,以便任何会话都能验证完整性。
版本化的内容
技能包是一个SKILL.md加上所有关联文件。典型内容包括:
- - SKILL.md(技能定义)
- evals.json(评估套件)
- 生成脚本(例如,generate.js、generate.py)
- 由评估或实际使用产生的输出工件(.docx、.pdf)
- 交接记录
- 用户提供的源材料(被追踪但不版本化)
技能本身(SKILL.md)和评估是主要的版本化工件。脚本和输出由清单追踪,但与包一起版本化,而非独立版本化。交接记录是可选的便利工件。
内部版本头
能够安全携带YAML前置元数据的文件以YAML前置元数据块开头(或扩展现有块),包含以下字段:
yaml
skill_bundle: my-skill # 包名称,跨版本稳定
file_role: skill # skill | evals | script | output | handoff
version: 5 # 整数,单调递增
version_date: 2026-02-10 # 此版本的日期
previous_version: 4 # v1为null
change_summary: >
重写了第5阶段的布局规则。移除了每节分页。
添加了内容流检查。添加了验证清单作为独立的最终页面。
规则
version是用于逐文件追踪的整数。它统计该特定文件在包内的修订次数。包级版本(MANIFEST.yaml中的bundle_version)使用语义化版本控制。
change_summary在v1之后的每个版本都是必需的。一到三句话。它必须描述更改了什么,而不仅仅是发生了更改。
previous_version创建了一个链条。任何会话都可以追溯谱系。
file_role值:
- - skill — SKILL.md本身
- evals — evals.json文件
- script — 生成脚本、实用脚本
- output — 渲染的工件(.docx、.pdf)
- handoff — 会话交接记录
- source — 用户提供的源材料(被追踪,不版本化)
- reference — references/中的文档,按需加载
- asset — assets/中用于输出的模板、图片、字体
- agents — 平台UI元数据(例如,Codex的agents/openai.yaml)
对于无法安全携带YAML前置元数据的文件(二进制文件和严格格式文件,如.json或可执行的.sh),清单追踪其版本,其version字段具有权威性。
SKILL.md前置元数据约束: Agent Skills开放标准(agentskills.io)要求name和description。不同平台对额外字段执行不同的规则:
| 平台 | 允许的SKILL.md前置元数据 |
|---|
| agentskills.io规范 | name、description、license、metadata、compatibility、allowed-tools |
| Claude Chat / 设置UI |
与规范相同。Claude的设置导入器拒绝无法识别的字段。 |
|
Claude Code | 规范字段加上扩展:disable-model-invocation、user-invocable、context、agent、model、hooks、argument-hint。这些是Claude Code的功能,不属于基础规范的一部分。 |
|
Claude API | 通过/v1/skills上传的技能。验证name和description。支持metadata。 |
|
Gemini CLI(Google) | 仅name和description。官方不支持额外字段。 |
|
Codex(OpenAI) | 仅name和description。额外字段被拒绝。 |
|
GitHub Copilot / VS Code | 遵循agentskills.io规范。 |
|
Cursor、Roo Code、Junie等 | 遵循agentskills.io规范。查看agentskills.io获取完整采用者列表(30+)。 |
为了最大可移植性,将SKILL.md前置元数据限制为仅name和description。如果规范包需要归属或可见的SKILL.md元数据,请使用规范的metadata字段,并为严格平台生成派生的最小副本:
yaml
name: my-skill
description: 技能的功能描述。
metadata:
skill_bundle: my-skill
file_role: skill
version: 3
version_date: 2026-02-10
previous_version: 2
change_summary: >
添加了第6阶段验证步骤。
如果直接针对Codex或其他严格平台,请完全省略SKILL.md中的metadata。清单无论哪种方式都会追踪SKILL.md的版本,因此不会丢失版本信息。
关于规范支持的说明: agentskills.io规范正式支持metadata作为任意键值映射,并以version作为示例用途。这意味着metadata.version方法现在已获得规范认可,而非仅Claude的扩展。然而,规范的版本是一个静态标签——它不解决过时追踪、变更日志或包完整性问题。默认情况下优先使用基于清单的追踪,仅当需要在文件本身中可见版本信息时才使用metadata。
清单
清单是一个名为MANIFEST.yaml的YAML文件,位于技能包目录的根目录——与SKILL.md同级。当包被打包为.skill ZIP时,清单位于ZIP内部。它是包内容单一真实来源。
yaml
bundle: my-skill
bundle_version: 5.1.0
bundle_date: 2026-02-10
description: >
用于从源材料和用户简报生成专业文档的技能。
处理研究、结构化和格式化。
compatibility:
designed_for:
surfaces:
- chat
- cli
- ide
capabilities:
- 最小SKILL.md前置元数据
- 本地文件系统访问
- 可选的Git工作流
tested_on:
- platform: Anthropic Claude
model: Claude Opus 4.6
surface: Chat
status: pass
date: 2026-02-10
- platform: Anthropic Claude
model: Claude Sonnet 4.5
surface: Chat
status: partial
date: 2026-02-09
notes: 在复杂包上遗漏了过时检测
spec_version: agentskills.io/1.0
frontmatter_mode: minimal
# minimal = 仅name + description(Codex、Gemini CLI,最大可移植性)
# metadata = 包含metadata块(任何支持规范metadata字段的平台)
dependencies: []
# 列出此包依赖的技能名称。如果没有则省略或留空。
deployments:
api:
version: 1759178010641129
workspace: docs-prod
claude:
scope: user
perplexity:
package_format: zip
files:
- path: SKILL.md
role: skill
version: 5
hash: sha256:abc123...
note: 规范技能定义
- path: evals.json
role: evals
version: 3
hash: sha256:def456...
note: 7个评估,包括真实内容合成
- path: scripts/generate.js
role: script
version: 4
hash: sha256:ghi789...
note: 评估3的生成脚本
- path: outputs/eval3-output.pdf
role: output
version: 4
hash: sha256:jkl012...
note: 渲染的评估3输出,10页,已验证
- path: sources/article-1.md
role: source
version: null
hash: sha256:pqr678...
note: 源文章1(已发布)
规则
bundle_version使用语义化版本控制(MAJOR.MINOR.PATCH)。对技能模型或接口进行破坏性更改时增加MAJOR,添加新功能或能力时增加MINOR,修复和文档更新时增加PATCH。每个文件的version字段保持为整数——它们是修订计数器,而非发布标识符。
hash是文件内容的sha256哈希。这是新会话验证