@ssheleg/make-skill 0.24.0 → 0.25.1
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/CHANGELOG.md +60 -0
- package/bin/make-skill.js +79 -11
- package/cursor/rules/make-skill.mdc +4 -1
- package/package.json +2 -2
- package/plugins/make-skill/.claude-plugin/plugin.json +1 -1
- package/plugins/make-skill/skills/make-skill/SKILL.md +1 -1
- package/plugins/make-skill/skills/make-skill/references/distribution.md +49 -3
- package/plugins/make-skill/skills/make-skill/references/host-capabilities.md +13 -2
- package/plugins/make-skill/skills/make-skill/references/retrofit.md +5 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,65 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v0.25.1 — the rule keeps its default, and the family's exception is written down
|
|
4
|
+
|
|
5
|
+
- **The same-name command rule now carries its recorded exception** (operator
|
|
6
|
+
decision, 2026-08-30: no renames anywhere in the family). The default in
|
|
7
|
+
`references/host-capabilities.md` is unchanged — never name a command after a
|
|
8
|
+
skill in the same plugin — and the one recorded exception is enumerated beside
|
|
9
|
+
it: the ssheleg family ships same-named commands deliberately (`task-pipeline`,
|
|
10
|
+
`project-audit`, `seo-aeo-audit`, `sheleg-design`, `agent-sync`, and
|
|
11
|
+
`super-ux`'s `vision` / `ux-foundation` / `ux-flows` / `ux-audit`), with the
|
|
12
|
+
cost stated rather than waived: the skill wins the trigger, and each command
|
|
13
|
+
stays an always-on token cost that may be unreachable in the picker.
|
|
14
|
+
`retrofit.md` item 14 and the Cursor rule teach the auditor the same path, so
|
|
15
|
+
family audits report ASY-02 / SEO-02 / TPA-02 / SHD-06 / SUX-03 as
|
|
16
|
+
*deliberate, recorded — no change needed* instead of open gaps. A collision
|
|
17
|
+
NOT on a dated, recorded exception list is still the gap the rule names.
|
|
18
|
+
- **A hand-typed eval count drifted, exactly as this skill's own gotcha predicts**
|
|
19
|
+
(MSK-02). `test/evals/RESULTS.md` said "20 queries" and `SKILL-CARD.md` said
|
|
20
|
+
"20 trigger queries" over a `triggers.json` holding 22. Both corrected — and
|
|
21
|
+
both statements are now compared, not typed: `test/evals_validate.py` parses
|
|
22
|
+
RESULTS.md's stated counts against the artifacts and refuses a claim-free
|
|
23
|
+
RESULTS.md rather than passing vacuously, with negative self-tests planting an
|
|
24
|
+
off-by-one count and a claim-free file; `test/validate.py`'s counted-claims
|
|
25
|
+
sweep gains the `N trigger queries` / `N behavioural scenarios` patterns for
|
|
26
|
+
every other document. Both guards were watched failing against the real
|
|
27
|
+
20-vs-22 defect before the numbers were corrected.
|
|
28
|
+
- The `SKILL.md` body is untouched on purpose: at ~4742/5000 tokens it has 8
|
|
29
|
+
tokens of headroom, so the whole amendment lives in the references.
|
|
30
|
+
|
|
31
|
+
## v0.25.0 — the installer refuses the shadow it documents, loudly
|
|
32
|
+
|
|
33
|
+
- **The family audit of 2026-08-29 reproduced the shadow live:** a bare
|
|
34
|
+
`npx @ssheleg/telegram-dev` created three plain copies in `~/.claude/skills/` while the
|
|
35
|
+
telegram-dev plugin was enabled. Every member's bin installer had the same hole, and every
|
|
36
|
+
member's CI tested only a fresh `HOME`, so the plugin-present case had never run anywhere.
|
|
37
|
+
This is the standards repository, so the canon lands here first and its own installer is
|
|
38
|
+
the reference implementation.
|
|
39
|
+
- **This repository's own check was the fail-open class, and the new canon names it.** Both
|
|
40
|
+
installers detected the plugin by the `~/.claude/plugins/marketplaces/make-skill`
|
|
41
|
+
directory alone — which under-reports (a `directory`-sourced marketplace has no dir
|
|
42
|
+
there; plugin names differ from marketplace names) — and the refusal exited **0**, which
|
|
43
|
+
reads as success to every script above it. `distribution.md` gains "The installer must
|
|
44
|
+
refuse the shadow it documents": detect from the TARGET home's
|
|
45
|
+
`installed_plugins.json` (keys are `<name>@<marketplace>`), refuse with the remedy and a
|
|
46
|
+
non-zero exit, offer `--force` as the recorded deliberate choice, fail open on a missing
|
|
47
|
+
or corrupt JSON, and gate only the `~/.claude` write — no other agent has plugins.
|
|
48
|
+
- **`bin/make-skill.js` and `install.sh` implement it:** exit `3` on refusal, the remedy
|
|
49
|
+
names the spec read from the JSON (`claude plugin update make-skill@<marketplace>`) plus
|
|
50
|
+
the family launcher, `--force` overrides, absence/corruption of the JSON installs as
|
|
51
|
+
before, and the marketplaces-dir read is kept as the fallback signal. The last line of a
|
|
52
|
+
successful install now says how the next version arrives (the v0.24.0 canon, applied to
|
|
53
|
+
this repo's own CLI).
|
|
54
|
+
- **`test/installer_test.js` joins `npm test` and CI** — 11 cases against throwaway HOMEs:
|
|
55
|
+
fresh / rerun-skip / `--force` / unknown-arg, plugin-present refusal (exit code, remedy
|
|
56
|
+
text, nothing written), a differently-named marketplace in the spec, corrupt JSON failing
|
|
57
|
+
open, no false refusal on other plugins or a `make-skill-extra` prefix-collider, the
|
|
58
|
+
marketplaces-dir fallback, and the same matrix for `install.sh`. Watched failing before
|
|
59
|
+
trusted: **6 of 11 red** against the pre-fix installers (`git stash` the two, run, pop).
|
|
60
|
+
The suite follows the house residue rule — a failing case keeps its HOME, and the run
|
|
61
|
+
ends by saying what it left.
|
|
62
|
+
|
|
3
63
|
## v0.24.0 — the plugin surface as it is now, and how updates reach a machine
|
|
4
64
|
|
|
5
65
|
- **Four plugin features that landed after this skill last read the docs.** Re-read
|
package/bin/make-skill.js
CHANGED
|
@@ -18,6 +18,44 @@ const os = require('os');
|
|
|
18
18
|
const ROOT = path.resolve(__dirname, '..');
|
|
19
19
|
const REPO = 'ssheleg/make-skill';
|
|
20
20
|
|
|
21
|
+
// Exit codes are the contract: 0 installed or skipped, 1 corrupted package,
|
|
22
|
+
// 2 usage error, 3 refused — the plugin channel owns this agent (--force overrides).
|
|
23
|
+
const EXIT_PLUGIN_PRESENT = 3;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* The plugin spec (`<name>@<marketplace>`) installed for `name` in this home,
|
|
27
|
+
* or null.
|
|
28
|
+
*
|
|
29
|
+
* `installed_plugins.json` is the record of what is actually installed. The
|
|
30
|
+
* `plugins/marketplaces/<name>` directory — the only thing this installer read
|
|
31
|
+
* until v0.25.0 — under-reports: a marketplace added from a local `directory`
|
|
32
|
+
* source has no dir there at all, and plugin names differ from marketplace
|
|
33
|
+
* names, so a check keyed on it stays green while the shadow lands. Absence
|
|
34
|
+
* and corruption both read as "no plugin": the fresh HOME is the common case,
|
|
35
|
+
* and an installer that crashes on a parse error refuses the machines that
|
|
36
|
+
* need it most.
|
|
37
|
+
*/
|
|
38
|
+
function installedPluginSpec(home, name) {
|
|
39
|
+
try {
|
|
40
|
+
const raw = fs.readFileSync(
|
|
41
|
+
path.join(home, '.claude', 'plugins', 'installed_plugins.json'), 'utf8');
|
|
42
|
+
const parsed = JSON.parse(raw);
|
|
43
|
+
const plugins =
|
|
44
|
+
parsed && typeof parsed === 'object' &&
|
|
45
|
+
parsed.plugins && typeof parsed.plugins === 'object'
|
|
46
|
+
? parsed.plugins
|
|
47
|
+
: parsed;
|
|
48
|
+
if (!plugins || typeof plugins !== 'object') return null;
|
|
49
|
+
for (const spec of Object.keys(plugins)) {
|
|
50
|
+
if (spec === name) return `${name}@${name}`;
|
|
51
|
+
if (spec.startsWith(name + '@')) return spec;
|
|
52
|
+
}
|
|
53
|
+
} catch {
|
|
54
|
+
// missing or corrupt = no plugin — fail open on absence, never crash
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
|
|
21
59
|
function version() {
|
|
22
60
|
try {
|
|
23
61
|
return require(path.join(ROOT, 'package.json')).version;
|
|
@@ -35,6 +73,12 @@ Usage:
|
|
|
35
73
|
npx @ssheleg/make-skill --version
|
|
36
74
|
npx @ssheleg/make-skill --help
|
|
37
75
|
|
|
76
|
+
Exit codes:
|
|
77
|
+
0 installed or skipped 2 usage error
|
|
78
|
+
1 corrupted package 3 refused: the make-skill PLUGIN is installed in
|
|
79
|
+
this home — a plain copy would shadow it (pass
|
|
80
|
+
--force to write it anyway)
|
|
81
|
+
|
|
38
82
|
Other install paths:
|
|
39
83
|
Claude Code plugin: /plugin marketplace add ${REPO}
|
|
40
84
|
/plugin install make-skill@make-skill
|
|
@@ -123,24 +167,39 @@ function main(argv) {
|
|
|
123
167
|
|
|
124
168
|
// One channel per agent. A plain ~/.claude/skills/make-skill beside an
|
|
125
169
|
// installed plugin is two listings of the same skill, and the stale copy wins
|
|
126
|
-
// — the exact
|
|
170
|
+
// — the exact shadow this canon forbids. Refuse rather than create it, and
|
|
171
|
+
// refuse LOUDLY: until v0.25.0 this check keyed on the marketplaces/ dir
|
|
172
|
+
// alone and exited 0 — the fail-open class. A directory-sourced marketplace
|
|
173
|
+
// has no dir there, plugin names differ from marketplace names, and a refusal
|
|
174
|
+
// that exits 0 reads as success to every script above it. Reproduced live
|
|
175
|
+
// 2026-08-29: a bare `npx @ssheleg/telegram-dev` shipped three shadows past
|
|
176
|
+
// exactly this hole while the plugin was enabled.
|
|
177
|
+
const spec = installedPluginSpec(home, 'make-skill');
|
|
127
178
|
const marketplace = path.join(home, '.claude', 'plugins', 'marketplaces', 'make-skill');
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
`
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
'
|
|
179
|
+
const viaMarketplaceDir = !spec && fs.existsSync(marketplace);
|
|
180
|
+
if ((spec || viaMarketplaceDir) && !force) {
|
|
181
|
+
const found = spec
|
|
182
|
+
? `installed as the Claude Code plugin ${spec}\n` +
|
|
183
|
+
' (declared in ~/.claude/plugins/installed_plugins.json)'
|
|
184
|
+
: `registered as a Claude Code marketplace\n (${marketplace})`;
|
|
185
|
+
console.error(
|
|
186
|
+
`refused: make-skill is already ${found}.\n` +
|
|
187
|
+
' A plain copy in ~/.claude/skills/make-skill would shadow the plugin\n' +
|
|
188
|
+
' and serve this frozen version forever. Update the plugin channel\n' +
|
|
189
|
+
' instead:\n' +
|
|
190
|
+
' claude plugin marketplace update make-skill\n' +
|
|
191
|
+
` claude plugin update ${spec || 'make-skill@make-skill'}\n` +
|
|
192
|
+
' Family launcher (updates every member, prunes shadow copies):\n' +
|
|
193
|
+
' npx --yes sshlg-skills@latest update\n' +
|
|
194
|
+
' Pass --force to write the plain copy anyway — a deliberate choice\n' +
|
|
195
|
+
' to run two channels, where the stale one wins.'
|
|
137
196
|
);
|
|
138
197
|
// Offered here too. The skill IS present on this machine — as the plugin —
|
|
139
198
|
// so the routing block is exactly as wanted as on the install path. Two
|
|
140
199
|
// doors into one install that behave differently is how a feature comes to
|
|
141
200
|
// exist for half its users.
|
|
142
201
|
offerRouters();
|
|
143
|
-
return
|
|
202
|
+
return EXIT_PLUGIN_PRESENT;
|
|
144
203
|
}
|
|
145
204
|
|
|
146
205
|
installOne(
|
|
@@ -151,6 +210,15 @@ function main(argv) {
|
|
|
151
210
|
force
|
|
152
211
|
);
|
|
153
212
|
offerRouters();
|
|
213
|
+
// The last line says how the next version arrives — "Installed" is not a
|
|
214
|
+
// complete sentence. Auto-update is off on purpose: this member composes
|
|
215
|
+
// with its family, and per-marketplace autoUpdate moves each member on its
|
|
216
|
+
// own clock, into combinations nobody tested together.
|
|
217
|
+
console.log(
|
|
218
|
+
'\nUpdates: rerun `npx @ssheleg/make-skill@latest --force`, or refresh the\n' +
|
|
219
|
+
'whole family with `npx --yes sshlg-skills@latest update` (every channel,\n' +
|
|
220
|
+
'and it prunes plain copies that would shadow a plugin).'
|
|
221
|
+
);
|
|
154
222
|
return 0;
|
|
155
223
|
}
|
|
156
224
|
|
|
@@ -140,7 +140,10 @@ through a quoted `"${CLAUDE_PLUGIN_ROOT}/…"` with a `timeout`; hook scripts ex
|
|
|
140
140
|
0 silently when the event is not theirs and when the interpreter is missing;
|
|
141
141
|
`PreToolUse` blocks (exit 2 sends stderr to the model), `PostToolUse` advises via
|
|
142
142
|
`systemMessage`; plugin agents may not carry `hooks`, `mcpServers` or
|
|
143
|
-
`permissionMode`; a command is never named after a skill in the same plugin
|
|
143
|
+
`permissionMode`; a command is never named after a skill in the same plugin —
|
|
144
|
+
unless the collision is on the recorded, dated exception list in the skill's
|
|
145
|
+
`references/host-capabilities.md` (the ssheleg family, operator decision
|
|
146
|
+
2026-08-30), which an audit reports as deliberate and recorded, not as a gap.
|
|
144
147
|
|
|
145
148
|
## Hard rules
|
|
146
149
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ssheleg/make-skill",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.1",
|
|
4
4
|
"description": "Create, retrofit, audit, and ship agent skills & Claude Code plugins the proven ssheleg way — conformance to the Agent Skills open standard AND Anthropic's platform rules (front-matter limits, disclosure budgets, per-surface runtime limits, the Skills API, evals) plus the Claude Code plugin reference (manifest schemas, component layout, claude plugin validate --strict), marketplace repo layout, version sync, validator + CI, multi-channel distribution (plugin, vercel skills CLI, npx, Cursor), npm gotchas, the review checklist for third-party skills, and MCP / A2A rules for protocol-connected skills. This package is the installer CLI.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"skill",
|
|
@@ -45,6 +45,6 @@
|
|
|
45
45
|
"node": ">=16"
|
|
46
46
|
},
|
|
47
47
|
"scripts": {
|
|
48
|
-
"test": "python3 test/validate.py && python3 test/plant_guard_test.py && python3 test/checker_parity_test.py && python3 test/residue_test.py"
|
|
48
|
+
"test": "python3 test/validate.py && python3 test/plant_guard_test.py && python3 test/checker_parity_test.py && python3 test/residue_test.py && node test/installer_test.js"
|
|
49
49
|
}
|
|
50
50
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "make-skill",
|
|
4
4
|
"displayName": "Make Skill",
|
|
5
5
|
"description": "Create, retrofit, audit, and ship agent skills & Claude Code plugins the proven ssheleg way: conformance to the Agent Skills open standard, Anthropic's platform rules (surfaces, Skills API, evals) and the Claude Code plugin reference, marketplace repo layout, version sync, validator + CI, multi-channel distribution (plugin, vercel skills CLI, npx, Cursor), npm gotchas, end-to-end first publish, the review checklist for third-party skills, plus MCP / A2A references for protocol-connected skills.",
|
|
6
|
-
"version": "0.
|
|
6
|
+
"version": "0.25.1",
|
|
7
7
|
"author": {
|
|
8
8
|
"name": "ssheleg",
|
|
9
9
|
"url": "https://x.com/sshlg93"
|
|
@@ -5,7 +5,7 @@ license: MIT
|
|
|
5
5
|
compatibility: Authoring works on any agent. The bundled scripts/ need python3. Publishing steps need git, gh, node and npm; the plugin gates need the claude CLI. Not usable on the Claude API surface, which has no network and no runtime package install.
|
|
6
6
|
metadata:
|
|
7
7
|
author: ssheleg
|
|
8
|
-
version: "0.
|
|
8
|
+
version: "0.25.1"
|
|
9
9
|
homepage: https://github.com/ssheleg/make-skill
|
|
10
10
|
---
|
|
11
11
|
|
|
@@ -10,7 +10,8 @@ API or claude.ai instead is `references/surfaces.md`.
|
|
|
10
10
|
- The distributable repo layout (tree, public-repo floor, version sync, gates)
|
|
11
11
|
- 1. Claude Code plugin
|
|
12
12
|
- 2. vercel-labs skills CLI
|
|
13
|
-
- 3. npx installer — npm gotchas
|
|
13
|
+
- 3. npx installer — npm gotchas; the installer must refuse the shadow it
|
|
14
|
+
documents; how updates reach the machine; implementation traps
|
|
14
15
|
- First publish — the 11-step sequence
|
|
15
16
|
- 4. Cursor
|
|
16
17
|
- 5. Ship a FAMILY via an umbrella repo
|
|
@@ -212,6 +213,50 @@ package's own repo, `npx` resolves the local package and reports a false
|
|
|
212
213
|
- **`npx` inside the package's own repo** resolves the local package → a false
|
|
213
214
|
`command not found`. Always e2e-test from another cwd.
|
|
214
215
|
|
|
216
|
+
### The installer must refuse the shadow it documents
|
|
217
|
+
|
|
218
|
+
The shadow rule at the top of this file is not only about the skills CLI: **a member's
|
|
219
|
+
own `npx @scope/<name>` installer is the other machine that recreates the shadow.** It
|
|
220
|
+
writes `~/.claude/skills/<name>` on request, and on a machine where the same skill is
|
|
221
|
+
installed as a Claude Code plugin, that write is a plain copy that outranks the plugin
|
|
222
|
+
and serves the version it was copied from forever. Measured 2026-08-29: a bare
|
|
223
|
+
`npx @ssheleg/telegram-dev` created three plain copies in `~/.claude/skills/` while the
|
|
224
|
+
`telegram-dev` plugin was enabled — and every bin installer in the family had the same
|
|
225
|
+
hole, because every member's CI tested a fresh `HOME` only, so the plugin-present case
|
|
226
|
+
had never run anywhere.
|
|
227
|
+
|
|
228
|
+
The canon, for every bin installer that targets `~/.claude/skills/`:
|
|
229
|
+
|
|
230
|
+
- **Detect the plugin from the TARGET home before writing.** Read that home's
|
|
231
|
+
`~/.claude/plugins/installed_plugins.json` and look for a plugin whose name matches
|
|
232
|
+
the skill under ANY marketplace — the keys are `<name>@<marketplace>`, and the two
|
|
233
|
+
names differ often. A `~/.claude/plugins/marketplaces/<name>` directory also signals
|
|
234
|
+
the plugin channel, but only as the fallback read: it **under-reports** — a
|
|
235
|
+
marketplace added from a local `directory` source has no dir there at all, and a
|
|
236
|
+
differently-named marketplace never matches the skill name. A presence check keyed on
|
|
237
|
+
that directory alone stays green while the shadow lands, which is the fail-open
|
|
238
|
+
class: it looks at the wrong file and then exits 0.
|
|
239
|
+
- **Refuse, and exit non-zero.** Print what was found, why the plain copy is refused,
|
|
240
|
+
and the plugin-channel remedy — `claude plugin marketplace update <name>` then
|
|
241
|
+
`claude plugin update <name>@<marketplace>` with the spec read from the JSON, or the
|
|
242
|
+
family launcher (`npx --yes sshlg-skills@latest update`) for a member that composes
|
|
243
|
+
with its family. A refusal that exits 0 reads as success to every script above it:
|
|
244
|
+
this repository's own installer shipped exactly that half-measure until v0.25.0 —
|
|
245
|
+
marketplace-dir check, a `skip:` message, exit 0.
|
|
246
|
+
- **`--force` is the deliberate override**, named inside the refusal itself. Two
|
|
247
|
+
channels on one agent is a choice someone may make on purpose, and the flag is where
|
|
248
|
+
that choice gets recorded instead of happening by accident.
|
|
249
|
+
- **Absence fails open; corruption never crashes.** A missing or unparsable
|
|
250
|
+
`installed_plugins.json` reads as "no plugin" — the fresh HOME is the common case,
|
|
251
|
+
and an installer that dies on a parse error refuses the machines that need it most.
|
|
252
|
+
- **Only Claude Code has plugins.** The check gates the `~/.claude` write alone;
|
|
253
|
+
installs into other agents' skill directories are untouched by it.
|
|
254
|
+
- **CI runs the plugin-present case, not only a fresh HOME.** A fake HOME whose
|
|
255
|
+
`installed_plugins.json` declares the plugin, asserting all three at once: the
|
|
256
|
+
non-zero exit, the remedy in the output, and that nothing was written — plus the
|
|
257
|
+
`--force` path installing and the fresh HOME still installing. Reference
|
|
258
|
+
implementation: this repository's `bin/make-skill.js` and `test/installer_test.js`.
|
|
259
|
+
|
|
215
260
|
### How updates reach the machine — decide it, then SAY it
|
|
216
261
|
|
|
217
262
|
An installer that never mentions updates has still chosen an update model: **never**. The
|
|
@@ -245,7 +290,7 @@ offer the launcher and say plainly that auto-update is off **on purpose**.
|
|
|
245
290
|
Either way the last thing the installer prints is how the next version arrives. "Installed"
|
|
246
291
|
is not a complete sentence.
|
|
247
292
|
|
|
248
|
-
|
|
293
|
+
### Installer implementation traps (read while WRITING the CLI)
|
|
249
294
|
|
|
250
295
|
- **Piped stdin + readline:** sequential `rl.question()` drops buffered lines.
|
|
251
296
|
Use ONE persistent-listener prompter for the whole flow (super-ux
|
|
@@ -356,7 +401,8 @@ claude plugin update <name>@<name> # full id required
|
|
|
356
401
|
`claude plugin validate ./plugins/<name> --strict` and
|
|
357
402
|
`claude plugin validate . --strict` → both exit 0.
|
|
358
403
|
3. Functional tests: installer against a scratch `HOME` (fresh / rerun-skip /
|
|
359
|
-
`--force`), `node --check`
|
|
404
|
+
`--force` / **plugin-present refusal**, per the canon in §3), `node --check`
|
|
405
|
+
on the CLI, piped-menu tests.
|
|
360
406
|
4. Conventional commit; push; confirm CI `success`; tag `v<ver>` and push the tag;
|
|
361
407
|
`gh release create` from the CHANGELOG section (or let the release workflow
|
|
362
408
|
below do it).
|
|
@@ -143,7 +143,17 @@ body receives `$ARGUMENTS`. Two rules cost a debugging round each:
|
|
|
143
143
|
|
|
144
144
|
- **Never name a command after a skill in the same plugin.** Commands are skills
|
|
145
145
|
now: both claim `/<name>`, the skill wins, the command is unreachable always-on
|
|
146
|
-
cost visible only in `claude plugin details`.
|
|
146
|
+
cost visible only in `claude plugin details`. That is the default for every new
|
|
147
|
+
plugin. **One recorded exception (operator decision, 2026-08-30): the ssheleg
|
|
148
|
+
family ships same-named commands deliberately** — `task-pipeline`,
|
|
149
|
+
`project-audit`, `seo-aeo-audit`, `sheleg-design`, `agent-sync`, and
|
|
150
|
+
`super-ux`'s `vision`, `ux-foundation`, `ux-flows`, `ux-audit`. The cost is
|
|
151
|
+
accepted, not waived: the skill wins the trigger, and each command stays an
|
|
152
|
+
always-on token cost that may be unreachable in the picker. An audit that finds
|
|
153
|
+
a collision on this list reports it as *deliberate, recorded — no change
|
|
154
|
+
needed*; a collision NOT on a dated, recorded exception list is still the gap
|
|
155
|
+
this rule names. A rule's exception is enumerated, dated, and carries its cost
|
|
156
|
+
— never implied.
|
|
147
157
|
- **Quote `argument-hint`.** Bare `[a | b]` is a YAML flow sequence; a comma
|
|
148
158
|
inside it drops the entire frontmatter block, leaving a command with no
|
|
149
159
|
description and no warning.
|
|
@@ -236,7 +246,8 @@ what the agent reads at the exact moment something is missing.
|
|
|
236
246
|
- [ ] `PostToolUse` advises (`systemMessage`), `PreToolUse` blocks — not the reverse
|
|
237
247
|
- [ ] Hook commands quote `"${CLAUDE_PLUGIN_ROOT}"` and set a `timeout`
|
|
238
248
|
- [ ] Hook scripts are executable, have a shebang, and need no `jq`
|
|
239
|
-
- [ ] No command named after a skill
|
|
249
|
+
- [ ] No command named after a skill — or the collision is on a recorded, dated
|
|
250
|
+
exception list (see *Commands*); every `argument-hint` quoted
|
|
240
251
|
- [ ] Plugin agents carry no `hooks` / `mcpServers` / `permissionMode`
|
|
241
252
|
- [ ] Scripts are stdlib-only, inside the skill dir, invoked by a resolvable path
|
|
242
253
|
- [ ] No command the agent is told to RUN contains `${CLAUDE_PLUGIN_ROOT}` — it is
|
|
@@ -125,8 +125,11 @@ Report the table before changing anything, then fix.
|
|
|
125
125
|
MCP server: the degradation contract written in the body for all three axes
|
|
126
126
|
(not Claude Code / recommended plugin absent / tool absent); hooks that
|
|
127
127
|
exit 0 silently when the event is not theirs; `PostToolUse` advising rather
|
|
128
|
-
than blocking; commands quoted and never named after a skill
|
|
129
|
-
|
|
128
|
+
than blocking; commands quoted and never named after a skill (a collision on
|
|
129
|
+
the recorded, dated exception list in `references/host-capabilities.md` —
|
|
130
|
+
the ssheleg family's same-named commands, operator decision 2026-08-30 — is
|
|
131
|
+
reported as *deliberate, recorded — no change needed*, not as a gap); plugin
|
|
132
|
+
agents free of `hooks`, `mcpServers` and `permissionMode`.
|
|
130
133
|
|
|
131
134
|
## Personal skills — the short form
|
|
132
135
|
|