Kasetto logo

CI Release Rust License Stand with Ukraine

Listed on BacklinkLog

A declarative AI agent environment manager, written in Rust.

kasetto sync output **About the name** Name comes from the Japanese word **カセット** (*kasetto*) - cassette. Think of Skills, MCPs, commands, and instructions as cassettes you plug in, swap out, and share across machines. ## Why Kasetto There are good tools in this space already - [Vercel Skills](https://github.com/vercel-labs/skills) installs skills from a curated catalog, and [Claude Plugins](https://claude.com/plugins) offer runtime integrations. Both work well for one-off installs, but neither gives you a declarative, version-controlled config. Kasetto is a **community-first** project that solves a different problem: **declarative, reproducible AI environment management across projects, machines, and agents.** - **Declarative** — one YAML file, your whole setup: skills, commands, MCPs, instructions, and agents. Apply globally or scope to a project; configs compose with `extends`, so org, team, and project stay in sync - **Enterprise & private repositories** — pull from anywhere: GitHub, GitLab, Bitbucket, Codeberg, Gitea, and self-hosted instances, public or private. Onboard a new engineer with one command; everyone gets the same environment, zero drift - **Multi-agent** — write once, ship everywhere. Claude Code, Cursor, Codex, Windsurf, Copilot, Gemini CLI, and [many more](#supported-agents) — one sync keeps them all current - **Skills, Commands, MCPs & Instructions** — four asset kinds, one source: skills, commands, MCPs, and instructions (`CLAUDE.md`, `.cursor/rules`, `AGENTS.md`, ...). Everything is transformed into each agent's native format, and auto-merged. Distribute instructions, tools, and prompts as easily as sharing a repository link - **Secrets management** — specify `${kst_...}` placeholders into your configs instead of real tokens. At sync time Kasetto pulls the value from your environment, a credentials file, or a secret manager you already use (1Password, Vault, AWS, GCP, Azure, KeePassXC, pass, macOS Keychain) and injects it into the agent's settings only - **Speed** — instant by design. Built in Rust, it hashes content and diffs a lock file so only what changed gets touched — full syncs finish in seconds - **Universal** — one static binary for macOS, Linux, and Windows. Install as `kasetto`, run as `kst`. CI-friendly with `--json` output and real exit codes > Inspired by [cargo](https://github.com/rust-lang/cargo) and [uv](https://github.com/astral-sh/uv) — the same lock-first, declarative, CLI-only ergonomics, applied to AI agent skills. ## Install ### Standalone Installer **macOS and Linux:** ```bash curl -fsSL kasetto.dev/install | sh ``` **Windows:** ```powershell powershell -ExecutionPolicy Bypass -c "irm kasetto.dev/install.ps1 | iex" ``` ### Homebrew ```bash brew tap pivoshenko/tap brew trust pivoshenko/tap brew install kasetto ``` ### Scoop (Windows) ```bash scoop bucket add kasetto https://github.com/pivoshenko/scoop-bucket scoop install kasetto ``` ### Cargo ```bash cargo install kasetto ``` ## Getting Started **1. Scaffold a config:** ```bash kst init # creates ./kasetto.yaml in the current directory kst init --global # or a global one at ~/.config/kasetto/kasetto.yaml ``` Edit the generated `kasetto.yaml` — pick an `agent`, add a `skills:` source, and you're ready to sync. Or let Kasetto edit the config for you: ```bash kst add https://github.com/anthropics/skills # add every skill in the pack kst add https://github.com/anthropics/skills@v1.2.0 # `@` shorthand (cargo/uv-style) kst add https://github.com/anthropics/skills --skill pptx # or just named ones kst add https://github.com/example/repo --skill find --mcp github --command review ``` `kst add` appends the source (keeping your comments) and syncs it in one step; `kst remove ` reverses it. See [cargo/uv-style editing](#commands) below. **2. Sync skills into your agents:** ```bash # uses ./kasetto.yaml in the current directory kst sync # or point at a shared team config over HTTPS kst sync --config https://example.com/team-skills.yaml ``` Want bare `kst sync` to always pull from a remote URL? Persist it in `~/.config/kasetto/config.yaml`: ```yaml source: https://github.com/pivoshenko/pivoshenko.ai/blob/main/kasetto.yaml ``` After that, `kst sync` resolves the URL automatically — no `--config` flag needed. That's it. Kasetto pulls the skills, installs them into the right agent directory, and records exactly what it installed in `kasetto.lock`. Commit `kasetto.yaml` and `kasetto.lock` together (like `Cargo.lock` or `package-lock.json`) and every teammate gets identical versions. A plain `kst sync` honors the lock without re-resolving moving refs; `kst sync --update` rolls versions forward; `kst sync --locked` enforces the lock in CI. See [pivoshenko/pivoshenko.ai](https://github.com/pivoshenko/pivoshenko.ai) for a community example pulling skills from multiple packs for Claude Code and OpenCode. **3. See what's installed:** ```bash kst list # table of installed skills, MCPs, commands, instructions kst list --type skills # filter to one asset kind kst doctor # version, paths, last sync status ``` ## Commands One-line synopsis below. Full flags and examples in the [commands reference](https://kasetto.dev/docs/commands). - **`kst init`** — generate a starter `kasetto.yaml` (local or `--global`) - **`kst add `** — append a source to the config (comments preserved) and sync it in. Kind-tagged repeatable flags `--skill`/`--mcp`/`--command`/`--instruction` name entries (a lone `*` is a wildcard; no flags ⇒ `skills: "*"`), so one `add` can touch several lists. Accepts a cargo/uv-style `@` shorthand and deep `blob`/`tree` browse URLs — the latter decomposed into source + `ref`/`branch` + `sub-dir` (+ skill name for a `SKILL.md` link); `--ref`/`--branch`/`--sub-dir` override. `--dry-run` previews the edit; `--no-sync` edits without installing; `--locked` keeps the follow-up sync offline; `--json` for scripting - **`kst remove `** (alias `rm`) — drop entries from the config and prune the now-unconfigured assets. Mirrors `add`: `--skill`/`--mcp`/`--command`/`--instruction` (repeatable) subtract named entries (last one drops the whole entry; a lone `*` drops it outright); no kind flags removes the source from every list. `--ref`/`--branch` (or the `@` shorthand) disambiguate a repeated URL. `--dry-run` previews; `--no-sync` edits only; `--locked` and `--json` mirror `add` - **`kst lock`** — re-resolve every source and pin it into `kasetto.lock` without installing; skills become offline-ready for `sync --locked`, MCP/command/instruction revision pins refresh. `--check` (alias `--locked`/`--frozen`) verifies the lock matches the config without writing (CI-friendly); `-P`/`--upgrade-package ...` re-resolves only the named skills' sources - **`kst sync`** — read config, install skills + MCPs + commands + instructions into agent dirs honoring `kasetto.lock`; `--update` rolls pins forward, `--locked`/`--frozen` enforce the lock without fetching - **`kst list`** — print a uv-style table of installed skills, MCPs, commands, and instructions from the lock file; `--type skills|mcps|commands|instructions` filters; `--json` for scripting - **`kst doctor`** — local diagnostics: version, paths, last sync status, broken skills - **`kst clean`** — remove tracked skills, commands, MCP configs, and instructions for the given scope - **`kst self update`** — fetch latest release, verify SHA256, replace binary in place - **`kst self uninstall`** — remove installed assets, data, and the binary - **`kst completions `** — emit shell completion script (`bash`/`zsh`/`fish`/`powershell`) Most commands accept `--json`, `--color `, `-q`/`--quiet` (repeat for stricter silence), and `--project | --global`. `--plain` is still accepted as a deprecated alias for `--color never`. ## Configuration When `--config` is omitted, Kasetto looks for config in this order: 1. `$KASETTO_CONFIG` env var 2. `./kasetto.yaml` 3. `source:` key in `$XDG_CONFIG_HOME/kasetto/config.yaml` 4. `$XDG_CONFIG_HOME/kasetto/kasetto.yaml` (or `~/.config/kasetto/kasetto.yaml`) Run `kst init` to scaffold a local config, or `kst init --global` for the global one. ```yaml # Option A: preset destination by agent (see README for supported agent values) agent: - codex - claude-code # Option B: manual destination (takes precedence if both are set) # destination: ./.agents/skills skills: # "*" syncs every skill in the source — each is a directory with a SKILL.md, # discovered in the source root or its skills/ subdirectory - source: https://github.com/vercel-labs/next-skills # ref: v1.0.0 # pin to a tag or commit; omit to track the default branch skills: "*" # or list skills by name - source: https://github.com/anthropics/skills skills: - doc-coauthoring - frontend-design - pptx # sub-dir: resolve the named skills under this path, e.g. skills/productivity/grill-me/ - source: https://github.com/mattpocock/skills sub-dir: skills/productivity skills: - grill-me - caveman # path: a skill in a non-standard location → //, here skills/engineering/improve-codebase-architecture/ - source: https://github.com/mattpocock/skills skills: - name: improve-codebase-architecture path: skills/engineering commands: # names resolve to commands/.md in the source (nested dirs namespace, e.g. git:commit) - source: https://github.com/gsd-build/get-shit-done commands: - gsd:explore - gsd:fast instructions: # instructions wire CLAUDE.md / .cursor/rules / AGENTS.md etc. from instructions/.{md,mdc} # "*" syncs every instruction; aggregate files (CLAUDE.md, AGENTS.md) get managed blocks - source: https://github.com/pivoshenko/pivoshenko.ai instructions: - docs-autoupdate - multi-agent-dispatch mcps: # names resolve to mcps/.json in the source - source: https://github.com/pivoshenko/pivoshenko.ai branch: main # track a specific branch (use ref: to pin a tag or commit) mcps: - github - vercel - kaggle ``` Full key reference, merge instructions, and `extends:` inheritance live in the [configuration docs](https://kasetto.dev/docs/configuration). ### Secrets MCP packs often need a token or password. Reference one with a `${kst_}` placeholder instead of committing it — Kasetto resolves it at sync time and writes the value into the agent's settings file only: ```json { "mcpServers": { "vercel": { "url": "https://mcp.vercel.com", "type": "http", "headers": { "Authorization": "Bearer ${kst_vercel_token}" } } } } ``` Values come from environment variables first (the name as written, then uppercased — `${kst_vercel_token}` reads `KST_VERCEL_TOKEN`), then `~/.config/kasetto/credentials.yaml` (`__` in a name descends nested keys, e.g. `${kst_vercel__token}` → `vercel.token`). To pin exactly one source, use the tagged form `${kst::}`: - **`env`** — Specific environment variable - **`crd`** — Credentials file - **`op`** — 1Password - **`vault`** — HashiCorp Vault - **`kp`** — KeePassXC - **`aws`** — AWS Secrets Manager - **`gcp`** — Google Secret Manager - **`az`** — Azure Key Vault - **`pass`** — Pass / GoPass - **`keychain`** — MacOS Keychain Each external manager inherits your existing CLI session, so kasetto stores no tokens of its own. A missing secret fails the sync (exit non-zero) unless you pass `--allow-missing-secrets`. The resolved value never lands in `kasetto.lock`, so the lock stays commit-safe. Rotated a secret? A plain `sync` won't touch the live entry — run `kst sync --update` to push it. Full details in the [secret-injection docs](https://kasetto.dev/docs/secrets). ## Supported Agents Set the `agent` field and Kasetto figures out where to put things.
Full list of supported agents
| Agent | Config value | Install path | | -------------- | ---------------- | ------------------------------- | | Amp | `amp` | `~/.config/agents/skills/` | | Antigravity | `antigravity` | `~/.gemini/antigravity/skills/` | | Augment | `augment` | `~/.augment/skills/` | | Claude Code | `claude-code` | `~/.claude/skills/` | | Cline | `cline` | `~/.agents/skills/` | | Codex | `codex` | `~/.codex/skills/` | | Continue | `continue` | `~/.continue/skills/` | | Cursor | `cursor` | `~/.cursor/skills/` | | Gemini CLI | `gemini-cli` | `~/.gemini/skills/` | | GitHub Copilot | `github-copilot` | `~/.copilot/skills/` | | Goose | `goose` | `~/.config/goose/skills/` | | Junie | `junie` | `~/.junie/skills/` | | Kiro CLI | `kiro-cli` | `~/.kiro/skills/` | | OpenClaw | `openclaw` | `~/.openclaw/skills/` | | OpenCode | `opencode` | `~/.config/opencode/skills/` | | OpenHands | `openhands` | `~/.openhands/skills/` | | Replit | `replit` | `~/.config/agents/skills/` | | Roo Code | `roo` | `~/.roo/skills/` | | Trae | `trae` | `~/.trae/skills/` | | Warp | `warp` | `~/.agents/skills/` | | Windsurf | `windsurf` | `~/.codeium/windsurf/skills/` | | ZCode | `zcode` | `~/.zcode/skills/` |
Don't see your agent? Use the `destination` field to point at any path. ## Private Repositories & Enterprise Private GitHub, GitLab, Bitbucket, Codeberg, Gitea, and self-hosted instances work via env-var tokens (`GITHUB_TOKEN`, `GITLAB_TOKEN`, `BITBUCKET_TOKEN`, `GITEA_TOKEN`, etc.) — no login command, no credentials file. The same tokens apply to remote `--config` URLs. Full host table and auth resolution instructions in the [authentication docs](https://kasetto.dev/docs/authentication). ## Contributing See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and guidelines. ## License Licensed under either [MIT](LICENSE-MIT) or [Apache-2.0](LICENSE-APACHE), at your option.