skillcask 0.1.0 → 0.2.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
@@ -8,31 +8,63 @@ version constraints and commits a lock with content hashes. In CI it does frozen
8
8
  fail on drift, and it links every skill into each agent's skill directory. It ships as a single
9
9
  static binary with no runtime, so it works in a repository in any language.
10
10
 
11
- Skills are distributed through the Composer repository protocol. Packagist serves public skills;
12
- GitLab's Composer registry, Satis, Private Packagist or the static repository built by
13
- `skillcask publish` serve private ones. skillcask does not need PHP or Composer.
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.
14
16
 
15
17
  ## Install
16
18
 
19
+ **macOS, Linux**
20
+
21
+ ```sh
22
+ brew install puniserv/tap/skillcask
23
+ # or, without Homebrew:
24
+ curl --proto '=https' --tlsv1.2 -LsSf https://github.com/puniserv/skillcask/releases/latest/download/skillcask-installer.sh | sh
25
+ ```
26
+
27
+ **Windows (PowerShell)**
28
+
29
+ ```powershell
30
+ powershell -ExecutionPolicy Bypass -c "irm https://github.com/puniserv/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
+ **npm, bun**
37
+
17
38
  ```sh
18
- brew install puniserv/tap/skillcask # macOS, Linux
19
- npm install -g skillcask # or: bun add -g skillcask
20
- npx skillcask install --frozen # or: bunx skillcask …, no global install
21
- cargo install skillcask
39
+ npm install -g skillcask # global
40
+ bun add -g skillcask # global, bun
41
+ npx skillcask install --frozen
42
+ bunx skillcask install --frozen
22
43
  ```
23
44
 
24
45
  The npm package is a thin wrapper that downloads the release binary for your platform from
25
- GitHub. It does not check a checksum itself; where that matters, install the binary directly
26
- and verify it.
46
+ GitHub. It does not check a checksum itself; where that matters, use Homebrew or a release
47
+ archive and verify it.
48
+
49
+ **Cargo**
50
+
51
+ ```sh
52
+ cargo install --locked skillcask
53
+ ```
27
54
 
28
- Prebuilt binaries for macOS, Linux and Windows are on the
55
+ **Release archives** for macOS, Linux and Windows are on the
29
56
  [releases page](https://github.com/puniserv/skillcask/releases), with sha256 checksums and GitHub
30
- build provenance attestations (`gh attestation verify <file> -R puniserv/skillcask`).
57
+ build provenance attestations:
58
+
59
+ ```sh
60
+ gh attestation verify skillcask-x86_64-unknown-linux-gnu.tar.xz -R puniserv/skillcask
61
+ ```
31
62
 
32
63
  ## Use
33
64
 
34
65
  ```sh
35
66
  skillcask add netresearch/agent-jira-skill # resolve, write skills.toml + skills.lock, install
67
+ skillcask add github:mattpocock/skills/tdd # one skill from a GitHub repository
36
68
  skillcask install --frozen # CI: install exactly the lock or exit non-zero
37
69
  skillcask status # manifest vs lock vs installed files
38
70
  ```
@@ -43,6 +75,7 @@ skillcask status # manifest vs lock vs installed fil
43
75
  skills.toml # manifest, commit it
44
76
  skills.lock # lock, commit it
45
77
  .agents/skills/<name>/ # installed skill (gitignored)
78
+ .agents/skills/.skillcask-installed # what this machine installed (gitignored)
46
79
  .claude/skills/<name> -> ../../.agents/skills/<name>
47
80
  .junie/skills/<name> -> ../../.agents/skills/<name>
48
81
  .gitignore # managed block
@@ -52,7 +85,9 @@ Project skills live in `.skills/<name>/SKILL.md` (`[agents] local`). skillcask l
52
85
  into the store (`.agents/skills/<name> -> ../../.skills/<name>`) and from there into every agent
53
86
  directory. These links are committed, so they work in every clone. A directory written by hand
54
87
  straight into `.agents/skills/` is linked the same way. A project skill with the same name as a
55
- locked one is an error.
88
+ locked one is an error. When a skill with the same name exists in your home (`~/.claude/skills`,
89
+ `~/.agents/skills`, …), `install` and `doctor` print a warning: Claude Code runs the personal one,
90
+ Codex lists both.
56
91
 
57
92
  ### skills.toml
58
93
 
@@ -65,6 +100,8 @@ acme = { type = "composer", url = "https://git.example.com/api/v4/group/42/-/pac
65
100
  "netresearch/agent-jira-skill" = "^3.34"
66
101
  "acme/agents-md" = { version = "^1.0", repository = "acme" }
67
102
  "acme/review" = { version = "1.4.2", repository = "acme", skills = ["review"] }
103
+ "mattpocock/skills" = { github = true, version = "^1.3", skills = ["tdd", "code-review"], rename = { code-review = "mp-code-review" } }
104
+ "anthropics/skills" = { github = true, skills = ["pdf"] } # default branch
68
105
 
69
106
  [agents]
70
107
  targets = [".claude/skills", ".junie/skills"]
@@ -80,12 +117,48 @@ Constraints follow Composer semantics: `^0.3` means `>=0.3.0 <0.4.0`, `~1.2` mea
80
117
  `>=1.2 <2.0`, and pre-releases are only selected when the constraint names a stability
81
118
  (`^1.0@beta`).
82
119
 
120
+ ### Name conflicts
121
+
122
+ Skills have no namespaces: an agent knows a skill by its name. Two skills with the same name in
123
+ one project are an error. Install one of them under another name with `rename`:
124
+
125
+ ```toml
126
+ "mattpocock/skills" = { github = true, rename = { code-review = "mp-code-review" } }
127
+ ```
128
+
129
+ skillcask then installs `.agents/skills/mp-code-review` and changes the `name:` line in its
130
+ `SKILL.md`; the lock records the original name and the hash of the renamed copy. Nothing else in
131
+ the skill changes, so text that mentions the old name (`/code-review`) stays as it is.
132
+ `add`, `install` and `update` offer the rename when they hit a conflict in a terminal.
133
+
134
+ ### Personal skills (`--global`)
135
+
136
+ `skillcask --global` (`-g`) manages skills for your user instead of a project, with the same
137
+ manifest, lock and verification:
138
+
139
+ ```sh
140
+ skillcask -g add github:mattpocock/skills/grill-me
141
+ skillcask -g install --frozen # e.g. from a dotfiles repository
142
+ ```
143
+
144
+ - `skills.toml`, `skills.lock` and an optional `auth.json` live in `~/.config/skillcask`
145
+ (`$XDG_CONFIG_HOME/skillcask`; `SKILLCASK_HOME` overrides both). Keep them in your dotfiles.
146
+ - Skills go to `~/.agents/skills` (read by Codex), with links in `~/.claude/skills` and
147
+ `~/.junie/skills` (`[agents] targets`, relative to home). Links are absolute, so a symlinked
148
+ `~/.claude` works. `[agents] local` does not apply.
149
+ - Personal skills you wrote by hand stay where they are and are not linked anywhere.
150
+ - The list of managed paths is `~/.agents/skills/.skillcask-installed`, local to the machine;
151
+ nothing touches git.
152
+
83
153
  ### Commands
84
154
 
155
+ Every command except `publish` takes `-g, --global`.
156
+
85
157
  | Command | |
86
158
  |---|---|
87
159
  | `init` | Create `skills.toml`. |
88
160
  | `add <vendor/name>[@constraint] [--repository r]` | Resolve, lock and install. |
161
+ | `add github:<owner/repo>[/skill][@version-or-ref]` | The same from a GitHub repository, see below. |
89
162
  | `remove <vendor/name>…` | Drop from manifest and lock; delete files, links and gitignore lines. |
90
163
  | `install [--frozen]` | Install the lock. `--frozen` (implied by `CI`) fails when the lock is out of date. |
91
164
  | `update [vendor/name…]` | Re-resolve within constraints. |
@@ -93,12 +166,55 @@ Constraints follow Composer semantics: `^0.3` means `>=0.3.0 <0.4.0`, `~1.2` mea
93
166
  | `status` | Exit 1 when manifest, lock or installed files disagree. |
94
167
  | `doctor [--fix]` | Broken or committed links, stale gitignore block, modified skills. |
95
168
  | `search <query>` | Packagist (`type=ai-agent-skill`) and listed private packages. |
96
- | `publish --vendor v --base-url URL --out DIR [paths…]` | Build a static Composer repository from a monorepo. |
169
+ | `publish --vendor v --base-url URL --out DIR [--inline] [--dist-url TPL] [paths…]` | Build a static Composer repository from a monorepo. |
97
170
  | `<other>` | Runs `skillcask-<other>` from `PATH`, like git and cargo plugins. |
98
171
 
99
172
  Exit codes: 0 ok, 1 manifest/lock/status problems, 2 authentication, 3 network, 4 hash mismatch,
100
173
  5 IO or archive error.
101
174
 
175
+ ### Skills from GitHub and skills.sh
176
+
177
+ [skills.sh](https://skills.sh) lists skills as `owner/repo/skill`, for example
178
+ `mattpocock/skills/grill-me`. Put `github:` in front and add it:
179
+
180
+ ```sh
181
+ skillcask add github:mattpocock/skills/grill-me # one skill
182
+ skillcask add github:mattpocock/skills/tdd # a second one from the same repository
183
+ skillcask add github:anthropics/skills # every skill in the repository
184
+ ```
185
+
186
+ All skills of one repository share one entry in `skills.toml`:
187
+
188
+ ```toml
189
+ "mattpocock/skills" = { github = true, version = "^1.3", skills = ["grill-me", "tdd"] }
190
+ ```
191
+
192
+ Which version you get:
193
+
194
+ - **Repository with version tags** (`v1.3.1`): `add` writes `version = "^<major.minor>"`, like
195
+ for Composer packages, and `update` moves within it. The release time of a tag is its commit
196
+ date.
197
+ - **Repository without tags**: the entry follows the default branch; `ref = "main"` names a
198
+ branch, tag or commit instead. The lock pins the commit sha, so `install` keeps installing that
199
+ commit until you run `update`.
200
+ - `@` picks explicitly: `github:owner/repo@^2.0` (version tags), `github:owner/repo@main` or
201
+ `@<commit sha>` (ref).
202
+ - With `policy.allow-ranges = false` a branch counts as a range: `add` writes the full commit sha
203
+ as `ref`, and a hand-written branch name is rejected.
204
+
205
+ Skills are found by their `SKILL.md` anywhere in the repository, except inside another skill.
206
+ The install name is the frontmatter `name`; when that is not a valid name (`Jira Automation`), the
207
+ directory name is used. `skills = [...]` takes these names.
208
+
209
+ GitHub allows 60 anonymous API requests per hour. `add`, `update` and `outdated` use a few per
210
+ entry; `install` from the lock uses none, it downloads the pinned archive. Set `GITHUB_TOKEN`
211
+ (GitHub Actions has one) or Composer's `"github-oauth": {"github.com": "<token>"}` in `auth.json`
212
+ for a higher limit and for private repositories. `SKILLCASK_GITHUB_API` points at GitHub
213
+ Enterprise (`https://ghe.example.com/api/v3`).
214
+
215
+ skills.sh itself is not queried: its API needs a Vercel token. Search on the website, then add
216
+ what you picked.
217
+
102
218
  ## Security
103
219
 
104
220
  - The lock pins the version, the commit reference, the sha256 of the downloaded archive and
@@ -109,7 +225,13 @@ Exit codes: 0 ok, 1 manifest/lock/status problems, 2 authentication, 3 network,
109
225
  - Archives with absolute paths, `..`, devices or symlinks that leave their skill are rejected.
110
226
  No symlink is ever written from a package. Size and file count are capped (`--max-download`,
111
227
  `--max-unpacked`, `--max-files`).
228
+ - File names must be valid on every OS: Windows-reserved names, `<>:"|?*\`, control characters
229
+ and paths that collide by case or Unicode form fail a skill that contains them, and are
230
+ skipped outside the selected skills.
112
231
  - No package code runs, ever. No telemetry.
232
+ - `min-release-age` for GitHub sources reads commit dates, which the committer sets. A
233
+ backdated commit passes the cooldown; reviewing what `add`/`update` change in `skills.lock` is
234
+ the real check there.
113
235
  - Credentials come from Composer's `auth.json` / `COMPOSER_AUTH` (`http-basic`, `bearer`,
114
236
  `gitlab-token`, `gitlab-oauth`) and are never printed. In GitLab CI use `http-basic` with the
115
237
  user `gitlab-ci-token` and the password `$CI_JOB_TOKEN`.
@@ -130,9 +252,23 @@ This writes `packages.json`, `p2/acme/<name>.json` and deterministic zips under
130
252
  versions are immutable, and re-running on unchanged skills changes no file. Serve the directory
131
253
  over HTTPS.
132
254
 
255
+ Hosts that cannot serve `/` inside file names (GitLab's Generic Package Registry) take a single
256
+ file instead:
257
+
258
+ ```sh
259
+ skillcask publish --inline --vendor acme --out composer/ skills/ \
260
+ --dist-url 'https://git.example.com/api/v4/projects/7/packages/generic/{vendor}-{name}/{version}/{name}-{version}.zip'
261
+ ```
262
+
263
+ `--inline` puts every package into `packages.json` and writes no `p2/`. Upload each
264
+ `dist/<vendor>/<name>/<version>.zip` to the URL the template gives, and commit `packages.json` to
265
+ a repository. A repository `url` with a query string is used as given, so clients can read the
266
+ file through the GitLab raw files API
267
+ (`.../repository/files/composer%2Fpackages.json/raw?ref=main`) with a `gitlab-token`.
268
+
133
269
  ## Design
134
270
 
135
- See [docs/spec.md](docs/spec.md).
271
+ See [docs/specs/2026-10-19-skillcask-v1.md](docs/specs/2026-10-19-skillcask-v1.md).
136
272
 
137
273
  ## License
138
274
 
@@ -19,7 +19,7 @@
19
19
  "hasInstallScript": true,
20
20
  "license": "MIT OR Apache-2.0",
21
21
  "name": "skillcask",
22
- "version": "0.1.0"
22
+ "version": "0.2.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.1.0"
51
+ "version": "0.2.0"
52
52
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "artifactDownloadUrls": [
3
- "https://github.com/puniserv/skillcask/releases/download/v0.1.0"
3
+ "https://github.com/puniserv/skillcask/releases/download/v0.2.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.1.0",
107
+ "version": "0.2.0",
108
108
  "volta": {
109
109
  "node": "18.14.1",
110
110
  "npm": "9.5.0"