KASETTO

Commands

Reference for kst add, remove, lock, sync, list, doctor, init, clean, and self-update.

kst init

Generates a starter config file — local ./kasetto.yaml by default, or global config with --global.

kst init [OPTIONS]

Options

FlagDescription
--globalWrite $XDG_CONFIG_HOME/kasetto/kasetto.yaml (or ~/.config/kasetto/kasetto.yaml)
--forceOverwrite an existing config file without prompting

kst add

Appends a source to your local kasetto.yaml and syncs it in — the cargo/uv-style way to grow a config without hand-editing YAML. Comments and formatting in the file are preserved; only the targeted lists gain a new entry.

kst add <SOURCE> [OPTIONS]

Kind-tagged flags --skill, --mcp, and --command (each repeatable) name the entries to add. Because skills, MCPs, and commands are separate lists, a single add can write to several of them at once — handy for a repo that ships more than one kind. A lone * value (--skill "*") is a wildcard. With no kind flags, the source is added as skills: "*".

kst add https://github.com/anthropics/skills                 # every skill in the pack
kst add https://github.com/anthropics/skills@v1.2.0           # `@<ref>` shorthand (cargo/uv-style)
kst add https://github.com/anthropics/skills --skill pptx --skill pdf
kst add https://github.com/example/repo --skill find --mcp github --command review
kst add https://github.com/example/pack --branch develop --no-sync
kst add https://github.com/example/pack --dry-run             # preview the edit, don't write

Deep browse URLs. Paste the URL you're looking at on GitHub/Gitea/GitLab — add decomposes a blob/tree URL into the repo, ref, and sub-directory (and, for a SKILL.md link, the skill name):

kst add https://github.com/mattpocock/skills/blob/main/skills/personal/edit-article/SKILL.md

writes:

skills:
  - source: https://github.com/mattpocock/skills
    branch: main
    sub-dir: skills/personal
    skills:
      - edit-article

A 40-char hex ref is pinned as ref:; any other ref (e.g. main) becomes branch: so --update keeps tracking it. Explicit --ref/--branch/--sub-dir override the derived pieces — e.g. add a tree/ URL for the sub-dir and name the skills yourself with --skill.

Options

FlagDescription
--skill <name>Skill to add (repeatable; * for all). Default kind when none given
--mcp <name>MCP server to add (repeatable; * for all)
--command <name>Command to add (repeatable; * for all)
--ref <ref>Pin to a git tag, commit SHA, or ref (conflicts with --branch)
--branch <branch>Track a specific branch (conflicts with --ref)
--sub-dir <dir>Subdirectory inside the source to use as the root (skills/commands)
--config <path>Config file to edit (default: ./kasetto.yaml); must be a local file
--no-verifySkip the upfront fetch that validates the source resolves
--no-syncEdit the config without installing
--dry-runPreview the edit without writing the config or syncing
--locked, --frozenDuring the follow-up sync, never fetch; honor the lock
--jsonPrint the edit summary as JSON
-q, --quietSuppress non-error output (repeat for stricter silence)
--color <when>auto (default), always, or never
--projectSync into the current project
--globalSync globally (default)

Before writing, add fetches the source once to confirm it resolves (and, for a named skill list, that the names exist) — skip with --no-verify. Adding a source whose (source, ref/branch, sub-dir) identity already exists in a list is rejected; edit it directly or kst remove it first. MCP entries never carry sub-dir (the schema has none there). Remote configs (HTTPS) can't be edited in place.

The <SOURCE>@<REF> shorthand (cargo/uv-style) splits the trailing @<ref> off the positional and is equivalent to --ref <REF>. Passing both the shorthand and --ref/--branch is rejected. SSH (git@host:org/repo) and URLs with userinfo (https://user@host/repo) round-trip unchanged.

kst remove

Deletes entries from your local kasetto.yaml, then syncs so the now-unconfigured skills, MCPs, and commands are pruned from disk and the lock. Aliased as kst rm.

kst remove <SOURCE> [OPTIONS]

remove mirrors add. The kind-tagged flags --skill, --mcp, and --command (each repeatable) subtract named entries from a list; when the last name goes, the whole entry is dropped. A lone * value drops that kind's entry outright. With no kind flags, the source is removed from every list it appears in.

kst remove https://github.com/anthropics/skills               # drop the whole source
kst remove https://github.com/anthropics/skills@v1.2.0         # disambiguate via `@<ref>` shorthand
kst remove https://github.com/vercel-labs/skills --skill find-skills
kst remove https://github.com/example/repo --mcp github --command review
kst remove https://github.com/example/pack --mcp "*"          # drop the whole mcps entry
kst remove https://github.com/example/pack --dry-run          # preview, don't write
kst rm ./local/pack --no-sync                                 # edit config only

Deep blob/tree browse URLs are accepted too — they resolve to the same repo-root source add would have written, so you can paste the URL you're looking at.

Options

FlagDescription
--skill <name>Skill to remove (repeatable; * drops the whole skills entry)
--mcp <name>MCP to remove (repeatable; * drops the whole mcps entry)
--command <name>Command to remove (repeatable; * drops the whole commands entry)
--ref <ref>Disambiguate by pinned ref when a URL appears more than once
--branch <branch>Disambiguate by tracked branch
--config <path>Config file to edit (default: ./kasetto.yaml); must be local
--no-syncEdit the config without pruning installed assets
--dry-runPreview the edit without writing the config or pruning
--locked, --frozenDuring the follow-up sync, never fetch; honor the lock
--jsonPrint the edit summary as JSON
-q, --quietSuppress non-error output (repeat for stricter silence)
--color <when>auto (default), always, or never
--projectPrune from the current project
--globalPrune globally (default)

Subtracting a name from a "*" wildcard entry is an error (there are no named entries to drop — use --<kind> "*" to remove the whole entry); so is naming a skill that isn't in the list. When several entries share a source URL, pass --ref or --branch to pick one. Entries inherited via extends: live in the parent config and must be removed there.

kst sync

Reads your config, fetches any remote skills, and brings your local install up to date.

kst sync [OPTIONS]

Options

FlagDescription
--config <path-or-url>Path or HTTPS URL to a YAML config (default order: $KASETTO_CONFIG, ./kasetto.yaml, source: in config.yaml, $XDG_CONFIG_HOME/kasetto/kasetto.yaml)
--dry-runPreview what would change without writing anything
-q, --quietSuppress non-error output (repeat for stricter silence)
--jsonPrint the sync report as JSON
--color <when>auto (default), always, or never
-v, --verboseIncrease detail (-v, -vv, -vvv); per-skill action list at -v
--projectInstall into the current project directory
--globalInstall globally (default)

Missing skills are reported as broken but won't stop the rest of the run. The exit code is non-zero only for source-level failures.

--dry-run is great in CI — verify your config without touching anything on disk.

kst lock

Re-resolves every source and pins it into kasetto.lock without installing to your agent directories — the equivalent of cargo generate-lockfile / uv lock. Like sync --update, it re-resolves moving refs (branches and the default HEAD).

kst lock [OPTIONS]

Options

FlagDescription
--config <path-or-url>Path or HTTPS URL to a YAML config (same default order as sync)
--jsonPrint the result as JSON
--check, --locked, --frozenVerify the lock matches the config without writing; exit 1 on drift
-P, --upgrade-package <name>...Only re-resolve sources providing these skills (mirrors sync --update <name>...)
-q, --quietSuppress non-error output (repeat for stricter silence)
--color <when>auto (default), always, or never
--projectLock the project scope (./kasetto.lock)
--globalLock the global scope (default)

Skills are hashed from the materialized source tree. Because a skill installs as a verbatim copy, that hash equals the one a later sync computes at the destination — so after kst lock a plain kst sync --locked succeeds with zero fetches. MCP and command entries can't be hashed without applying their merge/transform, so lock only refreshes their resolved revision pins; their content hash fills in on the next real sync. Any source that fails to resolve aborts the lock before writing.

kst lock reads remote configs fine (it only writes the lock, never the config). kst add / kst remove, which rewrite the config, require a local file.

kst list

Prints a uv-style table of installed assets from the lock file — name, scope, and source per row.

kst list [OPTIONS]

Options

FlagDescription
--type <kind>all (default), skills, mcps, or commands
--jsonOutput as JSON
-q, --quietSuppress output (unless --json is set)
--color <when>auto (default), always, or never
--projectOnly read the project lock (./kasetto.lock) in the current directory
--globalOnly read the global lock (under XDG data)

With no --project or --global, Kasetto merges both scopes so you can see global and project installs together. Each row includes a scope column. The --json shape always includes top-level skills, mcps, commands, and merged_scopes keys; --type filters the contents of each list but never drops the key.

kst doctor

Prints a local health check: your version, lock file location, install paths, last sync time, and any skills that failed.

kst doctor [OPTIONS]

Options

FlagDescription
--jsonOutput as JSON
-q, --quietDo not print anything (unless --json)
--color <when>auto (default), always, or never
--projectShow project-scoped diagnostics
--globalShow globally-scoped diagnostics (default)

kst clean

Removes everything Kasetto installed for the given scope — skills, MCP configs, and lock file entries.

kst clean [OPTIONS]

Options

FlagDescription
--dry-runPreview what would be removed (lists skill paths and MCP packs)
--jsonPrint output as JSON
-q, --quietSuppress non-error output
--color <when>auto (default), always, or never
--projectClean project-scoped assets
--globalClean globally-scoped assets (default)

kst self

Manage Kasetto itself — update to a new version or remove it completely.

kst self update

Fetches the latest release from GitHub, verifies the SHA256 checksum against checksums.txt from the same release, and swaps out the binary in-place.

kst self update [OPTIONS]

Options

FlagDescription
--jsonOutput as JSON

Self-update only works when Kasetto was installed via the standalone installer. For Homebrew or Cargo installs, use their own upgrade commands.

Update notifications

Kasetto prints a yellow New version available: x.y.z → a.b.c line at the end of any command when a newer release exists on GitHub. The check runs in a background thread at most once every 24 hours and stores the result under $XDG_CACHE_HOME/kasetto/update-check.json (default: ~/.cache/kasetto/update-check.json).

The notice is suppressed when:

  • output is --json, --color never, or --quiet
  • the command emits machine-readable content (completions, self update)
  • stdout is not a TTY (e.g. piped to a file)

kst self uninstall

A full teardown: removes installed skills and MCP configs, clears Kasetto's data directories, and deletes the binary.

kst self uninstall [OPTIONS]

Options

FlagDescription
--yesSkip the confirmation prompt (required in non-interactive use)

kst completions

Generates completion scripts for your shell.

kst completions <SHELL>

Supported shells: bash, zsh, fish, powershell.

Example for Fish: kst completions fish > ~/.config/fish/completions/kst.fish

On this page