skillcask 0.10.6 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,698 +1,144 @@
1
- # skillcask
2
-
3
- A lockfile-first package manager for AI agent skills: directories with a `SKILL.md`, read by
4
- Claude Code, Codex, Junie and others.
5
-
6
- skillcask installs skills the way Cargo or Composer install libraries. It reads a manifest with
7
- version constraints and commits a lock with content hashes. In CI it does frozen installs that
8
- fail on drift, and it links every skill into each agent's skill directory. It ships as a single
9
- static binary with no runtime, so it works in a repository in any language.
10
-
11
- Skills come from Composer repositories or straight from GitHub. Packagist serves public skill
12
- packages; GitLab's Composer registry, Satis, Private Packagist or the static repository built by
13
- `skillcask publish` serve private ones. Any GitHub repository with `SKILL.md` files works too,
14
- which covers most of what [skills.sh](https://skills.sh) lists. skillcask does not need PHP,
15
- Composer or Node.
1
+ <p align="center">
2
+ <picture>
3
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/GetResponse/skillcask/master/docs/assets/wordmark-dark.svg">
4
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/GetResponse/skillcask/master/docs/assets/wordmark-light.svg">
5
+ <img alt="skillcask" src="https://raw.githubusercontent.com/GetResponse/skillcask/master/docs/assets/wordmark-light.svg" width="480">
6
+ </picture>
7
+ </p>
8
+
9
+ <p align="center">
10
+ <strong>A lockfile-first package manager for AI agent skills.</strong><br>
11
+ One manifest, one lock, every agent's skill directory.
12
+ </p>
13
+
14
+ <p align="center">
15
+ <a href="https://github.com/GetResponse/skillcask/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/GetResponse/skillcask/actions/workflows/ci.yml/badge.svg"></a>
16
+ <a href="https://crates.io/crates/skillcask"><img alt="crates.io" src="https://img.shields.io/crates/v/skillcask"></a>
17
+ <a href="https://www.npmjs.com/package/skillcask"><img alt="npm" src="https://img.shields.io/npm/v/skillcask"></a>
18
+ <a href="https://github.com/GetResponse/homebrew-tap"><img alt="Homebrew: getresponse/tap" src="https://img.shields.io/badge/homebrew-getresponse%2Ftap-orange"></a>
19
+ <a href="#license"><img alt="License: MIT OR Apache-2.0" src="https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue"></a>
20
+ </p>
21
+
22
+ skillcask installs skills (directories with a `SKILL.md`, read by Claude Code, Codex, Junie and
23
+ others) the way Cargo or Composer install libraries: a manifest with version constraints, a
24
+ committed lock with content hashes, and frozen installs in CI that fail on drift. It ships as a
25
+ single static binary with no runtime, and takes skills from Composer repositories, GitHub (which
26
+ covers most of what [skills.sh](https://skills.sh) lists) and any git repository over HTTPS.
16
27
 
17
28
  ## Install
18
29
 
19
- **macOS, Linux**
20
-
21
30
  ```sh
22
- brew install getresponse/tap/skillcask
23
- # or, without Homebrew:
31
+ brew install getresponse/tap/skillcask # macOS, Linux
24
32
  curl --proto '=https' --tlsv1.2 -LsSf https://github.com/GetResponse/skillcask/releases/latest/download/skillcask-installer.sh | sh
33
+ npm install -g skillcask # or: cargo install --locked skillcask
25
34
  ```
26
35
 
27
- **Windows (PowerShell)**
28
-
29
- ```powershell
30
- powershell -ExecutionPolicy Bypass -c "irm https://github.com/GetResponse/skillcask/releases/latest/download/skillcask-installer.ps1 | iex"
31
- ```
32
-
33
- The two installer scripts download the binary for your platform from the latest release and put
34
- it in `~/.cargo/bin` (`%USERPROFILE%\.cargo\bin` on Windows).
35
-
36
- **Desktop app (macOS 14+ only for now)**
37
-
38
- ```sh
39
- brew install getresponse/tap/skillcask getresponse/tap/skillcask-app
40
- skillcask app # or open Skillcask from Applications
41
- ```
42
-
43
- Install with the full names: Homebrew loads a third-party tap's cask only when it is named in full
44
- (or listed by `brew trust`); after that, `brew upgrade` takes the short name.
45
-
46
- The tap was `puniserv/tap` before 0.10.5. If you installed from it, move to the new name once
47
- (your app settings stay):
48
-
49
- ```sh
50
- brew uninstall --cask puniserv/tap/skillcask-app # skip if you have no app
51
- brew uninstall puniserv/tap/skillcask
52
- brew untap puniserv/tap
53
- brew install getresponse/tap/skillcask getresponse/tap/skillcask-app
54
- ```
55
-
56
- Without Homebrew:
57
-
58
- ```sh
59
- curl --proto '=https' --tlsv1.2 -LsSf https://github.com/GetResponse/skillcask/releases/latest/download/skillcask-app-installer.sh | sh
60
- ```
61
-
62
- The installer downloads `Skillcask-X.Y.Z-macos-universal.zip` (signed and notarized, with its own
63
- CLI inside) from the latest release, checks its sha256 and Gatekeeper's verdict, and moves the app
64
- to `/Applications`; an earlier copy goes to the Trash. It leaves a Homebrew install alone.
65
- `SKILLCASK_VERSION=X.Y.Z` picks a release, `SKILLCASK_APP_DIR` another folder.
66
-
67
- Linux and Windows have the terminal UI, `skillcask ui`. More in [macOS app](#macos-app).
68
-
69
- **npm, bun**
70
-
71
- ```sh
72
- npm install -g skillcask # global
73
- bun add -g skillcask # global, bun
74
- npx skillcask install --frozen
75
- bunx skillcask install --frozen
76
- ```
77
-
78
- The npm package is a thin wrapper that downloads the release binary for your platform from
79
- GitHub. It does not check a checksum itself; where that matters, use Homebrew or a release
80
- archive and verify it.
81
-
82
- **Cargo**
83
-
84
- ```sh
85
- cargo install --locked skillcask
86
- ```
87
-
88
- **Release archives** for macOS, Linux and Windows are on the
89
- [releases page](https://github.com/GetResponse/skillcask/releases), with sha256 checksums and GitHub
90
- build provenance attestations:
91
-
92
- ```sh
93
- gh attestation verify skillcask-x86_64-unknown-linux-gnu.tar.xz -R GetResponse/skillcask
94
- ```
95
-
96
- Releases up to 0.10.2 were built before the repository moved and verify with `--owner puniserv --signer-repo puniserv/skillcask`.
36
+ Windows, the desktop app, bun, release archives with attestations, the GitHub Action and updating:
37
+ [Install guide](docs/guide/install.md).
97
38
 
98
- **GitHub Actions**
99
-
100
- ```yaml
101
- permissions:
102
- contents: read
103
- attestations: read # for the provenance check
104
- steps:
105
- - uses: actions/checkout@<sha>
106
- - uses: GetResponse/skillcask@<commit sha of a release tag> # vX.Y.Z
107
- with:
108
- version: X.Y.Z # needed when the action is pinned to a sha, not a tag
109
- args: install --frozen # default
110
- # working-directory: .
111
- # verify-attestation: "true" # default
112
- ```
113
-
114
- The action downloads the release archive for the runner (Linux x64 and arm64, macOS, Windows
115
- x64), checks its sha256 and its build provenance attestation, puts `skillcask` on `PATH` and runs
116
- it with `args`. It runs no other action. Used at a tag (`@vX.Y.Z`) it takes the version from the
117
- tag.
118
-
119
- ### Update
120
-
121
- `skillcask self-update` reruns the release's installer when `skillcask-installer.sh` installed
122
- this binary (Linux, macOS); for any other install it prints the one command to run and exits 1.
123
- `SKILLCASK_SELF_UPDATE=0` makes it print the installer command too. By hand:
124
-
125
- ```sh
126
- brew update && brew upgrade skillcask skillcask-app # Homebrew (skillcask alone without the app)
127
- npm install -g skillcask@latest # npm (bun: bun add -g skillcask@latest)
128
- cargo install --locked skillcask # Cargo
129
- ```
130
-
131
- The installer scripts (`skillcask-installer.sh`, `skillcask-installer.ps1`,
132
- `skillcask-app-installer.sh`) install the latest release when run again; the app's installer moves
133
- the earlier copy to the Trash. The app's own CLI updates with the app; Homebrew updates the app and
134
- the CLI on your `PATH` separately, which is why `brew upgrade` names both. For the GitHub Action,
135
- bump the pinned commit and `version`. `skillcask --version` prints what you have.
136
-
137
- ## Use
39
+ ## Quickstart
138
40
 
139
41
  ```sh
140
- skillcask add netresearch/agent-jira-skill # resolve, write skills.toml + skills.lock, install
141
- skillcask add github:mattpocock/skills/tdd # one skill from a GitHub repository
142
- skillcask install --frozen # CI: install exactly the lock or exit non-zero
143
- skillcask status # manifest vs lock vs installed files
144
- ```
145
-
146
- `add` creates:
147
-
148
- ```
149
- skills.toml # manifest, commit it
150
- skills.lock # lock, commit it
151
- .agents/skills/<name>/ # installed skill (gitignored)
152
- .agents/skills/.skillcask-installed # what this machine installed (gitignored)
153
- .claude/skills/<name> -> ../../.agents/skills/<name>
154
- .gitignore # managed block
155
- ```
156
-
157
- Project skills live in `.skills/<name>/SKILL.md` (`[agents] local`). skillcask links each one
158
- into the store (`.agents/skills/<name> -> ../../.skills/<name>`) and from there into every agent
159
- directory. These links are committed, so they work in every clone. A directory written by hand
160
- straight into `.agents/skills/` is linked the same way. A project skill with the same name as a
161
- locked one is an error. When a skill with the same name exists in your home (`~/.claude/skills`,
162
- `~/.agents/skills`, …), `install` and `doctor` print a warning: Claude Code runs the personal one,
163
- Codex lists both.
164
-
165
- ### skills.toml
166
-
167
- ```toml
168
- [repositories]
169
- acme = { type = "composer", url = "https://git.example.com/api/v4/group/42/-/packages/composer/packages.json" }
170
- # A repository you review yourself can skip the cooldown; the others keep it.
171
- own = { url = "https://git.example.com/own/packages.json", min-release-age = "0" }
172
- # Default sources, written by `init`; `= false` turns one off. Packagist is always searched last.
173
- packagist = { url = "https://repo.packagist.org" }
174
- github = { type = "github", url = "https://api.github.com" } # GitHub Enterprise: its API URL
175
-
176
- [skills]
177
- "netresearch/agent-jira-skill" = "^3.34"
178
- "acme/agents-md" = { version = "^1.0", repository = "acme" }
179
- "acme/review" = { version = "1.4.2", repository = "acme", skills = ["review"] }
180
- "mattpocock/skills" = { github = true, version = "^1.3", skills = ["tdd", "code-review"], rename = { code-review = "mp-code-review" } }
181
- "anthropics/skills" = { github = true, skills = ["pdf"] } # default branch
182
-
183
- [agents]
184
- targets = ["claude", "kiro"] # agent names or paths with a "/"; default: config.toml, else ["claude"]
185
- local = ".skills" # project skills
186
-
187
- [policy]
188
- min-release-age = "3d" # cooldown for add/update; "0" disables
189
- allow-ranges = true # false: every version must be exact
190
- packagist = true # false: drop the implicit Packagist repository
191
- github-requires = false # true: dependencies may come from GitHub or git URLs
192
- allow-sources = ["acme", "own", "packagist", "github"] # only these sources; default: all
193
- deny-patterns = false # true: risky patterns and invisible characters in new skill text fail instead of warning
194
- deny-packages = ["evil/*"] # refused by name from any source, also in a lock; default: none
195
- ```
196
-
197
- ### Agents
198
-
199
- Most agents read `.agents/skills` themselves (Codex, Copilot, Cursor, Gemini CLI, OpenCode, Amp,
200
- Junie, Devin/Windsurf, Roo Code, Cline, Goose, Factory, Mistral Vibe), so they need no link.
201
- `[agents] targets` lists the agents that need one, by name, or any directory as a path with a `/`:
202
-
203
- | Name | Project | Home (`--global`) |
204
- |---|---|---|
205
- | `claude` | `.claude/skills` | `~/.claude/skills` |
206
- | `kiro` | `.kiro/skills` | `~/.kiro/skills` |
207
- | `junie` | store | `~/.junie/skills` |
208
- | `codex`, `copilot`, `cursor`, `gemini`, `opencode`, `amp`, `devin`, `roo`, `cline`, `goose`, `factory`, `vibe` | store | store |
209
-
210
- Set the list once in `config.toml` next to the global manifest; a `skills.toml` that sets
211
- `targets` replaces it. Manifests from before 0.6.0 carry an explicit list: delete the line to
212
- follow `config.toml`.
213
-
214
- ```toml
215
- # ~/.config/skillcask/config.toml
216
- [agents]
217
- targets = ["claude", "kiro"]
218
-
219
- [search]
220
- skills-sh = true # search also asks skills.sh (it receives the query); written by search --remember or skillcask -g config search.skills-sh true
221
- ```
222
-
223
- When a target is dropped, the next `install` removes the links skillcask made there; `doctor`
224
- reports them. `status` prints the targets, where they came from and the directories they link.
225
-
226
- Constraints follow Composer semantics: `^0.3` means `>=0.3.0 <0.4.0`, `~1.2` means
227
- `>=1.2 <2.0`, and pre-releases are only selected when the constraint names a stability
228
- (`^1.0@beta`).
229
-
230
- ### Allowed sources and policy for every project
231
-
232
- `allow-sources` lists the only places skills may come from: repository names, `packagist`, `github`,
233
- or `https://` URL prefixes (`https://api.github.com/repos/acme/` allows one GitHub organisation).
234
- End a prefix with `/` (`https://gitlab.example.com/`): an entry without one also names a registry
235
- declared at exactly that URL, whose archives may then come from any host. Other repositories get no
236
- request, and `install` refuses a lock entry from them, also with `--frozen`, so a committed lock
237
- cannot bring them back. Dependencies follow the same rule.
238
-
239
- `deny-packages` refuses packages by name, `vendor/name` or a whole `vendor/*`, whatever source
240
- serves them (a GitHub `owner/repo` counts as `owner/repo`). A plain git entry is matched by its key
241
- in `skills.toml`, which the project picks, so limit git URLs with `allow-sources`. It is checked
242
- before any download and again on every lock entry, so it also stops a dependency or a committed
243
- lock. Enforced in `config.toml`, the list is a floor: a project may add packages to it, not drop
244
- any.
245
-
246
- Policy can also come from `config.toml` next to the global manifest (`~/.config/skillcask`) and
247
- from the environment. The first layer that sets a key wins:
248
-
249
- 1. `SKILLCASK_ALLOW_SOURCES`, `SKILLCASK_MIN_RELEASE_AGE`, `SKILLCASK_ALLOW_RANGES`,
250
- `SKILLCASK_PACKAGIST`, `SKILLCASK_GITHUB_REQUIRES`, `SKILLCASK_DENY_PATTERNS`,
251
- `SKILLCASK_DENY_PACKAGES` (lists comma-separated; against an enforced key only a stricter value
252
- is accepted: a longer cooldown, `deny-patterns` on, the others off, narrower sources, more
253
- denied packages);
254
- 2. keys `config.toml` lists in `enforce`: a project that sets them otherwise fails;
255
- 3. `[policy]` in `skills.toml`;
256
- 4. the other keys of `config.toml`, as defaults.
257
-
258
- ```toml
259
- # ~/.config/skillcask/config.toml: only the company registry and GitHub, in every project
260
- [policy]
261
- allow-sources = ["https://gitlab.example.com/", "github"]
262
- enforce = ["allow-sources"]
263
- ```
264
-
265
- `"github"` in an enforced `allow-sources` is public GitHub (`https://api.github.com/repos/`):
266
- `SKILLCASK_GITHUB_API` and `GITHUB_API_URL` do not move it. For GitHub Enterprise, enforce its
267
- prefix, e.g. `"https://ghe.example.com/api/v3/repos/"`.
268
-
269
- An enforced `min-release-age` also applies to a repository's own `min-release-age`: a project
270
- may only make it longer. Exceptions, by URL prefix, stay in `config.toml`:
271
-
272
- ```toml
273
- [policy]
274
- min-release-age = "3d"
275
- enforce = ["min-release-age"]
276
-
277
- [policy.repository-min-release-age]
278
- "https://gitlab.example.com/" = "0" # internal skills, reviewed in merge requests
42
+ skillcask init # create skills.toml
43
+ skillcask add netresearch/agent-jira-skill # resolve, write skills.toml + skills.lock, install
44
+ skillcask add github:mattpocock/skills/tdd # one skill from a GitHub repository
45
+ skillcask status # manifest vs lock vs installed files
46
+ skillcask install --frozen # CI: install exactly the lock or exit non-zero
279
47
  ```
280
48
 
281
- `enforce` stops a project and its dependencies from loosening the policy for what they resolve, and
282
- a lock entry from a source outside an enforced `allow-sources`, or younger than an enforced or
283
- environment `min-release-age`, from installing. The environment, which a project's CI configuration
284
- also sets, may only make an enforced key stricter. A pinned version is not scanned again for `deny-
285
- patterns`, and its release time is what the lock says. Under `allow-sources`, a GitHub or git entry
286
- downloads only from its repository, and a registry the list admits only by a prefix only from inside
287
- the list; the archive URL of Packagist or a registry the list names (or gives by its exact URL,
288
- without a trailing `/`) is what the lock says, so review lock changes. `enforce` does not stop the
289
- person running skillcask: `SKILLCASK_HOME`, `XDG_CONFIG_HOME` or `HOME` can point at a config
290
- without it. For a rule nobody may skip, run `skillcask install --frozen` as a required check on pull
291
- requests, with the policy in the job's environment and `.github/workflows/` protected (CODEOWNERS or
292
- a required workflow), since a pull request runs its own copy of the workflow.
49
+ Commit `skills.toml` and `skills.lock`; the installed skills are gitignored. In GitHub Actions,
50
+ `uses: GetResponse/skillcask@<commit sha of a release tag>` with `version: X.Y.Z` runs
51
+ `install --frozen` ([setup](docs/guide/install.md)).
293
52
 
294
- `config.toml` and the environment take URL prefixes, not repository names, since a name means
295
- whatever a project calls it. `skillcask status` prints each key that is set and where it came
296
- from.
53
+ ## Why skillcask
297
54
 
298
- ### Dependencies
55
+ - **Locked and verified.** The lock pins the version, the commit reference, the sha256 of the
56
+ downloaded archive and the tree hash of every installed skill; `install` verifies both hashes.
57
+ - **Every agent.** Skills go to `.agents/skills`, which most agents read themselves, with links
58
+ into `.claude/skills`, `.kiro/skills` or any directory you name.
59
+ - **Your sources.** Packagist, GitLab's Composer registry, Satis, Private Packagist, GitHub, any
60
+ git server over HTTPS, or a static repository built by `skillcask publish`.
61
+ - **Reviewable updates.** A release-age cooldown (`init` writes `3d`), `outdated --strict` for
62
+ scheduled jobs, and `diff` / `diff --from old.lock` to read the skill text a change brings in.
63
+ - **Policy for every project.** `allow-sources`, `deny-packages`, exact versions only, and keys that
64
+ `config.toml` enforces so a project cannot loosen them.
65
+ - **Audit.** `audit` lists what each skill reaches (commands, hosts, paths, env vars, scripts),
66
+ flags risky lines and invisible characters, and prints SARIF; `--advisories` also checks
67
+ published security advisories.
68
+ - **Data only.** No package code runs, ever. No telemetry. No PHP, Composer or Node needed.
299
69
 
300
- A skill that needs other skills lists them in its `SKILL.md`:
70
+ ## How it works
301
71
 
302
- ```yaml
303
- ---
304
- name: gitlab-branch-mr
305
- version: 1.2.0
306
- requires:
307
- acme/security-review: ^1.0
308
- github:mattpocock/skills/pr: main
309
- "git:https://git.example.com/team/skills.git#review": ^2.0
310
- ---
311
72
  ```
312
-
313
- `add`, `install` and `update` resolve, lock and install them like your own entries: same
314
- cooldown, same hashes, one version per package (the highest one every requirer accepts). They
315
- stay out of `skills.toml`; the lock records each package's `requires` and switches to
316
- `version = 2`. A dependency is looked up only in your repositories, in order, then Packagist;
317
- a `github:` or `git:<url>[#skill]` one needs `github-requires = true`. `remove` drops dependencies nobody needs any
318
- more, and `status` shows them as `via <requirer>`.
319
-
320
- ### Name conflicts
321
-
322
- Skills have no namespaces: an agent knows a skill by its name. Two skills with the same name in
323
- one project are an error. Install one of them under another name with `rename`:
324
-
325
- ```toml
326
- "mattpocock/skills" = { github = true, rename = { code-review = "mp-code-review" } }
73
+ skills.toml ──add/update──▶ skills.lock ──install──▶ .agents/skills/<name>/ read by Codex, Cursor, Gemini CLI, …
74
+ manifest, lock, commit it ├─▶ .claude/skills/<name> link ([agents] targets)
75
+ commit it └─▶ .kiro/skills/<name> link
327
76
  ```
328
77
 
329
- skillcask then installs `.agents/skills/mp-code-review` and changes the `name:` line in its
330
- `SKILL.md`; the lock records the original name and the hash of the renamed copy. Nothing else in
331
- the skill changes, so text that mentions the old name (`/code-review`) stays as it is.
332
- `add`, `install` and `update` offer the rename when they hit a conflict in a terminal.
78
+ `add` and `update` resolve the constraints in `skills.toml` and write the exact versions and
79
+ hashes to `skills.lock`; `install` installs exactly what the lock pins and fails on any hash
80
+ mismatch. Details: [Use](docs/guide/usage.md).
333
81
 
334
- ### Personal skills (`--global`)
82
+ ## macOS app
335
83
 
336
- `skillcask --global` (`-g`) manages skills for your user instead of a project, with the same
337
- manifest, lock and verification:
84
+ <picture>
85
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/GetResponse/skillcask/master/docs/assets/macos-app-dark.png">
86
+ <img alt="Skillcask for macOS: a project's skills with their state, and the details of one skill" src="https://raw.githubusercontent.com/GetResponse/skillcask/master/docs/assets/macos-app-light.png" width="800">
87
+ </picture>
88
+
89
+ <table>
90
+ <tr>
91
+ <td width="33%"><picture>
92
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/GetResponse/skillcask/master/docs/assets/macos-updates-dark.png">
93
+ <img alt="Reviewing an update as a diff before applying it" src="https://raw.githubusercontent.com/GetResponse/skillcask/master/docs/assets/macos-updates-light.png">
94
+ </picture></td>
95
+ <td width="33%"><picture>
96
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/GetResponse/skillcask/master/docs/assets/macos-audit-dark.png">
97
+ <img alt="Security findings for a skill" src="https://raw.githubusercontent.com/GetResponse/skillcask/master/docs/assets/macos-audit-light.png">
98
+ </picture></td>
99
+ <td width="33%"><picture>
100
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/GetResponse/skillcask/master/docs/assets/macos-add-dark.png">
101
+ <img alt="Searching and adding a skill" src="https://raw.githubusercontent.com/GetResponse/skillcask/master/docs/assets/macos-add-light.png">
102
+ </picture></td>
103
+ </tr>
104
+ <tr><td align="center">Review updates</td><td align="center">Audit findings</td><td align="center">Add skills</td></tr>
105
+ </table>
106
+
107
+ A SwiftUI app for macOS 14+ over the CLI: see each skill's state, updates and audit findings, read
108
+ its SKILL.md and diffs, and add, update or remove skills. Linux and Windows have the terminal UI,
109
+ `skillcask ui`.
338
110
 
339
111
  ```sh
340
- skillcask -g add github:mattpocock/skills/grill-me
341
- skillcask -g install --frozen # e.g. from a dotfiles repository
112
+ brew install getresponse/tap/skillcask getresponse/tap/skillcask-app
342
113
  ```
343
114
 
344
- - `skills.toml`, `skills.lock` and an optional `auth.json` live in `~/.config/skillcask`
345
- (`$XDG_CONFIG_HOME/skillcask`; `SKILLCASK_HOME` overrides both). Keep them in your dotfiles.
346
- - Skills go to `~/.agents/skills` (read by most agents), with links in `~/.claude/skills`
347
- (`[agents] targets`, see Agents). Links are absolute, so a symlinked
348
- `~/.claude` works. `[agents] local` does not apply.
349
- - Personal skills you wrote by hand stay where they are and are not linked anywhere. `status`
350
- lists them, and copies other tools put in a target, as `not managed`; `status --json` names the
351
- source `npx skills` recorded for one. `skillcask -g add --adopt <source>` moves such a skill to
352
- `~/.config/skillcask/adopted/` and installs the package's skill of the same name in its place.
353
- - The list of managed paths is `~/.agents/skills/.skillcask-installed`, local to the machine;
354
- nothing touches git.
115
+ More in [macOS app](docs/guide/macos-app.md).
355
116
 
356
- ### Commands
117
+ ## Documentation
357
118
 
358
- Every command except `publish`, `validate` and `projects` takes `-g, --global`.
359
-
360
- | Command | |
119
+ | Guide | |
361
120
  |---|---|
362
- | `init` | Create `skills.toml`. |
363
- | `add <vendor/name>[@constraint] [--repository r]` | Resolve, lock and install. |
364
- | `add github:<owner/repo>[/skill][@version-or-ref]` | The same from a GitHub repository, see below. |
365
- | `add git:<https-url>[@version-or-ref]` | The same from any git repository over HTTPS, see below. |
366
- | `remove <vendor/name>…` | Drop from manifest and lock; delete files, links and gitignore lines. |
367
- | `install [--frozen]` | Install the lock. `--frozen` (implied by `CI`) fails when the lock is out of date. |
368
- | `update [vendor/name…] [--diff]` | Re-resolve within constraints. `--diff` prints what changes in each updated or added package; it does not ask before installing. |
369
- | `outdated [--strict]` | Newer versions, when cooled-down ones become eligible, and GitHub or git tags moved since they were locked. `--strict` exits 1 when `update` would lock a newer version. |
370
- | `diff [vendor/name] [--to constraint\|--from old.lock]` | Unified diff of skill files from the locked version to the one `update` would lock, or from an older lock to `skills.lock`, see below. |
371
- | `info <vendor/name[@constraint]\|github:owner/repo\|git:url\|skill>` | A package's skills, versions, description, license and requirements, or which package installs a skill. |
372
- | `status` | Exit 1 when manifest, lock or installed files disagree. Also lists the repositories in use (name, type, URL without credentials) and whether `allow-sources` admits each. |
373
- | `doctor [--fix]` | Broken or committed links, stale gitignore block, modified skills; lists each check it ran. |
374
- | `audit [--json\|--sarif] [--advisories]` | What each installed skill reaches (commands, hosts, paths, env vars, scripts) and its findings: modified files, risky lines, invisible characters; with `--advisories` also published security advisories and abandoned packages. Exit 1 on any finding. |
375
- | `config [key [value…]] [--unset] [--json]` | Settings with where each comes from: `[policy]` and `[agents] targets` of `skills.toml`, or with `-g` of `config.toml` (also `policy.enforce` and `search.skills-sh`). `config policy.min-release-age 5d` sets a key, `--unset` removes it, each checked before the file is written; `config edit` opens the file in `$VISUAL`/`$EDITOR` and checks it afterwards. |
376
- | `search [query] [--skills-sh\|--no-skills-sh [--remember]]` | Packagist (`type=ai-agent-skill`) and skill packages of the other repositories, GitLab included; with skills.sh on, also the GitHub skills it lists, as `github:owner/repo/skill` with their install count. skills.sh is off until you turn it on, since it receives the query: the first search in a terminal asks once, `--remember` saves a flag's choice (no query needed), both in `config.toml`. |
377
- | `auth set\|remove <host>` | Keep a registry token in git's credential helper (Keychain, Credential Manager, libsecret). |
378
- | `publish --vendor v --base-url URL --out DIR [--inline] [--dist-url TPL] [paths…]` | Build a static Composer repository from a monorepo. |
379
- | `validate [paths…]` | Check `SKILL.md` files against the Agent Skills spec, see below. |
380
- | `projects [dirs…]` | Directories that hold `skills.toml` under the given ones (default: the current one), up to 6 levels down; hidden directories, `node_modules`, `vendor`, `target` and `Library` are skipped. |
381
- | `ui` | A terminal UI over the commands above: skills with their state and updates, `info`, SKILL.md and `audit` per skill, add, adopt (also offered when an add hits a skill skillcask does not manage), update (diff first), remove, doctor, a filter of the list, search of the registries (and skills.sh, asked once), the repositories in use (`R`, `S` turns skills.sh on or off) and a projects picker; `g` switches between the project and `--global`. |
382
- | `app` | Opens the macOS app (see [macOS app](#macos-app)); exits 1 when it is not installed, and on Linux and Windows. |
383
- | `self-check [--json]` | Whether a newer skillcask is released, from the `skillcask-app` cask file of the tap; one anonymous request, only when run; writes nothing. |
384
- | `self-update [--dry-run]` | Update skillcask: reruns the release's installer for an installer-script install (Linux, macOS), else prints the Homebrew, npm, cargo or app command and exits 1. `--dry-run` prints what would run. |
385
- | `<other>` | Runs `skillcask-<other>` from `PATH`, like git and cargo plugins. |
386
-
387
- `status`, `outdated`, `info`, `search`, `doctor`, `audit`, `projects`, `config` and
388
- `self-check` take `--json`: one JSON document on one line of stdout, with the same exit code;
389
- warnings and errors stay on stderr. Package text in it is escaped as in the terminal
390
- (`<U+202E>`). `status --json` has `repositories`
391
- (`[{"name", "type", "url", "allowed"}]`) and `skills-sh`; `search --json` results carry `source` (the repository
392
- name, or `skills.sh`) and `installs`, and the document has `"skills-sh": true|false|null` (`null`:
393
- never decided). `self-check --json` is `{"version", "latest", "newer"}` (`latest` is `null` when
394
- the cask holds no readable version). For example `skillcask outdated --json | jq
395
- '.packages[] | select(.within != .locked)'`.
396
-
397
- Exit codes: 0 ok, 1 manifest/lock/status problems, 2 authentication, 3 network, 4 hash mismatch,
398
- 5 IO or archive error. `self-update` exits 1 when it updated nothing and printed the command to run;
399
- when it runs the installer, the installer's exit code is its own.
400
-
401
- Output is coloured in a terminal (`NO_COLOR` turns it off, `CLICOLOR_FORCE` on) and errors name
402
- the next step on a `hint:` line. For coding agents, `--agent` or `SKILLCASK_AGENT=1` prints terse,
403
- uncoloured, tab-separated output with only the rows that need action; it is on by itself when
404
- `AI_AGENT` or `CLAUDECODE=1` is set, unless `SKILLCASK_AGENT=0`.
405
-
406
- A failed connection, HTTP 429 or a 5xx response is retried twice, after 1 s and 2 s or after the
407
- `Retry-After` seconds the server sends. A `Retry-After` above 60 s, a spent GitHub rate limit, a
408
- timeout or a TLS error fails at once.
409
-
410
- `add`, `update` and `outdated` warn about a package its registry marks `abandoned` and name the
411
- replacement when there is one (and it is a valid package name). Installing from the lock does not ask the registry.
412
-
413
- **Reviewing an update:** a skill is a prompt, so read what changes before you take it.
414
- `skillcask diff` prints a unified diff of the skill files, from the locked version to the one
415
- `update` would lock (newest within the constraint, past the cooldown), for every entry in
416
- `skills.toml` with a newer version; `diff vendor/name --to 2.0.0` compares one package with
417
- another version. A package new to the lock, such as a dependency a new version adds, is shown as
418
- all added. Nothing is installed or written. Control characters, bidi controls and other
419
- invisible characters in the diff are shown as `<U+XXXX>` (a carriage return too, when the line
420
- ends change), and invisible characters in changed files are warned about. Files over 1 MiB or
421
- 10,000 lines print `Files differ (too large to show)`. `update --diff` prints the same diff
422
- before it writes the lock, then installs without asking: run `skillcask diff` first to review
423
- and decide. A scheduled CI job can run `skillcask outdated --strict` (exit 1 when something is to
424
- update), then `skillcask update --diff` and open a pull request with the output.
425
-
426
- **Reviewing a lock change:** `skillcask diff --from old.lock` prints the same diff from the
427
- versions in another lock to those in `skills.lock`, plus the packages it drops, so a reviewer
428
- sees the skill text a pull request brings in instead of new versions and hashes. Each new dist
429
- is verified against `skills.lock` as `install` would, and the policy decides which repositories
430
- may be fetched. skillcask does not run git; the job fetches the old lock:
431
-
432
- ```yaml
433
- # GitLab CI: print the diff in the merge request pipeline
434
- skills-diff:
435
- rules:
436
- - if: $CI_PIPELINE_SOURCE == "merge_request_event"
437
- changes: [skills.lock]
438
- script:
439
- - git fetch --depth 1 origin "$CI_MERGE_REQUEST_TARGET_BRANCH_NAME"
440
- - git show FETCH_HEAD:skills.lock | skillcask diff --from -
441
- ```
442
-
443
- `--from -` reads the old lock from stdin. On GitHub the same lines run in a `pull_request` job with `$GITHUB_BASE_REF`; posting the
444
- output as a comment is up to the CI.
445
-
446
- **Where a skill comes from:** `skillcask info vendor/name` shows the package's skills with their
447
- descriptions, its versions, description, license, `abandoned` and `requires`, for the locked
448
- version or else the newest one `add` would take (`@constraint` for another); `info
449
- github:owner/repo` lists the skills of a GitHub repository before you add it. `skillcask info
450
- <skill>` names the package that installs an installed skill and the `skills.toml` entry, or the
451
- chain of `requires`, that brings it in.
452
-
453
- **Merge conflicts in `skills.lock`:** a lock with conflict markers fails with a hint. Resolve
454
- `skills.toml`, keep either side of the lock (`git checkout --theirs skills.lock`) and run
455
- `skillcask install`: it locks the entries from the other side that the kept lock lacks.
456
-
457
- ### Skills from GitHub and skills.sh
458
-
459
- [skills.sh](https://skills.sh) lists skills as `owner/repo/skill`, for example
460
- `mattpocock/skills/grill-me`. Put `github:` in front and add it:
461
-
462
- ```sh
463
- skillcask add github:mattpocock/skills/grill-me # one skill
464
- skillcask add github:mattpocock/skills/tdd # a second one from the same repository
465
- skillcask add github:anthropics/skills # every skill in the repository
466
- ```
467
-
468
- All skills of one repository share one entry in `skills.toml`:
469
-
470
- ```toml
471
- "mattpocock/skills" = { github = true, version = "^1.3", skills = ["grill-me", "tdd"] }
472
- ```
473
-
474
- Which version you get:
475
-
476
- - **Repository with version tags** (`v1.3.1`): `add` writes `version = "^<major.minor>"`, like
477
- for Composer packages, and `update` moves within it. The release time of a tag is its commit
478
- date.
479
- - **Repository without tags**: the entry follows the default branch; `ref = "main"` names a
480
- branch, tag or commit instead. The lock pins the commit sha, so `install` keeps installing that
481
- commit until you run `update`.
482
- - `@` picks explicitly: `github:owner/repo@^2.0` (version tags), `github:owner/repo@main` or
483
- `@<commit sha>` (ref).
484
- - With `policy.allow-ranges = false` a branch counts as a range: `add` writes the full commit sha
485
- as `ref`, and a hand-written branch name is rejected.
486
-
487
- Skills are found by their `SKILL.md` anywhere in the repository, except inside another skill.
488
- The install name is the frontmatter `name`; when that is not a valid name (`Jira Automation`), the
489
- directory name is used. `skills = [...]` takes these names.
490
-
491
- GitHub allows 60 anonymous API requests per hour. `add`, `update` and `outdated` use a few per
492
- entry; `install` from the lock uses none, it downloads the pinned archive. Set `GITHUB_TOKEN`
493
- (GitHub Actions has one) or Composer's `"github-oauth": {"github.com": "<token>"}` in `auth.json`
494
- for a higher limit and for private repositories. `SKILLCASK_GITHUB_API` points at GitHub
495
- Enterprise (`https://ghe.example.com/api/v3`). `GITHUB_TOKEN` is sent only to the API the user or
496
- the runner names: `SKILLCASK_GITHUB_API`, else GitHub Actions' `GITHUB_API_URL`, else
497
- `api.github.com`; for an Enterprise URL set only in `skills.toml`, use
498
- `skillcask auth set ghe.example.com --username oauth2` or `github-oauth` in `auth.json`.
499
-
500
- skills.sh itself is not queried: its API is undocumented and may change without notice. Search
501
- on the website, then add what you picked.
502
-
503
- ### Skills from any git repository
504
-
505
- GitLab, Bitbucket, Azure DevOps, Gitea or a self-hosted server work without a Composer registry:
506
-
507
- ```sh
508
- skillcask add git:https://gitlab.example.com/acme/skills.git
509
- skillcask add git:https://gitlab.example.com/acme/skills.git@main
510
- ```
511
-
512
- ```toml
513
- "acme/skills" = { git = "https://gitlab.example.com/acme/skills.git", version = "^1.0" }
514
- ```
515
-
516
- Versions, `ref` and `skills = [...]` work as for GitHub; the entry is named after the last two
517
- parts of the URL. skillcask speaks git's HTTPS protocol itself: no git binary runs, so no hook or
518
- filter of the repository can. It fetches the one commit it needs and checks every file against
519
- the commit's object ids. Credentials come from the same places as for registries (`auth.json`,
520
- the credential helper, `$CI_JOB_TOKEN` in GitLab CI). Git servers keep no release or push times,
521
- so `min-release-age` uses commit dates, which the committer sets; a branch whose newest commit is
522
- too young falls back to an older commit when the server supports partial fetches (`filter`).
121
+ | [Install](docs/guide/install.md) | Every install method, the GitHub Action, updating |
122
+ | [Use](docs/guide/usage.md) | `skills.toml`, agents, dependencies, name conflicts, personal skills (`--global`) |
123
+ | [Commands](docs/guide/commands.md) | Every command, `--json`, exit codes, reviewing updates and lock changes |
124
+ | [Sources](docs/guide/sources.md) | Skills from GitHub, skills.sh and any git repository |
125
+ | [Policy](docs/guide/policy.md) | Allowed sources and policy for every project |
126
+ | [Security](docs/guide/security.md) | What is verified, warnings, `audit`, credentials |
127
+ | [Publishing skills](docs/guide/publishing.md) | Packages, monorepos with `skillcask publish`, `validate` |
128
+ | [macOS app](docs/guide/macos-app.md) | Installing and building the app |
129
+ | [Design](docs/specs/2026-10-19-skillcask-v1.md) | Goals, non-goals and numbered decisions |
523
130
 
524
131
  ## Security
525
132
 
526
- - The lock pins the version, the commit reference, the sha256 of the downloaded archive and
527
- the tree hash of every installed skill. `install` verifies both hashes, so what gets installed
528
- is what was reviewed.
529
- - HTTPS only, verified against the system trust store, so corporate CAs work. Verification
530
- cannot be turned off; `SKILLCASK_CA_FILE` replaces the trust store with a PEM bundle.
531
- - Archives with absolute paths, `..`, devices or symlinks that leave their skill are rejected.
532
- No symlink is ever written from a package. Size and file count are capped (`--max-download`,
533
- `--max-unpacked`, `--max-files`).
534
- - File names must be valid on every OS: Windows-reserved names, `<>:"|?*\`, control characters
535
- and paths that collide by case or Unicode form fail a skill that contains them, and are
536
- skipped outside the selected skills.
537
- - No package code runs, ever. No telemetry.
538
- - `self-check` and the app's "Check for Updates…" send nothing but the request for the tap's cask
539
- file, which carries the skillcask version in its User-Agent (`skillcask/<version>`): no token,
540
- account, project or skill data; GitHub sees your IP address. The app checks
541
- daily only after you say yes. `SKILLCASK_SELF_CHECK_URL` points it at a mirror (HTTPS only).
542
- - `self-update` sends the same request, then, for an installer-script install only, downloads that
543
- release's `skillcask-installer.sh` the same way (`SKILLCASK_SELF_UPDATE_URL` replaces the
544
- download base) and runs it with `/bin/sh`, without your `SKILLCASK_*`, `INSTALLER_*` and
545
- `CARGO_DIST_*` variables. The script checks the archive's sha256 with `sha256sum`, so
546
- `self-update` refuses to run it when `sha256sum` is not on `PATH`.
547
- - `add` and `update` (and `install` when it resolves) warn about characters a reviewer cannot
548
- see in the text files of new content: bidi controls (`U+202A`-`U+202E`, `U+2066`-`U+2069`,
549
- `U+200E`, `U+200F`, `U+061C`), zero-width characters (`U+200B`-`U+200D`, `U+2060`, `U+FEFF`) and
550
- Unicode tags (`U+E0000`-`U+E007F`), as `warning: acme/x: skills/foo/SKILL.md:12: U+202E
551
- RIGHT-TO-LEFT OVERRIDE`, at most five per file. A leading byte order mark and a zero width
552
- joiner inside an emoji are not reported; right-to-left and Indic text can trigger warnings.
553
- Installing from the lock does not warn again.
554
- - The same commands warn about lines that usually mean harm, as `warning: acme/x:
555
- skills/foo/SKILL.md:12: downloads code into a shell`, at most five per file:
556
-
557
- | Warning | Matches (case-insensitive) |
558
- |---|---|
559
- | downloads code into a shell | `curl`, `wget`, `irm`, `iwr`, `Invoke-WebRequest` or `Invoke-RestMethod` piped (`\|`) into `sh`, `bash`, `zsh`, `dash`, `iex`, `Invoke-Expression`, `python`, `perl`, `ruby` or `node`, also after `sudo` |
560
- | decodes base64 and runs it | `base64 -d`, `base64 --decode`, `b64decode` or `FromBase64String` with a pipe into a shell, `eval`, `exec(` or `iex` |
561
- | reads SSH keys | `~/.ssh`, `$HOME/.ssh`, `id_rsa`, `id_ed25519` |
562
- | reads system account files | `/etc/passwd`, `/etc/shadow` |
563
- | tells the agent to ignore its instructions | "ignore (all) previous/prior instructions", "disregard all previous/prior" |
564
-
565
- Skills that teach shell setup trigger some of these legitimately, so they are warnings. With
566
- `deny-patterns = true` under `[policy]` (or enforced in `config.toml`) they, and the invisible
567
- characters above, fail the command with exit 1 and nothing is written.
568
- - `skillcask audit` reviews what is installed now, every skill in `.agents/skills` and the project
569
- skills: the commands its shell code blocks run, the hosts of its URLs, the paths in the home
570
- directory or under system roots, the environment variables it reads and the files an agent could
571
- run. That is read from the text, so it is a hint for review, not a sandbox, and a skill without
572
- findings is not known to be safe. It also reports a locked skill that differs from the lock, and
573
- every risky line and invisible character above, with no limit per file, and exits 1 on any of
574
- them.
575
- - `skillcask audit --advisories` also asks the sources of the locked packages what is published
576
- about them: security advisories from a Composer repository that offers them (Packagist does) and
577
- from a GitHub repository's security advisories, matched against the locked version, and
578
- packages marked abandoned. An entry locked at a commit has no version to match, so only
579
- advisories published after that commit count. A source that cannot be read fails the run;
580
- packages whose source publishes no advisories, and plain git entries, are listed as unchecked.
581
- Plain `audit` stays offline. To warn users of
582
- your skill, publish a GitHub security advisory on its repository (for a Composer package, with
583
- the `composer` ecosystem and the package name, so Packagist lists it too).
584
- - `--sarif` prints a SARIF 2.1.0 log for code scanning, e.g. in GitHub Actions. Scripts a skill
585
- bundles with their own dependencies (`package.json`, `requirements.txt`) are not covered by
586
- `--advisories`; [OSV-Scanner](https://github.com/google/osv-scanner) checks those:
587
-
588
- ```yaml
589
- - uses: GetResponse/skillcask@v0.10.5
590
- with:
591
- args: install --frozen
592
- - run: skillcask audit --advisories --sarif > skills.sarif
593
- env:
594
- GITHUB_TOKEN: ${{ github.token }} # anonymous GitHub API calls are limited to 60 an hour
595
- - uses: github/codeql-action/upload-sarif@v3
596
- if: always()
597
- with:
598
- sarif_file: skills.sarif
599
- # optional, needs osv-scanner on PATH (e.g. google/osv-scanner-action): dependencies of bundled scripts
600
- - run: osv-scanner scan source -r .agents/skills
601
- ```
602
- - Plain git sources pin the commit; the lock's `dist-sha256` hashes the commit's file list
603
- (path, mode, sha256 of the content), so it does not depend on how a server packs objects.
604
- - `min-release-age` for GitHub sources uses times GitHub sets: release publication for tags,
605
- push times from the Activity API for branches. A tag without a release, or a ref GitHub lists no
606
- pushes for, falls back to commit dates, which the committer sets; reviewing what `add`/`update`
607
- change in `skills.lock` is the real check there.
608
- - Credentials come from Composer's `auth.json` / `COMPOSER_AUTH` (`http-basic`, `bearer`,
609
- `gitlab-token`, `gitlab-oauth`), then from git's credential helper, and are never printed.
610
- `skillcask auth set git.example.com` keeps a token in the macOS Keychain, the Windows Credential
611
- Manager or libsecret instead of a plain-text file (the default username `PRIVATE-TOKEN` sends
612
- GitLab's header; `--username oauth2` a Bearer token). `SKILLCASK_GIT_CREDENTIALS=0` turns the
613
- helper off. In GitLab CI use `http-basic` with the
614
- user `gitlab-ci-token` and the password `$CI_JOB_TOKEN`.
615
-
616
- ## Publishing skills
617
-
618
- **One repository per skill:** a `composer.json` with `"type": "ai-agent-skill"` (the
619
- [netresearch convention](https://github.com/netresearch/composer-agent-skill-plugin)) and semver
620
- tags. Packagist or GitLab's Composer registry picks up the tags; skillcask plays no part.
621
-
622
- **Monorepo:** give each `SKILL.md` a `version` in its frontmatter and run
623
-
624
- ```sh
625
- skillcask publish --vendor acme --base-url https://skills.example.com --out public skills/
626
- ```
627
-
628
- This writes `packages.json`, `p2/acme/<name>.json` and deterministic zips under `dist/`. Published
629
- versions are immutable, and re-running on unchanged skills changes no file. Serve the directory
630
- over HTTPS.
631
-
632
- Check the skills before publishing; `validate` exits 1 on any error and warns about invisible
633
- Unicode, as `add` does:
634
-
635
- ```sh
636
- skillcask validate skills/
637
- ```
638
-
639
- It follows the [Agent Skills specification](https://agentskills.io/specification): `name` 1-64
640
- lowercase letters, digits and single hyphens, equal to the directory name; `description` 1-1024
641
- characters; `compatibility` at most 500. Without paths it searches the current directory, skipping
642
- hidden ones; `skillcask validate .agents/skills` checks the skills installed in a project.
643
- `publish` skips a `SKILL.md` without `name` or `version` and names it in a warning.
644
-
645
- To retire a skill, publish a new version with `deprecated: true`, or `deprecated: vendor/name`
646
- naming its replacement, in the frontmatter. It becomes Composer's `abandoned`, and consumers see a
647
- warning on `add`, `update` and `outdated`.
648
-
649
- Hosts that cannot serve `/` inside file names (GitLab's Generic Package Registry) take a single
650
- file instead:
651
-
652
- ```sh
653
- skillcask publish --inline --vendor acme --out composer/ skills/ \
654
- --dist-url 'https://git.example.com/api/v4/projects/7/packages/generic/{vendor}-{name}/{version}/{name}-{version}.zip'
655
- ```
656
-
657
- `--inline` puts every package into `packages.json` and writes no `p2/`. Upload each
658
- `dist/<vendor>/<name>/<version>.zip` to the URL the template gives, and commit `packages.json` to
659
- a repository. A repository `url` with a query string is used as given, so clients can read the
660
- file through the GitLab raw files API
661
- (`.../repository/files/composer%2Fpackages.json/raw?ref=main`) with a `gitlab-token`.
662
-
663
- ## macOS app
664
-
665
- `macos/` holds a SwiftUI app for macOS 14+ over the CLI (D35): open My Skills (the `-g` scope) or a
666
- project folder, see each skill's state, updates and audit findings, read its SKILL.md and diffs,
667
- and run `add` (also `--adopt`), `update`, `remove`, `install` and `doctor --fix`; its Settings
668
- change every key `skillcask -g config` lists. It has no package logic of its own: it runs the
669
- `skillcask` binary, 0.9.4 or newer, and reads its `--json` output.
670
-
671
- Install it with Homebrew, then open it from Applications or with `skillcask app`. The cask depends
672
- on the formula; name both, since Homebrew loads from a third-party tap only what it was asked for
673
- or what `brew trust` lists:
674
-
675
- ```sh
676
- brew install getresponse/tap/skillcask getresponse/tap/skillcask-app
677
- ```
678
-
679
- Every release also has `Skillcask-X.Y.Z-macos-universal.zip`, signed with a Developer ID and
680
- notarized (D50): unzip it into `/Applications`.
681
-
682
- The app tells you about a newer release but installs nothing ([Update](#update)). Its app menu
683
- has Check for Updates…, which runs `skillcask self-check`; it checks daily only after you say yes
684
- once (it asks in the sidebar; Settings › Updates switches it). A newer version gets a card and a
685
- sheet with the Homebrew command to copy, or the release page for a download (D51).
686
-
687
- `macos/bundle.sh` builds a universal `Skillcask.app` that carries its own CLI at
688
- `Contents/Helpers/skillcask`. Run outside a bundle (`swift run` from `macos/`), the app uses the
689
- path set in its Settings, else looks on `PATH`, in `/opt/homebrew/bin`, `/usr/local/bin` and
690
- `~/.cargo/bin`. Building it needs Xcode 26.x with Swift 6.3 or newer, not only the Command Line
691
- Tools. Building, signing, Gatekeeper, tests and renders: [macos/README.md](macos/README.md).
133
+ HTTPS only, hashes checked on every install, archives that escape their skill rejected, and no
134
+ package code run. The threat model and every check are in [Security](docs/guide/security.md);
135
+ report a vulnerability as [SECURITY.md](SECURITY.md) describes.
692
136
 
693
- ## Design
137
+ ## Contributing
694
138
 
695
- See [docs/specs/2026-10-19-skillcask-v1.md](docs/specs/2026-10-19-skillcask-v1.md).
139
+ Read [AGENTS.md](AGENTS.md) for the checks CI runs and the project's invariants, and the
140
+ [design spec](docs/specs/2026-10-19-skillcask-v1.md) before changing how the manifest, lock,
141
+ install or publish behave.
696
142
 
697
143
  ## License
698
144
 
@@ -19,7 +19,7 @@
19
19
  "hasInstallScript": true,
20
20
  "license": "MIT OR Apache-2.0",
21
21
  "name": "skillcask",
22
- "version": "0.10.6"
22
+ "version": "0.11.0"
23
23
  },
24
24
  "node_modules/detect-libc": {
25
25
  "engines": {
@@ -48,5 +48,5 @@
48
48
  }
49
49
  },
50
50
  "requires": true,
51
- "version": "0.10.6"
51
+ "version": "0.11.0"
52
52
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "artifactDownloadUrls": [
3
- "https://github.com/GetResponse/skillcask/releases/download/v0.10.6"
3
+ "https://github.com/GetResponse/skillcask/releases/download/v0.11.0"
4
4
  ],
5
5
  "bin": {
6
6
  "skillcask": "run-skillcask.js"
@@ -104,7 +104,7 @@
104
104
  "zipExt": ".tar.xz"
105
105
  }
106
106
  },
107
- "version": "0.10.6",
107
+ "version": "0.11.0",
108
108
  "volta": {
109
109
  "node": "18.14.1",
110
110
  "npm": "9.5.0"