@camunda8/spm 0.1.1 → 0.3.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 +68 -5
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -15,13 +15,13 @@ ai.json ──resolve──▶ ai.lock ──fetch──▶ ~/.spm/store/<repo>@
|
|
|
15
15
|
|
|
16
16
|
- **`ai.json`** — you author it, commit it. Declares target vendors + skill deps.
|
|
17
17
|
- **`ai.lock`** — generated, commit it. Pins every version selector to an immutable commit SHA → reproducible installs.
|
|
18
|
-
- **Global store** (`~/.spm/store`) — each repo@commit
|
|
19
|
-
- **Vendor projection** — spm copies the store's skills into wherever each vendor loads them from. Nothing spm generates is committed to your repo.
|
|
18
|
+
- **Global store** (`~/.spm/store`) — a **fetch cache only**: each repo@commit is cloned once and shared across all projects. Nothing is *registered* or *materialized* here — it exists purely so repeated installs don't re-clone.
|
|
19
|
+
- **Vendor projection** — spm copies the store's skills into a **project-local** directory wherever each vendor loads them from. Nothing spm generates is committed to your repo, and nothing is written into a user-global vendor location.
|
|
20
20
|
- **Registration** differs per vendor:
|
|
21
21
|
- **Claude** — spm assembles a self-contained plugin marketplace in the **project-local**, gitignored `.spm/claude/` dir and writes a pointer to it into `.claude/settings.local.json` (gitignored by convention). The dir sits outside `.agents/skills/` so Copilot's scanner never picks it up. Declarative, per-project, zero VCS footprint.
|
|
22
22
|
- **Copilot CLI** — spm copies the resolved skills into a **project-local** directory, `.agents/skills/spm-managed-skills/<name>/`, where Copilot CLI auto-discovers them (`.agents/skills/**/SKILL.md`). That directory is added to the project's `.gitignore` (with an explanatory comment) so the materialized skills stay truly local and are never committed. No user-global state, no `copilot` CLI required.
|
|
23
23
|
|
|
24
|
-
On a fresh clone, teammates run `spm install` — it
|
|
24
|
+
On a fresh clone, teammates run `spm install` — it repopulates their own fetch cache and re-materializes the project-local skills from `ai.lock`. Same model as `node_modules`.
|
|
25
25
|
|
|
26
26
|
## ai.json
|
|
27
27
|
|
|
@@ -66,6 +66,19 @@ Version selectors (exactly one per skill):
|
|
|
66
66
|
|
|
67
67
|
`path` (optional) selects a subdirectory — for monorepos holding many skills.
|
|
68
68
|
|
|
69
|
+
To pull in **every** skill under a directory at once (each immediate
|
|
70
|
+
subdirectory that has its own `SKILL.md`), add `--all` instead of naming them
|
|
71
|
+
one by one:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
spm add https://github.com/org/repo --tag v1.0.0 --path skills --all
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Each sub-skill becomes its own `ai.json` entry, keyed by its directory name
|
|
78
|
+
(`--all` cannot be combined with `--name`). This is the one-shot equivalent of
|
|
79
|
+
the per-skill `spm add … --path <sub> --name <sub>` commands spm suggests when
|
|
80
|
+
you point `--path` at a container of skills.
|
|
81
|
+
|
|
69
82
|
### Repo URLs (HTTPS & SSH)
|
|
70
83
|
|
|
71
84
|
`git` accepts any URL the system `git` understands:
|
|
@@ -139,18 +152,68 @@ make install PREFIX=~/.local # or a custom prefix
|
|
|
139
152
|
```bash
|
|
140
153
|
spm init [--target claude|copilot ...] # scaffold ai.json (repeatable / comma-separated)
|
|
141
154
|
spm add <git> (--tag|--branch|--commit <v>) \ # add + install a skill
|
|
142
|
-
[--path <subdir>] [--name <local-name>]
|
|
155
|
+
[--path <subdir>] [--name <local-name>] [--all] # --all: add every skill under --path
|
|
143
156
|
spm remove <name> # drop a skill
|
|
144
157
|
spm update [name] # re-resolve branches/tags to latest
|
|
145
158
|
spm install # rebuild from ai.lock (after clone)
|
|
146
159
|
spm list # show skills + pinned commits
|
|
160
|
+
spm status # check skills are materialized in this checkout
|
|
147
161
|
spm clean # remove generated vendor config
|
|
148
162
|
```
|
|
149
163
|
|
|
164
|
+
## Worktrees & fresh clones
|
|
165
|
+
|
|
166
|
+
spm materializes skills into **gitignored** project-local dirs (`.spm/claude/`,
|
|
167
|
+
`.agents/skills/spm-managed-skills/`). Git **worktrees** have their own working
|
|
168
|
+
tree and don't share those untracked files, so — exactly like `node_modules` —
|
|
169
|
+
**each checkout needs its own `spm install`**:
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
git worktree add ../feature -b feature
|
|
173
|
+
cd ../feature && spm install # materialize this worktree's skills
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Skipping this is the usual reason an agent doesn't see a declared skill in a new
|
|
177
|
+
worktree or a fresh clone. `spm status` tells you at a glance and **exits
|
|
178
|
+
non-zero** when anything is missing, so it works in scripts too:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
spm status
|
|
182
|
+
# [claude] 0/1 installed .../.spm/claude/plugin/skills
|
|
183
|
+
# reviewer MISSING
|
|
184
|
+
# error: some declared skills are not materialized in this checkout — run `spm install` here
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
To install automatically on every branch checkout and new worktree, add a
|
|
188
|
+
`post-checkout` git hook (worktrees share the repo's `.git/hooks`):
|
|
189
|
+
|
|
190
|
+
```sh
|
|
191
|
+
# .git/hooks/post-checkout — then: chmod +x .git/hooks/post-checkout
|
|
192
|
+
#!/bin/sh
|
|
193
|
+
# Re-materialize spm skills so Claude/Copilot always see the declared set.
|
|
194
|
+
[ -f ai.lock ] && command -v spm >/dev/null 2>&1 && spm install >/dev/null 2>&1
|
|
195
|
+
exit 0
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
> **Claude note:** `spm install` writes the *absolute* path of the current
|
|
199
|
+
> checkout's `.spm/claude/` into that checkout's `.claude/settings.local.json`.
|
|
200
|
+
> Since that file is gitignored, a new worktree either has no registration at all
|
|
201
|
+
> or — if it was copied over — one still pointing at the checkout it came from.
|
|
202
|
+
> Either way, run `spm install` inside the worktree and start (or
|
|
203
|
+
> `/reload-plugins` in) the Claude session from that same worktree; discovery is
|
|
204
|
+
> snapshotted at session start. `spm status` reports a stale pointer explicitly:
|
|
205
|
+
>
|
|
206
|
+
> ```
|
|
207
|
+
> ! .claude/settings.local.json marketplace points at /repo/.spm/claude, not this checkout (/repo-feature/.spm/claude)
|
|
208
|
+
> ```
|
|
209
|
+
|
|
210
|
+
To see what each harness actually loaded: `claude plugin list` /
|
|
211
|
+
`claude plugin marketplace list` for Claude; `copilot skill list` for Copilot.
|
|
212
|
+
|
|
150
213
|
## Design notes
|
|
151
214
|
|
|
152
215
|
- **Cross-OS**: shells out to the system `git` (no libgit2 build deps); no symlinks; all paths via `std::path`. Runs on Linux, macOS, Windows.
|
|
153
|
-
- **`SPM_HOME`** overrides the store
|
|
216
|
+
- **`SPM_HOME`** overrides the store root (default `~/.spm`, holding only the fetch cache) — used by tests. Vendor output is always project-local and is not affected by `SPM_HOME`.
|
|
154
217
|
- **Vendor adapters**: adding a target means implementing one `Vendor` trait (`src/vendor/`). `claude` assembles a plugin-marketplace layout (`marketplace.json` → `plugin.json` → `skills/<name>/SKILL.md`) into the gitignored project-local `.spm/claude/` and points to it; `copilot` copies skills into the gitignored project-local `.agents/skills/spm-managed-skills/`. Both keep their materialized files out of VCS via the shared `src/gitignore.rs` helper.
|
|
155
218
|
|
|
156
219
|
## Development
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camunda8/spm",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Skill package manager (spm): declare AI skills in ai.json and materialize them for Claude/Copilot.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://github.com/camunda/spm-cli#readme",
|
|
@@ -33,10 +33,10 @@
|
|
|
33
33
|
"node": ">=18"
|
|
34
34
|
},
|
|
35
35
|
"optionalDependencies": {
|
|
36
|
-
"@camunda8/spm-linux-x64": "0.
|
|
37
|
-
"@camunda8/spm-linux-arm64": "0.
|
|
38
|
-
"@camunda8/spm-darwin-x64": "0.
|
|
39
|
-
"@camunda8/spm-darwin-arm64": "0.
|
|
40
|
-
"@camunda8/spm-win32-x64": "0.
|
|
36
|
+
"@camunda8/spm-linux-x64": "0.3.0",
|
|
37
|
+
"@camunda8/spm-linux-arm64": "0.3.0",
|
|
38
|
+
"@camunda8/spm-darwin-x64": "0.3.0",
|
|
39
|
+
"@camunda8/spm-darwin-arm64": "0.3.0",
|
|
40
|
+
"@camunda8/spm-win32-x64": "0.3.0"
|
|
41
41
|
}
|
|
42
42
|
}
|