Deterministic, repo-local skill deps for your CLI workflow.
Repo-local · Deterministic · No registry
brew install skill-vendor/tap/skv
skv init
skv add https://github.com/acme/skill-foo
skv sync
skv.cue, skv.lock, and .skv/.Why SKV?
Skills are becoming a shared standard across tools (Claude Code, Codex CLI, OpenCode), but there is no good ecosystem for dependency management. SKV brings a Go-modules-like workflow to skills:
The problem
- Skills scattered across repos with no versioning
- No way to pin exact versions across a team
- Manual copy-paste leads to drift
- No CI verification that skills match expectations
SKV's approach
- CUE-based spec with JSON lock file
- Deterministic installs (pinned commits + checksums)
- Vendored skills committed to the repo
- Works with any Git host—no registry required
Supported Tools
Native support
- Claude Code (
.claude/skills/) - OpenAI Codex (
.codex/skills/) - OpenCode (
.opencode/skill/)
Compatible
- Cursor (via Codex/Claude-compatible skills handling)
Workflow
Go from spec to vendored skills and tool links in one repeatable flow.
Spec
Declare skills in skv.cue with repo, ref, and path.
Vendor
skv sync fetches and pins exact commits into .skv/skills/.
Link
SKV wires symlinks into each tool's skill directory automatically.
Commit
Commit skv.cue, skv.lock, and .skv/ to your repo.
Verify
Run skv verify in CI to ensure skills match the lock.
How It Works
skv.cue skv sync .skv/skills/
(your spec) ──────────────► (vendored content)
│
▼
skv.lock
(commits + checksums)
│
▼
.claude/skills/ .codex/skills/ .opencode/skill/
(symlinks)
skv syncreads yourskv.cuespec- Skills are vendored into
.skv/skills/<name>/ skv.lockrecords the resolved commit SHA and checksum- Symlinks are created in each tool’s skill directory
Commands
| Command | Description |
|---|---|
skv init |
Scaffold spec, lock, and .skv/skills/ directory |
skv add <repo>[#ref][:path] |
Add a skill to the spec |
skv sync |
Vendor skills, update lock, refresh symlinks |
skv sync --offline |
Verify and link without network access |
skv sync --refresh |
Re-fetch and overwrite vendored content |
skv sync --accept-local |
Treat local content as source of truth |
skv update [name] |
Update floating refs (branches/tags) |
skv update --all |
Update all non-commit-pinned skills |
skv verify |
Check vendored skills match the lock (CI-friendly) |
skv list |
List all skills with their status |
skv remove <name> |
Remove a skill from spec, lock, and disk |
skv import <path> |
Move a local skill into SKV management |
Adding Skills
# Single-skill repo (expects SKILL.md at root)
skv add https://github.com/acme/skill-foo
# Skill from a monorepo path
skv add https://github.com/acme/skill-pack:skills/skill-foo
# Pinned to a tag
skv add https://github.com/acme/skill-pack#v1.2.3:skills/skill-foo
# Override the skill name
skv add https://github.com/acme/skill-pack:skills/skill-foo --name release-notes
Managing Skills
List installed skills:
$ skv list
skill-foo https://github.com/acme/skill-foo (abc1234)
release-notes https://github.com/acme/skill-pack:skills/release-notes#v1.2.3 (def5678)
local-helper local:.skv/skills/local-helper
Remove a skill:
$ skv remove skill-foo
Removed skill-foo from spec, lock, and .skv/skills/
Configuration
The spec file skv.cue defines your skill dependencies:
skv: {
// Exclude specific tools (all enabled by default)
tools: {
exclude: ["opencode"]
}
skills: [
{
name: "skill-foo"
repo: "https://github.com/acme/skill-pack"
path: "skills/skill-foo" // subdirectory in repo
ref: "v1.2.3" // optional: tag, branch, or commit
},
{
name: "local-helper"
local: "./.skv/skills/local-helper" // local skill, not fetched
},
]
}
Fields:
| Field | Required | Description |
|---|---|---|
name |
Always | Unique skill identifier |
repo |
For remote skills | Git repository URL |
path |
No | Subdirectory containing the skill |
ref |
No | Tag, branch, or commit (defaults to repo default branch) |
local |
For local skills | Path to local skill directory (mutually exclusive with repo) |
Lock File
skv.lock is a machine-managed JSON file that ensures deterministic installs. It captures:
- Resolved commit SHA — the exact commit vendored, even if the spec uses a branch or tag
- Checksum — SHA-256 hash of the vendored directory contents
- License metadata — best-effort SPDX identifier and license file path
Why checksums matter:
Checksums use SHA-256 over a deterministic directory hash (sorted file paths + file mode + file contents). This provides:
- Integrity — detects local edits or tampering
- Reproducibility — ensures vendored contents match what was resolved
- CI verification —
skv verifyvalidates checksums and errors on mismatch
Tags are expected to be stable. If a tag resolves to a different commit, skv update warns and aborts unless you re-run with --force.
CI Integration
Add skv verify to your CI pipeline to ensure vendored skills match the lock file:
# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
verify-skills:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install skv
run: |
curl -sL https://github.com/skill-vendor/skv/releases/latest/download/skv-linux-amd64 -o skv
chmod +x skv
sudo mv skv /usr/local/bin/
- name: Verify skills
run: skv verify
For ARM64 runners, use skv-linux-arm64 instead.
If vendored content doesn’t match the lock, skv verify exits non-zero with details about the mismatch.
Troubleshooting
Missing SKILL.md
error: skill directory must contain SKILL.md at its root
Every skill directory must have a SKILL.md file. If adding a single-skill repo, ensure SKILL.md is at the repo root. For monorepos, specify the path to the skill directory.
Lock mismatch
error: vendored content does not match lock
The vendored files have changed since the lock was written. Options:
skv sync --refresh— re-fetch from remote and update the lockskv sync --accept-local— accept local changes and rewrite the lock
Network unavailable
error: fetch required but running in offline mode
skv sync --offline can only verify and link already-vendored skills. If a skill hasn’t been fetched yet, you’ll need network access.
Installation
Homebrew (macOS and Linux):
brew install skill-vendor/tap/skv
Go:
go install github.com/skill-vendor/skv/cmd/skv@latest
Binary:
Download from GitHub Releases:
curl -sL https://github.com/skill-vendor/skv/releases/latest/download/skv-$(uname -s | tr '[:upper:]' '[:lower:]')-$(uname -m) -o skv
chmod +x skv
sudo mv skv /usr/local/bin/
Links
Built with Jekyll and hosted on GitHub Pages