@ssheleg/make-skill 0.10.0 → 0.11.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 CHANGED
@@ -1,5 +1,185 @@
1
1
  # Changelog
2
2
 
3
+ ## v0.11.1 — 2026-08-10
4
+
5
+ A behavioural pass over v0.11.0 — walking the skill the way an agent walks it and
6
+ running every command it hands out, rather than re-reading the files. The
7
+ structural gates were already green; what this found was in the one field no
8
+ structural gate covers.
9
+
10
+ ### Fixed — the description had a neighbour and no answer to it
11
+
12
+ Coexistence was measured instead of assumed, across the 130 skills of the 23
13
+ enabled plugins on the author's machine. The nearest neighbour is **not** the one
14
+ `test/evals/RESULTS.md` predicted:
15
+
16
+ | Neighbour | Overlap |
17
+ |---|---|
18
+ | **`claude-mem:version-bump`** | **9.6%** |
19
+ | `agent-sync` | 5.5% |
20
+ | `task-pipeline` (the predicted one) | 4.7% |
21
+
22
+ `version-bump` advertises "version increments across package.json,
23
+ marketplace.json, plugin.json manifests, git tagging, GitHub releases, and
24
+ changelog generation" — this skill's release checklist, and enabled alongside it.
25
+ The overlap is not vocabulary, it is *job*.
26
+
27
+ - The description now carries the clause `references/authoring.md` prescribes for
28
+ exactly this case: **NOT for a version bump or release in a repo that ships
29
+ anything but a skill or plugin.**
30
+ - **`triggers.json` gains q21 and q22**, the same manifest-bump-and-release
31
+ request once where the artifact IS a skill and once where it is not, on
32
+ opposite sides of the split so the near-miss is measured in validation rather
33
+ than tuned on. 22 queries, 11 positive / 11 near-miss negative.
34
+ - `RESULTS.md` records the measured table and drops the guess.
35
+
36
+ ### Added — the headroom rule reaches the field that decides triggering
37
+
38
+ v0.11.0 gave the body a 5% working limit and left the description at 1003 of
39
+ 1024\. Adding the clause above needed 60 characters that did not exist — the same
40
+ disease, in the field that decides whether the skill fires at all. Both the house
41
+ validator and the bundled auditor (`--house`) now hold the description to **≤970
42
+ of 1024**, with a negative self-test on each.
43
+
44
+ ### Verified, not assumed
45
+
46
+ Every command the canon hands an agent was executed against the released
47
+ artifact: `make-skill-audit` by bare name, the non-Claude fallback path, the
48
+ raw-fallback reference URLs (200 — checked for the first time), `npx skills add
49
+ --list` (no skeleton leaks), `npx` from a non-repo cwd, `claude plugin details`.
50
+ The hook was exercised on all three of its paths and returns valid JSON. Building
51
+ a skill from `assets/SKILL.template.md` and auditing it gives 0 GAP. The
52
+ compression in v0.11.0 was checked against every fact the evaluation scenarios
53
+ depend on: all of them are still reachable, and all 11 references are still
54
+ linked from the body.
55
+
56
+ The evaluation suite is still **authored and never executed against a model** —
57
+ that gap needs a fresh session per query per model, and this pass does not close
58
+ it. What it does show is why it matters: the risk this repo had written down was
59
+ not the risk it had.
60
+
61
+ ## v0.11.0 — 2026-08-10
62
+
63
+ A file-by-file audit of the whole repo, run with this skill's own evidence rules.
64
+ It found one defect that made the canon read as nonsense, one that made its first
65
+ documented command fail, and a class of drift nothing was checking. Every fix
66
+ here ships with the rule that stops it coming back.
67
+
68
+ ### Fixed — the two defects that manufacture wrong answers
69
+
70
+ - **A path variable used as a noun.** `SKILL.md` said "Hooks, subagents,
71
+ `/commands`, `${CLAUDE_PLUGIN_ROOT}` and MCP servers exist only inside Claude
72
+ Code". The body is substituted at load time, so what an agent actually read was
73
+ "Hooks, subagents, `/commands`, `/Users/…/plugins/cache/make-skill/0.10.0` and
74
+ MCP servers exist only inside Claude Code" — a filesystem path presented as a
75
+ host capability. The body now names the capability, and the validator rejects
76
+ any `${CLAUDE_*}` in it.
77
+
78
+ - **The first command of the audit procedure could not run.** `retrofit.md`, the
79
+ `/skill-audit` command and the `skill-auditor` agent all opened with
80
+ `python3 "${CLAUDE_PLUGIN_ROOT}/skills/make-skill/scripts/audit_skill.py"`.
81
+ That variable is substituted into *text* and exported to *hooks*, but it is
82
+ **empty in the Bash tool** — measured on Claude Code 2.1.220, the command
83
+ expands to `/skills/...` and dies. The instruction immediately above it says
84
+ "do not reason your way through it", so the agent was left with a forbidden
85
+ fallback and a broken tool, and the cheap way out is a PASS nobody ran.
86
+
87
+ Fixed at the root: **`plugins/make-skill/bin/make-skill-audit`**. Claude Code
88
+ puts a plugin's `bin/` on the Bash tool's PATH, so the auditor is now reachable
89
+ by name with no variable in the command. The wrapper resolves its payload from
90
+ its own location (following symlinks), so it also works copied, symlinked into
91
+ an agents hub, or called by absolute path. `bin/` is now documented as a host
92
+ capability in its own right — it is the only reliable way to hand an agent a
93
+ runnable command.
94
+
95
+ ### Added — NOT-RUN, the missing verdict
96
+
97
+ An audit with only PASS and GAP forces a check whose tool is absent into one of
98
+ them, and the cheaper lie is PASS. `retrofit.md` now defines **NOT-RUN**, and the
99
+ standing example is its own item 1: `skills-ref validate` installs from source
100
+ only, so on most machines "NOT-RUN, with the reason" is the honest result. The
101
+ conformance checklist says so where the demand is made.
102
+
103
+ ### Fixed — claims about the repo that the repo contradicted
104
+
105
+ Each of these was true when written and drifted the release after:
106
+
107
+ - `SKILL.md` said "13-item checklist" in its reference table and "14-item" nine
108
+ sections later; the file has 14.
109
+ - `SKILL-CARD.md` — the card a reviewer reads before installing — was pinned at
110
+ 0.9.0, claimed "ten files" of instruction surface against eleven, and "six
111
+ groups" of CI self-tests against eight.
112
+ - `README.md` never listed `mcp-ship.md`, added in v0.10.0.
113
+ - `README.md`'s "no agent turn required" one-liner used a glob one directory
114
+ level too shallow: `no matches found`, and at the right depth it matches every
115
+ cached version at once.
116
+ - `CONTRIBUTING.md` said "npm publishing stays a human step" 24 lines above "there
117
+ is no manual `npm publish` step in any repo in the family", named `chars/4`
118
+ where the validator uses the measured 3.9, and counted four channels where the
119
+ canon documents five.
120
+ - Three files claimed the hook is "30 lines"; it is 43. The claim is gone rather
121
+ than corrected — the number told a reader nothing.
122
+
123
+ **The rule that closes the class:** counted claims are now compared to the
124
+ artifacts they describe (checklist items, reference files, CI self-test groups),
125
+ `SKILL-CARD.md`'s version must equal `plugin.json`'s, and every shipped
126
+ `references/*.md` must appear in the README. A new gotcha states the principle: a
127
+ number typed by hand is an assertion, not documentation.
128
+
129
+ ### Fixed — the Cursor rule contradicted the validator
130
+
131
+ `cursor/rules/make-skill.mdc` prescribed a repo-root `templates/` directory,
132
+ which `test/validate.py` rejects outright and a CI self-test asserts against. A
133
+ Cursor user following the shipped rule built a repo this repo refuses. The rule
134
+ now matches the canon, drops the superseded "npm publish = human 2FA", carries
135
+ the path-variable fact and the family-pin rule — and the validator fails if a
136
+ `.mdc` prescribes that layout again.
137
+
138
+ ### Fixed — the installers created the shadow the canon forbids
139
+
140
+ `bin/make-skill.js` and `install.sh` wrote `~/.claude/skills/make-skill`, which
141
+ is exactly the duplicate-shadow this canon spends three paragraphs warning about,
142
+ with no check and no warning. Both now detect an installed plugin and refuse,
143
+ naming the update commands instead; `--force` still overrides.
144
+
145
+ ### Fixed — the auditor
146
+
147
+ - `PASS NAME_CHARSET … is spec-legal` was printed for `claude-invoice-helper`,
148
+ two lines above the GAP rejecting it. A PASS line quoted out of context is how
149
+ a wrong verdict acquires real command output as its evidence; it now says
150
+ "uses a legal charset".
151
+ - `REF_NO_TRIGGER` did not blank quoted spans, although `_strip_quoted` exists
152
+ for exactly that: the canon could not quote the "see references/" it forbids
153
+ without tripping its own linter.
154
+ - Link findings now carry `file:line`, the house checks (`--house`) report PASS
155
+ as well as GAP — "the house rules were checked" has to be provable from the
156
+ output the canon tells the agent to cite — and a body over the line budget also
157
+ reports its token count instead of hiding it behind `elif`.
158
+
159
+ ### Fixed — release and budget
160
+
161
+ - **`release.yml` now runs both `claude plugin validate … --strict` on the tag.**
162
+ The validate workflow also runs there, but it is a separate workflow: a red run
163
+ in it could not stop a release being cut and published.
164
+ - **The body budget has a working limit.** v0.10.0 shipped at ~4995 of 5000 — 20
165
+ characters from a red build, which turns every future correction into a trade
166
+ against an existing section. The validator now fails past **4750** (5%
167
+ headroom); this release moved duplicated material into the references that
168
+ already carried it and landed at ~4671.
169
+ - **The family pin is a stated non-negotiable of every release.** make-skill
170
+ 0.10.0 was on npm and installed while `sshlg-skills list` still advertised
171
+ 0.9.1 — the exact failure `distribution.md` describes, on this repo, found by
172
+ this audit.
173
+ - `XML_TAG_RE` is now compared between `test/validate.py` and the shipped
174
+ auditor: one rule, one pattern, or a skill passes one gate and fails the other.
175
+
176
+ ### Notes
177
+
178
+ The evaluation suite is still **authored and never executed against a model**
179
+ (`test/evals/RESULTS.md`). Running it needs a fresh agent session per query on
180
+ each model in scope, which no CI job here does and no single session can honestly
181
+ fake. It remains the largest open gap, and `SKILL-CARD.md` says so to a reviewer.
182
+
3
183
  ## v0.10.0 — 2026-08-06
4
184
 
5
185
  ### Added
package/README.md CHANGED
@@ -35,10 +35,12 @@ make a skill that turns our incident runbooks into a triage workflow
35
35
  ```
36
36
 
37
37
  …or run just the mechanical half against any skill directory, no agent turn
38
- required:
38
+ required. The plugin puts the auditor on the Bash tool's PATH, and the skills-CLI
39
+ copy ships the script it wraps:
39
40
 
40
41
  ```bash
41
- python3 ~/.claude/plugins/*/make-skill/*/skills/make-skill/scripts/audit_skill.py ./my-skill --house
42
+ make-skill-audit ./my-skill --house # in Claude Code
43
+ python3 ~/.agents/skills/make-skill/scripts/audit_skill.py ./my-skill --house # any terminal
42
44
  ```
43
45
 
44
46
  With no argument the skill detects the situation — a `SKILL.md` or
@@ -148,6 +150,7 @@ agent opens only when the situation calls for them:
148
150
  | `claude-code-plugin.md` | the [Claude Code layer](https://code.claude.com/docs/en/plugins-reference) — `plugin.json` / `marketplace.json` schemas, plugin sources, component locations, host-only front-matter, path variables, cache and symlink rules, the `claude plugin` CLI |
149
151
  | `distribution.md` | the repo layout, every install channel, exact CLI flags, npm publishing traps, the release checklist |
150
152
  | `mcp.md` | [MCP](https://modelcontextprotocol.io) — skill vs server, primitives and methods, transports, consent and untrusted-output rules |
153
+ | `mcp-ship.md` | shipping an MCP server — mounting it in an existing app and the double-path 404, auth middleware, the 404/307/401 bisect, `server.json` and the MCP Registry |
151
154
  | `a2a.md` | [A2A](https://a2a-protocol.org) — Agent Cards, task lifecycle, method mapping, v0.x→1.0 wire drift |
152
155
 
153
156
  Plus six skeletons in `skills/make-skill/assets/` — inside the skill directory,
@@ -175,7 +178,9 @@ npx skills add ssheleg/make-skill
175
178
  Don't target `claude-code` here if you installed the plugin above — see
176
179
  one-channel-per-agent.
177
180
 
178
- **npx, no clone:**
181
+ **npx, no clone** — installs a plain copy into `~/.claude/skills/make-skill`, so
182
+ use it only if you did **not** install the plugin above. Both installers detect
183
+ the plugin and refuse rather than leave a copy shadowing it:
179
184
 
180
185
  ```bash
181
186
  npx github:ssheleg/make-skill # always current with this repo
@@ -185,7 +190,7 @@ npx @ssheleg/make-skill # npm registry (scoped: npm blocks the bare na
185
190
  **Cursor, per project:** copy [`cursor/rules/make-skill.mdc`](cursor/rules/make-skill.mdc)
186
191
  into `.cursor/rules/` — it is self-contained by design.
187
192
 
188
- **Plain skill:**
193
+ **Plain skill** — same one-channel caveat as `npx` above:
189
194
 
190
195
  ```bash
191
196
  git clone https://github.com/ssheleg/make-skill
@@ -228,7 +233,8 @@ says so); `bash` for `install.sh` and the hook (Windows users: use `npx`, the
228
233
  plugin, or the skills CLI). The canon itself is plain Markdown and needs nothing.
229
234
 
230
235
  What runs on its own: one `PostToolUse` hook, which exits silently unless the
231
- file you just wrote is a `SKILL.md`. It is 30 lines and is described in
236
+ file you just wrote is a `SKILL.md`. Read it at
237
+ `plugins/make-skill/hooks/skill-md-audit.sh`; it is described in
232
238
  [SECURITY.md](SECURITY.md) and [SKILL-CARD.md](SKILL-CARD.md).
233
239
 
234
240
  ## Repo layout
@@ -242,6 +248,7 @@ plugins/make-skill/
242
248
  │ ├── references/*.md # loaded on demand
243
249
  │ ├── scripts/audit_skill.py # audits any skill dir, stdlib only
244
250
  │ └── assets/*.template.* # six skeletons: skill, manifests, hooks, agent, command
251
+ ├── bin/make-skill-audit # on Claude Code's Bash PATH — the auditor by name
245
252
  ├── hooks/ # Claude Code only — PostToolUse SKILL.md audit
246
253
  ├── agents/skill-auditor.md # Claude Code only
247
254
  └── commands/skill-audit.md # Claude Code only, never named after a skill
package/SECURITY.md CHANGED
@@ -24,15 +24,21 @@ is the only thing that runs without you asking:
24
24
  author skills it is a no-op you never see. When it is a `SKILL.md`, it runs
25
25
  the bundled auditor on that directory and returns the report as advice
26
26
  (`systemMessage`). It never blocks, never writes a file, never makes a network
27
- call, and needs no `jq`. Thirty lines; read them before enabling the plugin.
27
+ call, and needs no `jq`. Read it before enabling the plugin — it is short.
28
28
  - **`skills/make-skill/scripts/audit_skill.py`** reads a skill directory and
29
29
  prints a report. Standard library only. It writes nothing and is run by you,
30
30
  the `/skill-audit` command, the subagent, or the hook above.
31
+ - **`plugins/make-skill/bin/make-skill-audit`** is a POSIX-shell wrapper that
32
+ Claude Code places on the Bash tool's PATH while the plugin is enabled. It
33
+ resolves the auditor relative to its own location and `exec`s it; it runs only
34
+ when you invoke it, and it touches nothing else.
31
35
  - **`bin/make-skill.js`** (run via `npx`) and **`install.sh`** copy the skill
32
36
  directory into `~/.claude/skills/make-skill` and nothing else — no command file,
33
- no other path in `$HOME` — and overwrite only with `--force`. Both are
34
- zero-dependency: no network calls, no postinstall script. CI asserts the
35
- absence of `~/.claude/commands/make-skill.md` on every run.
37
+ no other path in `$HOME` — and overwrite only with `--force`. Both refuse to
38
+ install at all when the Claude Code plugin is present, rather than leaving a
39
+ plain copy that shadows it. Both are zero-dependency: no network calls, no
40
+ postinstall script. CI asserts the absence of `~/.claude/commands/make-skill.md`
41
+ on every run.
36
42
  - **`test/validate.py`** reads repository files and exits with a status. It writes
37
43
  nothing. `test/evals/` is inert data — text a human feeds to an agent — and
38
44
  `test/evals/fixtures/untrusted-skill.md` is a deliberately malicious *sample*
package/bin/make-skill.js CHANGED
@@ -88,6 +88,24 @@ function main(argv) {
88
88
  }
89
89
 
90
90
  const home = os.homedir();
91
+
92
+ // One channel per agent. A plain ~/.claude/skills/make-skill beside an
93
+ // installed plugin is two listings of the same skill, and the stale copy wins
94
+ // — the exact trap this canon documents. Refuse rather than create it.
95
+ const marketplace = path.join(home, '.claude', 'plugins', 'marketplaces', 'make-skill');
96
+ if (fs.existsSync(marketplace) && !force) {
97
+ console.log(
98
+ 'skip: make-skill is already installed as a Claude Code plugin\n' +
99
+ ` (${marketplace}).\n` +
100
+ ' Installing a plain copy into ~/.claude/skills would shadow it, and the\n' +
101
+ ' stale copy is the one that wins. Update the plugin instead:\n' +
102
+ ' claude plugin marketplace update make-skill\n' +
103
+ ' claude plugin update make-skill@make-skill\n' +
104
+ ' Pass --force if you really want both.'
105
+ );
106
+ return 0;
107
+ }
108
+
91
109
  installOne(
92
110
  'make-skill skill',
93
111
  skillSrc,
@@ -72,9 +72,10 @@ canon below only ADDS to it.
72
72
  .claude-plugin/marketplace.json # plugins[0].source: ./plugins/<name>
73
73
  plugins/<name>/.claude-plugin/plugin.json
74
74
  plugins/<name>/skills/<skill>/SKILL.md (+ references/, scripts/, assets/)
75
+ plugins/<name>/skills/<skill>/assets/*.template.* # skeletons — NEVER SKILL.md
75
76
  plugins/<name>/commands/*.md # only under a name no skill uses
77
+ plugins/<name>/bin/<exe> # on Claude Code's Bash PATH
76
78
  cursor/rules/*.mdc # self-contained, NO relative links
77
- templates/*.md # skeletons — NEVER name one SKILL.md
78
79
  bin/<name>.js + package.json # zero-dep npx installer
79
80
  test/validate.py # stdlib-only consistency validator
80
81
  test/evals/ # triggers.json + scenarios.json (data, run by a human)
@@ -110,13 +111,16 @@ checker, not a house opinion:
110
111
  - A pinned `version` is the update cache key — bump it or nobody ever receives
111
112
  the change. Marketplace names like `agent-skills`/`anthropic-*` are reserved
112
113
  and stop loading.
113
- - Bundled scripts resolve through `${CLAUDE_PLUGIN_ROOT}`, state through
114
- `${CLAUDE_PLUGIN_DATA}` — both Claude-Code-only, so keep relative paths as the
115
- portable contract.
114
+ - Path variables are substituted into skill/command/agent TEXT and exported to
115
+ HOOK processes — but `${CLAUDE_PLUGIN_ROOT}` is **empty in the Bash tool**, so
116
+ a command you tell the agent to run must never be built from it (it expands to
117
+ `/skills/...` and dies). Put runnable scripts in the plugin's `bin/`, which
118
+ Claude Code adds to the Bash PATH, and call them by name; keep relative paths
119
+ as the portable contract. State through `${CLAUDE_PLUGIN_DATA}`.
116
120
 
117
121
  ## Host capabilities and the degradation contract
118
122
 
119
- Hooks, subagents, `/commands`, `${CLAUDE_PLUGIN_ROOT}` and MCP servers exist only
123
+ Hooks, subagents, `/commands`, plugin path variables and MCP servers exist only
120
124
  inside Claude Code — which is a minority of where skills run. **Each is an
121
125
  accelerator with a WRITTEN fallback; the skill still finishes its job without
122
126
  it.** Put all three cases in the body, in the words the agent reads when it hits
@@ -148,9 +152,19 @@ through a quoted `"${CLAUDE_PLUGIN_ROOT}/…"` with a `timeout`; hook scripts ex
148
152
  with `npx skills add <repo> --list`.
149
153
  - **Validator must be able to fail:** CI runs a negative self-test (corrupt a copy →
150
154
  expect FAIL). A validator that can't fail is decoration.
155
+ - **A number typed by hand is an assertion, not documentation.** Counts of files,
156
+ steps and checklist items drift the release after you write them — compute
157
+ them, or have the validator compare each claim to the artifact.
158
+ - **Audit verdicts are PASS / GAP / NOT-RUN.** Without the third, a check whose
159
+ tool is missing gets recorded as a PASS nobody earned.
151
160
  - **One channel per agent:** don't run a plugin AND a plain `~/.claude/skills` copy
152
161
  on the same install — the stale plain copy shadows the plugin.
153
- - **npm name first:** `npm view <name>` (E404 = free). **npm publish = human 2FA.**
162
+ - **npm name first:** `npm view <name>` (E404 = free — the name-similarity 403
163
+ only fires on publish). **A `v*` tag publishes**: arm CI publishing once and a
164
+ manual `npm publish` is the fallback, not the route.
165
+ - **A release is not done until the family pin moves.** An umbrella that still
166
+ pins the previous version keeps advertising and installing it, with nothing in
167
+ either repo revealing the gap.
154
168
  - **Commands ARE skills now:** a `commands/<x>.md` beside `skills/<x>/` registers
155
169
  `/<x>` twice — the skill wins, the command is unreachable always-on cost. Check
156
170
  with `claude plugin details <name>@<marketplace>`; quote every `argument-hint`.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ssheleg/make-skill",
3
- "version": "0.10.0",
4
- "description": "Create, retrofit, audit, and ship agent skills & Claude Code plugins the proven ssheleg way \u2014 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.",
3
+ "version": "0.11.1",
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",
7
7
  "plugin",
@@ -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.10.0",
6
+ "version": "0.11.1",
7
7
  "author": {
8
8
  "name": "ssheleg",
9
9
  "url": "https://x.com/sshlg93"
@@ -13,16 +13,16 @@ You audit skills. You do not fix them, and you do not offer to.
13
13
  `.claude/skills/*/`, or a single directory handed to you.
14
14
 
15
15
  2. For each one, run the bundled auditor first — it is deterministic and costs
16
- no reasoning:
16
+ no reasoning. The make-skill plugin puts it on your PATH:
17
17
 
18
18
  ```bash
19
- python3 "${CLAUDE_PLUGIN_ROOT}/skills/make-skill/scripts/audit_skill.py" <skill-dir> --house
19
+ make-skill-audit <skill-dir> --house
20
20
  ```
21
21
 
22
- If `${CLAUDE_PLUGIN_ROOT}` is unset, find the script under the make-skill
23
- directory you were loaded from. If `python3` is missing, say so once and fall
24
- back to reading `references/agent-skills-spec.md` and checking by hand — a
25
- missing interpreter changes how you work, not whether you report.
22
+ If it exits 2 for a missing `python3`, say so once and check the mechanical
23
+ items by hand from `references/agent-skills-spec.md`. A missing interpreter
24
+ changes how you work, not whether you report — and it makes those items
25
+ **NOT-RUN**, never PASS.
26
26
 
27
27
  3. Work the judgement half from
28
28
  `${CLAUDE_PLUGIN_ROOT}/skills/make-skill/references/retrofit.md`: one job per
@@ -41,6 +41,6 @@ One table for the caller, nothing else:
41
41
  |---|---|---|
42
42
 
43
43
  `PASS` only for a check you actually ran — a `file:line` or the command output.
44
- `GAP` carries what is wrong and the fix that closes it. No "looks fine". Finish
45
- with the single highest-value next action across everything you audited, and
46
- stop.
44
+ `GAP` carries what is wrong and the fix that closes it. `NOT-RUN` names the tool
45
+ that was missing. No "looks fine". Finish with the single highest-value next
46
+ action across everything you audited, and stop.
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env sh
2
+ # make-skill-audit — the bundled skill auditor, reachable by name.
3
+ #
4
+ # Claude Code puts a plugin's bin/ on the Bash tool's PATH while the plugin is
5
+ # enabled, so `make-skill-audit <dir> --house` works in a session. That matters
6
+ # because ${CLAUDE_PLUGIN_ROOT} is substituted into skill/command text but is
7
+ # NOT exported to the Bash tool's environment: a documented command written
8
+ # around it expands to "/skills/..." and fails, and an agent that cannot run the
9
+ # deterministic half tends to reason through it and report a PASS it never ran.
10
+ #
11
+ # Resolves the auditor from its own location, never from an environment
12
+ # variable, so it also works when copied, symlinked into a hub, or invoked
13
+ # through an absolute path.
14
+ set -eu
15
+
16
+ self="$0"
17
+ # Follow symlinks without readlink -f, which BSD/macOS does not have.
18
+ while [ -L "$self" ]; do
19
+ link="$(readlink "$self")"
20
+ case "$link" in
21
+ /*) self="$link" ;;
22
+ *) self="$(dirname "$self")/$link" ;;
23
+ esac
24
+ done
25
+ here="$(cd "$(dirname "$self")" && pwd)"
26
+ auditor="$here/../skills/make-skill/scripts/audit_skill.py"
27
+
28
+ if [ ! -f "$auditor" ]; then
29
+ echo "make-skill-audit: auditor not found at $auditor" >&2
30
+ echo "Run scripts/audit_skill.py from the make-skill skill directory instead." >&2
31
+ exit 2
32
+ fi
33
+
34
+ if ! command -v python3 >/dev/null 2>&1; then
35
+ echo "make-skill-audit: no python3 on PATH." >&2
36
+ echo "Record the mechanical items NOT-RUN with this reason, then work the" >&2
37
+ echo "checklist by hand from references/agent-skills-spec.md." >&2
38
+ exit 2
39
+ fi
40
+
41
+ exec python3 "$auditor" "$@"
@@ -7,25 +7,24 @@ Audit the skill at `$ARGUMENTS` (default: the skill directory in the current
7
7
  working directory, or every `skills/*/` under `plugins/*/` if this is a plugin
8
8
  repo).
9
9
 
10
- 1. Run the bundled auditor — it does the mechanical half deterministically:
10
+ 1. Run the bundled auditor — it does the mechanical half deterministically. This
11
+ plugin puts it on your PATH:
11
12
 
12
13
  ```bash
13
- python3 "${CLAUDE_PLUGIN_ROOT}/skills/make-skill/scripts/audit_skill.py" <skill-dir> --house
14
+ make-skill-audit <skill-dir> --house
14
15
  ```
15
16
 
16
- No `${CLAUDE_PLUGIN_ROOT}` (not running as a Claude Code plugin)? The script
17
- sits at `scripts/audit_skill.py` inside the skill directory you are reading
18
- this from — commonly `~/.agents/skills/make-skill/` or
19
- `~/.claude/skills/make-skill/`. No `python3` at all? Do the same checks by
20
- hand from `references/agent-skills-spec.md`; the checklist is the same one the
21
- script implements.
17
+ No `python3`? The wrapper says so and exits 2. Record the mechanical items as
18
+ **NOT-RUN with that reason** and check them by hand from the spec reference —
19
+ never as PASS.
22
20
 
23
21
  2. Then work the judgement half from
24
22
  `${CLAUDE_PLUGIN_ROOT}/skills/make-skill/references/retrofit.md` — one job,
25
23
  entry point, evaluations, distribution, repo meta. The script cannot answer
26
- those.
24
+ those. Read the file; do not reconstruct it from memory.
27
25
 
28
- 3. Report one gap table: `PASS` / `GAP` per item, each with `file:line` or the
29
- command output that proves it. End with exactly ONE suggested next action.
26
+ 3. Report one gap table: `PASS` / `GAP` / `NOT-RUN` per item, each with
27
+ `file:line` or the command output that proves it. End with exactly ONE
28
+ suggested next action.
30
29
 
31
30
  Do not fix anything until the table is reported.
@@ -1,5 +1,5 @@
1
1
  {
2
- "description": "make-skill — spec check on every SKILL.md write. The hook exits 0 without output for any path that is not a SKILL.md, so installing this plugin globally changes nothing in projects that do not author skills. It never blocks: PostToolUse runs after the write, and the result is advice, not a veto.",
2
+ "description": "make-skill — spec check on every SKILL.md write. The hook exits 0 without output for any path that is not a SKILL.md, so installing this plugin globally changes nothing in projects that do not author skills. It applies the Agent Skills spec floor only (no --house), so it never imposes this repo's own conventions on someone else's skill. It never blocks: PostToolUse runs after the write, and the result is advice, not a veto.",
3
3
  "hooks": {
4
4
  "PostToolUse": [
5
5
  {