Skip to content

Repository files navigation

skillpack

GoTestsLicenseStatusBinaryDeps

Package manager, lockfile, and bundler for Claude Code / Cursor / AGENT.md agent skills. Resolve dependencies. Pin sha256 hashes. Bundle and sign. Single Go binary, zero runtime deps.

skillpack init
skillpack add ./skills
skillpack install # writes skillpack.lock
skillpack verify # CI: exit 1 if anything drifted
skillpack bundle # produces a deterministic *.skl tarball
skillpack sign --key priv.key mypack.skl

Why This Exists

The agent-skill ecosystem is exploding. In the last six months, vendors and the community have shipped:

  • Anthropic SKILL.md — the canonical Claude Code skill format with YAML frontmatter
  • Cursor .cursorrules — Cursor IDE rule files driving the editor's inline assistant
  • AGENT.md — the cross-vendor proposal for a portable agent manifest (used by opencli, googleworkspace/cli, and others)
  • skill.yaml — pure-YAML manifests for tooling-first skill catalogs

There are at least six trending GitHub repositories with combined stars above 100,000 that cluster around this wedge:

  • googleworkspace/cli (22K stars) — "40+ agent skills included"
  • antigravity-awesome-skills (28K stars) — curated catalog of skills
  • awesome-claude-code (33K stars) — the canonical "list of skills" repo
  • opencli (8K stars, 632 stars/day) — runtime dispatcher reading AGENT.md
  • claude-code-ultimate-guide — docs site for the ecosystem
  • awesome-openclaw-agents — community-curated agent registry

And yet — zero of these repositories solve the lifecycle problem. They all answer "what skills exist?" but none answer:

  • How do I pin the exact version of a skill across machines?
  • How do I detect when a skill on disk has drifted from what my CI expects?
  • How do I bundle 20 skills into a single distributable artifact?
  • How do I sign that artifact so my team can trust it?
  • How do I declare that skill A depends on skill B at version ^1.2.0?

opencli is a runtime dispatcher (different layer). googleworkspace/cli ships its own bundle (vendor-locked). awesome-claude-code is a hand-curated markdown list (no tooling). The lifecycle hole is wide open, and skillpack fills it.

skillpack is the npm/cargo/pip of agent skills — except it works across every vendor format from day one.


What skillpack Does

LayerWhat it does
ParseRead SKILL.md, .cursorrules, AGENT.md, and skill.yaml; normalize all four into a single canonical record
ResolveHonor requires: semver constraints between skills; produce a deterministic install order via topological sort
HashCompute a content-addressed sha256 fingerprint per skill (LF-normalized, frontmatter-sorted, key-canonicalized)
LockWrite skillpack.lock — a deterministic JSON file with no timestamps and stable ordering
BundleProduce a *.skl tarball (gzipped, fixed mtime, sorted file order, PAX format) — byte-identical across two runs
SignDetached ed25519 signatures over the bundle bytes
VerifyCI mode that exits non-zero on hash drift, version drift, or missing skills

Every byte of output is deterministic. Two machines parsing the same source files produce byte-identical lockfiles and tarballs. This is what makes skillpack a real package manager and not a glorified zip script.


Installation

From source

go install github.com/JSLEEKR/skillpack/cmd/skillpack@latest

Build manually

git clone https://github.com/JSLEEKR/skillpack.git
cd skillpack
go build -ldflags="-s -w" -o skillpack ./cmd/skillpack

The resulting binary is under 5 MB with zero runtime dependencies. Drop it in your $PATH and you're done.

Pre-built binaries

Download from the Releases page.


Quick Start

1. Initialize a workspace

mkdir my-pack &&cd my-pack
skillpack init --name my-pack

This creates a skillpack.yaml workspace manifest:

name: my-packversion: 0.1.0skills:
- ./skills

2. Add some skills

Drop a SKILL.md (or .cursorrules, AGENT.md, skill.yaml) under ./skills:

---name: code-reviewversion: 1.2.0description: Carefully review code changes for issueslicense: MITauthor: jsleetools:
- git
- bashrequires:
- base-agent ^1.0.0---# Code Review Skill
When asked to review code, follow these steps:
1. ...

3. Resolve and install

$ skillpack resolve
Install order (2 skills):
1. base-agent@1.0.0 [skill.md] — skills/base-agent/SKILL.md
2. code-review@1.2.0 [skill.md] — skills/code-review/SKILL.md
$ skillpack install
skillpack: wrote skillpack.lock (2 skills)

The resulting skillpack.lock:

{
"version": 1,
"generated_by": "skillpack",
"skills": [
{
"name": "base-agent",
"version": "1.0.0",
"format": "skill.md",
"hash": "sha256:b6a8...",
"source": "skills/base-agent/SKILL.md"
},
{
"name": "code-review",
"version": "1.2.0",
"format": "skill.md",
"hash": "sha256:f3c0...",
"source": "skills/code-review/SKILL.md",
"requires": ["base-agent ^1.0.0"]
}
]
}

4. Verify in CI

$ skillpack verify
skillpack: verify OK

Exit code 0. Wire it into your pipeline:

# .github/workflows/ci.yml
- name: Verify skill lockfilerun: skillpack verify

If any skill drifts (someone edited a body, bumped a version, deleted a file), verify exits with code 1 and prints exactly what changed.

5. Bundle and sign

$ skillpack bundle -o my-pack.skl
skillpack: wrote my-pack.skl (4218 bytes, 2 skills)
hash: sha256:5e9d...
$ skillpack keygen --priv priv.key --pub pub.key
$ skillpack sign --key priv.key my-pack.skl
skillpack: wrote signature my-pack.skl.sig
$ skillpack sign --verify --pubkey pub.key my-pack.skl
skillpack: signature OK for my-pack.skl

Distribute my-pack.skl + my-pack.skl.sig + pub.key and your users can verify provenance with one command.


Supported Formats

skillpack speaks all four of the de facto agent-skill manifest formats:

SKILL.md (Anthropic)

---name: my-skillversion: 1.0.0description: What this skill doeslicense: MITauthor: alicetools:
- bash
- gitrequires:
- other-skill ^1.0.0---
The body of the skill goes here.

.cursorrules (Cursor)

---name: my-cursor-rulesversion: 0.3.0description: Code style for our teamglobs:
- "**/*.ts"
- "**/*.tsx"alwaysApply: true---
Always use tabs.
Never use any.
Prefer named exports.

AGENT.md (Cross-vendor)

---name: portable-botversion: 2.0.0description: A bot that works in any vendor's runtimevendor: anthropicmodels:
- claude-3.5-sonnetpermissions:
- filesystem
- networktools:
- bash---
This agent helps you...

skill.yaml (Pure YAML)

name: yaml-onlyversion: 1.0.0description: A skill defined entirely in YAMLlicense: Apache-2.0tools:
- curl
- jqbody: | This skill talks to APIs.

skillpack normalizes all four into the same canonical record, so you can mix and match formats inside a single workspace and the lockfile will treat them identically.


Determinism Guarantees

Every byte of skillpack's output is deterministic. The following invariants are tested:

InvariantTest
skillpack install produces byte-identical lockfile across two runslockfile.TestMarshalDeterministic
skillpack bundle produces byte-identical tarball across two runsbundle.TestBundleDeterministic
Tarball is identical regardless of input skill orderbundle.TestBundleDeterministicRegardlessOfInputOrder
Hash is identical regardless of frontmatter key orderhasher.TestHashFrontmatterOrderInsensitive
Hash is identical regardless of tools/requires orderhasher.TestHashToolsOrderInsensitive
Hash is identical regardless of CRLF vs LF line endingsparser.TestParseSkillMDCRLF + canonical normalization
Hash is identical regardless of UTF-8 BOM presenceparser.TestParseSkillMDBOM
Resolver order is identical across runs (lexicographic tiebreak)resolver.TestResolveDeterministic

How we achieve this:

  • Lockfile: encoding/json with sorted struct fields, manually sorted skills slice, manually sorted requires within each entry, LF line endings, trailing newline.
  • Tarball: sorted file order, fixed mtime (1970-01-02 to dodge zero-mtime quirks), uid/gid = 0, Uname/Gname = "", tar.FormatPAX, gzip with fixed header name.
  • Hashing: canonical pre-image is line-oriented key=value\n form with sorted keys, body normalized to LF + single trailing newline.
  • No timestamps anywhere in any hashable code path.

Exit Codes

skillpack uses distinct exit codes so CI pipelines can branch on the failure mode:

CodeMeaningWhen
0OKOperation succeeded
1Driftverify found a hash or version mismatch (expected failure mode)
2Parse errorA skill file is malformed (YAML, frontmatter, manifest)
3IO errorFilesystem, permission, or missing-file error
4Internal errorAn unexpected bug in skillpack itself
5Usage errorInvalid CLI flags or missing required arguments
6Securitysign --verify failed (tampered bundle or wrong key) — treat as a hard-fail, never a routine lock refresh

CI example:

skillpack verify
case$?in
0) echo"All skills clean" ;;
1) echo"Drift detected — open a PR to update skillpack.lock";exit 1 ;;
2) echo"Skill file is broken — block merge";exit 1 ;;
6) echo"SIGNATURE TAMPER — do not merge, investigate";exit 1 ;;
*) echo"skillpack itself failed — investigate";exit 1 ;;
esac

Architecture

skillpack is intentionally small: ~5,300 lines of Go split across 13 internal packages. Each package has a single responsibility and a clean interface.

cmd/skillpack/main.go entry point (5 lines)
internal/
├── cli/ cobra command tree
│ ├── root.go root command + Execute
│ ├── init.go skillpack init
│ ├── add.go skillpack add
│ ├── resolve.go skillpack resolve
│ ├── install.go skillpack install
│ ├── verify.go skillpack verify
│ ├── bundle.go skillpack bundle
│ ├── sign.go skillpack sign / keygen
│ └── lock.go skillpack lock
├── workspace/ manifest + parser + resolver glue
├── manifest/ skillpack.yaml read/write
├── parser/ multi-format parser
│ ├── skillmd.go SKILL.md
│ ├── cursorrules.go .cursorrules
│ ├── agentmd.go AGENT.md
│ ├── skillyaml.go skill.yaml
│ └── helpers.go normalizeRequires, dedupSorted
├── skill/ canonical Skill record
├── semver/ constraint matching (^/~/x/...)
├── resolver/ topological sort with semver checks
├── hasher/ sha256 content addressing
├── lockfile/ deterministic JSON lockfile
├── bundle/ deterministic tar.gz writer
├── signer/ ed25519 detached signatures
├── verify/ CI drift detection
└── exitcode/ typed errors -> exit codes

Dependency direction always flows downward — cli depends on workspace, workspace depends on parser + resolver + manifest, and so on. There are no cycles, and the leaf packages (skill, semver, exitcode) have no internal dependencies.


Test Coverage

221 tests across all layers:

PackageTestsWhat it covers
parser32All four formats, CRLF, BOM, missing fields, bad YAML, requires (list/map), v-prefix versions
cli27init, add, resolve, install, verify (clean/drift), bundle, sign, keygen, lock, JSON output, error paths
lockfile19Roundtrip, sort order, LF only, trailing newline, missing/negative/future version, atomic write, duplicate-name rejection (Cycle K)
semver17Caret, tilde, comparators, x-ranges, BestMatch, normalize, edge cases
hasher17Determinism, frontmatter order, tools/requires order, body/version/name sensitivity, collision-resistance across comma/pipe/=/newline ambiguity
signer16Generate, sign, verify, tampered, wrong key, CRLF in key file, file roundtrip, trailing garbage, multi-line body
bundle16Determinism, multiple formats, header validation, path safety, list mode, tainted-archive hardening
skill16Canonical record validation, name rules (./../leading-dot/whitespace), constraint parsing, sorting
resolver14Linear chain, diamond, cycle, self-cycle, missing dep, version conflict, deterministic ordering, duplicates
manifest14Roundtrip, sort, missing fields, bad YAML, write/read, skills-path validation
verify12Clean, drift hash, drift version, missing, extra, sorted findings, parse error, JSON snake_case schema pin (Cycle J)
exitcode8Wrap/Classify, nil-safe, layered wrap preservation
workspace8Load happy, missing manifest, missing dep, recursive discover, dedup, ignore .git
docsmeta5Doc-accuracy meta-tests: ROUND_LOG/CHANGELOG/README test-count pins + badge pin + per-package table sum + meta-meta self-consistency (Cycle J, L)

Run them yourself:

go test ./... # all green, ~5 seconds
go test -race ./... # race detector clean
go vet ./... # vet clean

Comparison with Existing Tools

ToolLayerFormat supportLockfileHashingBundlingSigningStatus
skillpackLifecycleAll 4✅ sha256✅ deterministic✅ ed25519This project
opencliRuntime dispatchAGENT.mdDifferent layer
googleworkspace/cliVendor bundleVendor-specificBundled at buildVendor-locked
awesome-claude-codeCurationMarkdown listNo tooling
claude-code-ultimate-guideDocsDocsDocs site
npm/cargo/pipCode packagesN/ASometimesWrong domain

skillpack is the only tool that closes the lifecycle loop for agent skills.


Roadmap

Things that are explicitly out of scope for v1.0 (and may land in 1.x):

  • Federated registry — v1.0 has no centralized registry. Skills come from local paths, file:// URIs, http(s):// URLs, and git URLs only. A federated index is V2 and only if traction warrants.
  • Skill audit — security analysis of skill bundles (prompt injection, shell calls, oversized contexts). See the runner-up skillaudit proposal.
  • Skill catalog UI — local index + search over installed skills.
  • Schema validation — strict JSON Schema validation per format.
  • Lockfile resolution caching — for very large workspaces.

Contributing

Bug reports, feature ideas, and pull requests welcome at github.com/JSLEEKR/skillpack/issues.

Before opening a PR:

go test -race ./... # must be green
go vet ./... # must be clean

The Generator/Evaluator separation in our build pipeline means every change goes through an independent eval pass before merging.


License

MIT © 2026 JSLEEKR. See LICENSE for the full text.


Acknowledgements

  • The Anthropic Claude Code team for shipping SKILL.md as a parseable format
  • The Cursor team for .cursorrules
  • The opencli, googleworkspace/cli, and awesome-claude-code communities for proving the demand for skill tooling
  • golang.org/x/mod/semver for the rock-solid semver primitives
  • gopkg.in/yaml.v3 for YAML parsing
  • github.com/spf13/cobra for the CLI framework

If skillpack saves your team a single deployment headache, that's payment enough.

About

Package manager and lockfile for agent skills (SKILL.md/AGENT.md/.cursorrules). Resolve, pin, hash, bundle, sign. Single Go binary.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages