knack 0.2.1

CLI for packaging, discovering, and installing Agent Skills
knack-0.2.1 is not a library.

knack

Crates.io Docs.rs CI License

knack is an open-source Rust CLI and self-hostable registry project for teams to package, validate, version, publish, discover, install, and govern Agent Skills.

The current v0 focuses on local skill authoring and distribution primitives. See PROJECT.md for the north-star product direction.

Install

Install the CLI from crates.io:

cargo install knack

Install the registry server:

cargo install knack-registry

Or build both from source:

git clone https://github.com/ajac-zero/knack
cd knack
cargo build --release
# Binaries land at target/release/knack and target/release/knack-registry

Verify the install:

knack --help

Usage

Create a skill:

knack new rust-code-review

Initialize a project manifest:

knack init

By default, commands use project scope:

.agents/knack.toml
.agents/knack.lock
.agents/skills/

Pass -g (or --global) on any command to operate on user-wide skills instead of the current project. knack add creates the manifest on first use, so an explicit knack init is only needed if you want to customize the install target:

knack add gh:anthropics/skills/skills/pdf -g
knack sync -g
knack list -g

Global scope uses:

~/.agents/knack.toml
~/.agents/knack.lock
~/.agents/skills/

System-wide defaults are configured at:

/etc/knack/knack.toml
/usr/local/share/knack/skills/

These have no dedicated CLI flag because they are an administrator concern. Edit /etc/knack/knack.toml directly (with sudo) to seed registry aliases that every user on the machine should inherit.

Registry aliases are inherited in this order, with later layers overriding earlier layers:

system (/etc/knack/knack.toml)
global (~/.agents/knack.toml)
project (./.agents/knack.toml)

That lets administrators inject aliases such as tea: for all users while still allowing user or project-level overrides.

Read-only commands (knack find, knack registry list) search the merged set of registries from all three layers automatically. They work from a directory with no project manifest, so a globally-registered company: alias is reachable without an explicit -g.

Add and install a skill source into the manifest target:

knack add gh:anthropics/skills/skills/pdf

This updates .agents/knack.toml and writes .agents/knack.lock with the resolved source and a deterministic checksum of the installed skill contents.

Install all skills declared in .agents/knack.toml (uses the lockfile, reproducible):

knack sync

For CI: verify the install and lockfile are consistent with the manifest without modifying anything. Exits non-zero with an actionable message on missing lockfile entries, missing installs, or checksum drift:

knack sync --check

Pull upstream changes for skills tracking a moving ref (branch, tag). Sources pinned to a SHA-shaped ref are skipped — pass -f / --force to retry them anyway. Pass -n / --dry-run to preview what would change without touching the install dir or lockfile (still fetches from the network so the preview is accurate):

knack update              # branch/tag-tracking skills get refreshed
knack update --dry-run    # report what would change; modify nothing
knack update --force      # ignore pinning, re-fetch everything

The lockfile records each skill's resolved source as a content-addressed commit SHA — gh: and git+ URLs embed @<sha>, http+knack: URLs append #sha=<sha>. That makes knack sync truly reproducible: a teammate cloning the repo six months later installs the same commits, regardless of where main has moved since.

Validate a skill:

knack validate rust-code-review

Package a skill:

knack pack rust-code-review --output dist

Install a skill directory or package archive:

knack install rust-code-review --target .agents/skills
knack install dist/rust-code-review.skill.tar.gz --target .agents/skills

Install directly from a public GitHub repository:

knack install gh:owner/repo/path/to/skill --target .agents/skills
knack install gh:owner/repo@ref/path/to/skill --target .agents/skills

For example:

knack install gh:anthropics/skills/skills/pdf --target .agents/skills

Install from any Git host supported by your local git command:

knack install git+https://git.example.com/org/skills.git//path/to/skill
knack install git+ssh://git@git.example.com/org/skills.git@main//path/to/skill

Register a Git host alias in knack.toml:

knack registry add git+ssh://git@gitea.example.com tea
knack registry list

For HTTP knack registries the alias can be omitted — the CLI fetches GET <url>/info and adopts whatever name the registry advertises so every client of the same registry uses the same alias:

knack registry add http://127.0.0.1:7349           # adopts the advertised name
knack registry add http://127.0.0.1:7349 myalias   # explicit override

Then add skills through the alias:

knack add tea:platform/agent-skills/rust-code-review
knack add tea:platform/agent-skills@v1.2.0/rust-code-review

Alias syntax is:

alias:owner/repo[@ref]/path/to/skill

Generate a searchable registry index from a local tree of skills:

knack index generate ./skills \
  --source-prefix gh:owner/repo/skills \
  --output knack.index.toml

Serve the index with knack-registry:

knack-registry --index knack.index.toml --bind 127.0.0.1:7349

Build and run the registry container:

docker build -t knack-registry .
docker run --rm -p 7349:7349 \
  -v "$PWD:/data:ro" \
  knack-registry

The image defaults to:

knack-registry \
  --index /data/knack.index.toml \
  --skills-root /data/skills \
  --name company \
  --bind 0.0.0.0:7349

Override arguments as needed:

docker run --rm -p 7349:7349 \
  -v "$PWD:/data:ro" \
  knack-registry \
  --index /data/knack.index.toml \
  --skills-root /data/skills \
  --name platform \
  --bind 0.0.0.0:7349

To make the HTTP registry the only thing users need to interact with, serve skill archives too:

knack-registry \
  --index knack.index.toml \
  --skills-root ./skills \
  --name company \
  --bind 127.0.0.1:7349

With --name company, search results return proxy install sources such as company:deploy-container. The CLI resolves those through the HTTP registry and downloads the skill archive from the registry server. The registry also advertises the name at GET /info so clients can knack registry add <url> without supplying an alias.

When a skill's backing source is a git repository, the registry includes the resolved commit SHA in the archive response via the X-Knack-Resolved-Sha header. The CLI captures it into the lockfile so HTTP-registry installs are pinned the same way gh:/git+ installs are.

Register and search that registry from the CLI:

knack registry add http://127.0.0.1:7349 local
knack find pdf

Search results are installable sources:

local	pdf	Work with PDF files...	gh:owner/repo/skills/pdf

In proxy mode, results look like this:

company	deploy-container	Deploy containers to Kubernetes. 	company:deploy-container

Users can install without knowing the backing Git repo:

knack add company:deploy-container

For skills scattered across one or more Git repositories, prefer dynamic source entries. The registry fetches the backing source, scans for SKILL.md, and derives each skill's name and description from the skill itself:

[[source]]
source = "tea:platform/agent-skills"
tags = ["deploy", "kubernetes"]

At startup, that materializes skills such as tea:platform/agent-skills/deploy-container from platform/agent-skills/deploy-container/SKILL.md. This avoids duplicating fragile metadata in knack.index.toml.

Dynamic sources must refresh successfully on startup before the registry serves traffic. After startup, the registry refreshes dynamic sources every 300 seconds by default and keeps serving the last good index if a later refresh fails. Disable background refresh with --refresh-interval-seconds 0 or tune it with another interval.

Static entries are still supported for hand-curated overrides:

[[skill]]
name = "deploy-container"
description = "Deploy containers into the internal Kubernetes cluster."
source = "tea:payments/api/.agents/skills/deploy-container"
tags = ["deploy", "kubernetes"]

Start the registry with a source alias so it can fetch those backing sources server-side:

knack-registry \
  --index knack.index.toml \
  --name company \
  --source-alias tea=git+ssh://git@gitea.example.com \
  --refresh-interval-seconds 300 \
  --bind 127.0.0.1:7349

Users still only need the HTTP registry:

knack registry add http://127.0.0.1:7349       # adopts the advertised name `company`
knack find deploy
knack add company:deploy-container

Publish a local skill into a git-backed team skills repository:

knack registry add git+ssh://git@gitea.example.com tea
knack publish ./my-skill \
  --registry tea \
  --repo platform/agent-skills

Publishing currently supports git-host registries. It clones the target repository, copies the skill into skills/<skill-name>, regenerates knack.index.toml, commits the change, and pushes it. Use --no-push to leave the commit local in the temporary checkout for debugging.

After the registry server is serving the updated knack.index.toml, teammates can discover and install the skill:

knack find my-skill
knack add tea:platform/agent-skills/skills/my-skill

List installed skills:

knack list --target .agents/skills

v0 Scope

Implemented:

  • Skill scaffolding.
  • Agent Skills frontmatter validation.
  • Deterministic .skill.tar.gz packaging.
  • Local installation from directories and package archives.
  • GitHub installation with gh:owner/repo[@ref]/path/to/skill.
  • Generic Git installation with git+<url>[@ref]//path/to/skill.
  • Git-host registry aliases with alias:owner/repo[@ref]/path/to/skill.
  • Searchable HTTP registries served by knack-registry.
  • Proxied HTTP registry installs with registry:skill-name.
  • Registry-side proxying from indexed Git backing sources.
  • Registry index generation from local skill directories.
  • Publishing skills to git-backed team repositories.
  • Project manifests with knack.toml.
  • Lockfiles with knack.lock.
  • Project and global scoped config/install paths.
  • System scoped config at /etc/knack/knack.toml.
  • Layered registry alias inheritance from system to global to project.
  • add, sync, and update workflows for reproducible project installs.
  • Content-addressed lockfile entries (commit SHA captured for gh:, git+, and http+knack: sources).
  • knack sync --check for CI: assert install + lockfile consistency.
  • knack update --dry-run for previewing upstream changes.
  • Versioned lockfile schema; future-incompatible lockfiles refuse to load rather than silently round-tripping.
  • Listing installed skills.

Not implemented yet:

  • Static registries.
  • Signing, provenance, and policy checks.