@ssheleg/make-skill 0.8.1 → 0.9.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 +73 -0
- package/README.md +46 -16
- package/SECURITY.md +15 -3
- package/cursor/rules/make-skill.mdc +24 -0
- package/package.json +2 -3
- package/plugins/make-skill/.claude-plugin/plugin.json +1 -1
- package/plugins/make-skill/agents/skill-auditor.md +46 -0
- package/plugins/make-skill/commands/skill-audit.md +31 -0
- package/plugins/make-skill/hooks/hooks.json +19 -0
- package/plugins/make-skill/hooks/skill-md-audit.sh +43 -0
- package/plugins/make-skill/skills/make-skill/SKILL.md +79 -50
- package/plugins/make-skill/skills/make-skill/assets/agent.template.md +33 -0
- package/plugins/make-skill/skills/make-skill/assets/command.template.md +32 -0
- package/plugins/make-skill/skills/make-skill/assets/hooks.template.json +32 -0
- package/plugins/make-skill/skills/make-skill/references/authoring.md +7 -0
- package/plugins/make-skill/skills/make-skill/references/distribution.md +23 -8
- package/plugins/make-skill/skills/make-skill/references/host-capabilities.md +218 -0
- package/plugins/make-skill/skills/make-skill/references/retrofit.md +25 -2
- package/plugins/make-skill/skills/make-skill/scripts/audit_skill.py +378 -0
- package/templates/README.md +0 -34
- /package/{templates → plugins/make-skill/skills/make-skill/assets}/SKILL.template.md +0 -0
- /package/{templates → plugins/make-skill/skills/make-skill/assets}/marketplace.template.json +0 -0
- /package/{templates → plugins/make-skill/skills/make-skill/assets}/plugin.template.json +0 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: agent-name-here
|
|
3
|
+
description: What this agent does and WHEN the main thread should delegate to it. Third person, concrete triggers — the same selection problem a skill description solves.
|
|
4
|
+
tools: Read, Grep, Glob, Bash
|
|
5
|
+
# Optional: model, effort, maxTurns, disallowedTools, memory, background,
|
|
6
|
+
# isolation: "worktree" (only value accepted)
|
|
7
|
+
# REJECTED for plugin-shipped agents: hooks, mcpServers, permissionMode
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
You <one sentence: the single job>. You do not <the adjacent job you must refuse>.
|
|
11
|
+
|
|
12
|
+
## Procedure
|
|
13
|
+
|
|
14
|
+
1. Deterministic step first — run the bundled script rather than reasoning your
|
|
15
|
+
way to the same answer:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
python3 "${CLAUDE_PLUGIN_ROOT}/skills/SKILL_NAME/scripts/SCRIPT.py" <target>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
No `${CLAUDE_PLUGIN_ROOT}`? You are not running as a Claude Code plugin —
|
|
22
|
+
find the script under the skill directory you were loaded from. Interpreter
|
|
23
|
+
missing? Say so once and do the checks by hand from the reference; a missing
|
|
24
|
+
tool changes how you work, not whether you report.
|
|
25
|
+
|
|
26
|
+
2. Judgement steps, each naming the reference file that carries the rules. Read
|
|
27
|
+
the file; do not reconstruct it from memory.
|
|
28
|
+
|
|
29
|
+
## Output
|
|
30
|
+
|
|
31
|
+
Exactly what the caller needs and nothing else — a table, a verdict, or a patch.
|
|
32
|
+
Evidence for every claim (`file:line` or command output). Finish with ONE next
|
|
33
|
+
action and stop.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "One line the user sees in the / menu — what it does, not how it works"
|
|
3
|
+
argument-hint: "[what to pass] [--flag]"
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
<!--
|
|
7
|
+
Two rules this skeleton exists to enforce:
|
|
8
|
+
|
|
9
|
+
1. NEVER name this file after a skill directory in the same plugin. Commands
|
|
10
|
+
are skills now: `commands/x.md` beside `skills/x/` registers /x twice, the
|
|
11
|
+
skill wins, and the command is unreachable always-on token cost.
|
|
12
|
+
2. ALWAYS quote `argument-hint`. A bare [a | b] is a YAML flow sequence; one
|
|
13
|
+
comma inside it drops the whole frontmatter block, leaving a command with
|
|
14
|
+
no description and no warning.
|
|
15
|
+
-->
|
|
16
|
+
|
|
17
|
+
Do <the task> for `$ARGUMENTS`.
|
|
18
|
+
|
|
19
|
+
1. The deterministic part, by script:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
python3 "${CLAUDE_PLUGIN_ROOT}/skills/SKILL_NAME/scripts/SCRIPT.py" $ARGUMENTS
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Not running as a Claude Code plugin, so `${CLAUDE_PLUGIN_ROOT}` is unset? The
|
|
26
|
+
script is in the skill directory this file was installed beside. No
|
|
27
|
+
interpreter? Fall back to the manual procedure in the reference and say that
|
|
28
|
+
you did.
|
|
29
|
+
|
|
30
|
+
2. The judgement part, from `references/FILE.md`.
|
|
31
|
+
|
|
32
|
+
3. Report: what was checked, what the verdict is, and ONE next action.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{
|
|
2
|
+
"description": "PLUGIN_NAME — one sentence on what these hooks do, and the sentence that matters to a reviewer: when they no-op. A globally installed plugin must be invisible in projects that do not use it.",
|
|
3
|
+
"hooks": {
|
|
4
|
+
"PostToolUse": [
|
|
5
|
+
{
|
|
6
|
+
"matcher": "Write|Edit|MultiEdit",
|
|
7
|
+
"hooks": [
|
|
8
|
+
{
|
|
9
|
+
"type": "command",
|
|
10
|
+
"shell": "bash",
|
|
11
|
+
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/HOOK_SCRIPT.sh\"",
|
|
12
|
+
"timeout": 20,
|
|
13
|
+
"statusMessage": "What the user sees while this runs"
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
],
|
|
18
|
+
"SessionStart": [
|
|
19
|
+
{
|
|
20
|
+
"matcher": "startup|resume",
|
|
21
|
+
"hooks": [
|
|
22
|
+
{
|
|
23
|
+
"type": "command",
|
|
24
|
+
"shell": "bash",
|
|
25
|
+
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/SESSION_SCRIPT.sh\"",
|
|
26
|
+
"timeout": 15
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
]
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -180,6 +180,13 @@ if written carelessly.
|
|
|
180
180
|
- **Vision is available**: rendering an input to images and letting the agent look
|
|
181
181
|
at it beats describing a layout in prose.
|
|
182
182
|
|
|
183
|
+
Worked example: this skill's own `scripts/audit_skill.py`. It is stdlib-only so
|
|
184
|
+
it runs wherever the skill landed, prints `file:line` evidence rather than
|
|
185
|
+
verdicts, handles its own missing-file and bad-frontmatter cases, and its first
|
|
186
|
+
run flagged a false positive on the very document that teaches the anti-pattern —
|
|
187
|
+
which is why it now ignores quoted spans. Hooks, subagents and commands that wrap
|
|
188
|
+
it, plus the fallbacks they owe, are in `references/host-capabilities.md`.
|
|
189
|
+
|
|
183
190
|
## Evaluation and iteration — evals before prose
|
|
184
191
|
|
|
185
192
|
**Build the evaluations before writing extensive documentation.** Otherwise the
|
|
@@ -48,10 +48,13 @@ the shape from `ssheleg/super-ux`:
|
|
|
48
48
|
├── .claude-plugin/marketplace.json # root manifest, plugins[0].source: ./plugins/<name>
|
|
49
49
|
├── plugins/<name>/
|
|
50
50
|
│ ├── .claude-plugin/plugin.json # ONLY the manifest lives in .claude-plugin/
|
|
51
|
-
│
|
|
52
|
-
│
|
|
51
|
+
│ ├── skills/<skill>/SKILL.md + references/*.md + scripts/ + assets/
|
|
52
|
+
│ │ # skeletons live HERE, not at the repo root:
|
|
53
|
+
│ │ # only the skill dir travels on every channel
|
|
54
|
+
│ ├── hooks/hooks.json + *.sh # Claude Code only — see host-capabilities.md
|
|
55
|
+
│ ├── agents/*.md # Claude Code only
|
|
56
|
+
│ └── commands/*.md # never named after a skill
|
|
53
57
|
├── cursor/rules/*.mdc # if agent-rules make sense for Cursor
|
|
54
|
-
├── templates/*.md # skeletons (NEVER name one SKILL.md)
|
|
55
58
|
├── bin/<name>.js + package.json # npx installer (zero-dep Node)
|
|
56
59
|
├── test/validate.py # consistency validator (stdlib only)
|
|
57
60
|
├── test/evals/ # triggers.json + scenarios.json (data, run by a human)
|
|
@@ -59,15 +62,23 @@ the shape from `ssheleg/super-ux`:
|
|
|
59
62
|
├── install.sh # POSIX fallback
|
|
60
63
|
├── README.md (English-first), CHANGELOG.md, LICENSE (MIT)
|
|
61
64
|
├── CONTRIBUTING.md + SECURITY.md # public repo: how to check work, where to report
|
|
65
|
+
├── SKILL-CARD.md # the enterprise registry entry + risk-table pass
|
|
62
66
|
└── docs/superpowers/{specs,plans}/
|
|
63
67
|
```
|
|
64
68
|
|
|
65
69
|
**Public-repo floor** (validator-enforced): a README saying what it does before
|
|
66
70
|
how to install it, **English-first** — Russian belongs in trigger phrases, where
|
|
67
71
|
it changes whether the skill fires; `CONTRIBUTING.md` with the offline commands
|
|
68
|
-
that verify a change; `SECURITY.md` naming a private reporting channel and
|
|
69
|
-
|
|
70
|
-
|
|
72
|
+
that verify a change; `SECURITY.md` naming a private reporting channel and every
|
|
73
|
+
path that executes, hooks first; `SKILL-CARD.md` answering the enterprise
|
|
74
|
+
registry fields and the risk table honestly. A skill is text an agent executes,
|
|
75
|
+
so "review before installing" belongs in writing — and anything that runs
|
|
76
|
+
without being asked belongs at the top of it.
|
|
77
|
+
|
|
78
|
+
**What travels where.** Only `skills/<skill>/` reaches non-Claude channels, so
|
|
79
|
+
scripts and skeletons live inside it. `hooks/`, `agents/` and `commands/` reach
|
|
80
|
+
Claude Code alone: they are accelerators, and the skill body owes each one a
|
|
81
|
+
written fallback (`references/host-capabilities.md`).
|
|
71
82
|
|
|
72
83
|
**Version sync (hard rule):** `marketplace.json`, `plugin.json`, `package.json`
|
|
73
84
|
and the top CHANGELOG entry carry the SAME semver, bumped together; the validator
|
|
@@ -295,8 +306,12 @@ claude plugin update <name>@<name> # full id required
|
|
|
295
306
|
4. Conventional commit; push; confirm CI `success`; tag `v<ver>` and push the tag;
|
|
296
307
|
`gh release create` from the CHANGELOG section (or let the release workflow
|
|
297
308
|
below do it).
|
|
298
|
-
5. npm
|
|
299
|
-
|
|
309
|
+
5. **npm publishes itself** once CI publishing is armed (launch checklist step
|
|
310
|
+
9): the `v*` tag triggers it, with provenance, skipping a version the
|
|
311
|
+
registry already has. A manual `npm publish` here is the fallback for a repo
|
|
312
|
+
that has not armed it yet — not the normal path, and leaving it as the
|
|
313
|
+
normal path is how a family ends up with a release step nobody performs and
|
|
314
|
+
everybody documents. Then e2e `npx <name>@<ver>` from a non-repo cwd.
|
|
300
315
|
6. **Refresh THIS machine's global installs — always, as Definition of Done:**
|
|
301
316
|
`claude plugin marketplace update <name>` → `claude plugin update
|
|
302
317
|
<name>@<name>` → `npx skills update <name> --global --yes && rm -f
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# Host capabilities — hooks, agents, commands, and what happens without them
|
|
2
|
+
|
|
3
|
+
**Load this when:** deciding whether a skill should ship a hook, a subagent, a
|
|
4
|
+
command, an MCP server or a script — or when writing the degradation clauses that
|
|
5
|
+
keep it working where those do not exist.
|
|
6
|
+
|
|
7
|
+
Sources: [Claude Code hooks reference](https://code.claude.com/docs/en/hooks) and
|
|
8
|
+
the [plugins reference](https://code.claude.com/docs/en/plugins-reference)
|
|
9
|
+
(*read 2026-08-03, Claude Code 2.1.212*), plus `references/claude-code-plugin.md`
|
|
10
|
+
for the manifest side.
|
|
11
|
+
|
|
12
|
+
## Contents
|
|
13
|
+
|
|
14
|
+
- The rule: accelerator, never precondition
|
|
15
|
+
- What to reach for, and what it costs
|
|
16
|
+
- Hooks — events, handlers, matchers, exit codes
|
|
17
|
+
- Writing a hook that is invisible when idle
|
|
18
|
+
- Subagents
|
|
19
|
+
- Commands
|
|
20
|
+
- Scripts
|
|
21
|
+
- MCP servers and other plugins as dependencies
|
|
22
|
+
- The three degradation cases, written out
|
|
23
|
+
- Checklist
|
|
24
|
+
|
|
25
|
+
## The rule: accelerator, never precondition
|
|
26
|
+
|
|
27
|
+
Everything on this page exists only inside Claude Code. A skill that *needs* one
|
|
28
|
+
of them is broken on Cursor, Codex, the skills CLI, the Claude API and claude.ai
|
|
29
|
+
— which is most of where skills run. So:
|
|
30
|
+
|
|
31
|
+
> **Every host capability is an accelerator with a stated fallback. The skill
|
|
32
|
+
> must complete its job without it, more slowly and with less polish.**
|
|
33
|
+
|
|
34
|
+
"Stated" is the operative word: the fallback goes in the skill body, in the words
|
|
35
|
+
the agent will read at the moment the capability is missing. A fallback you know
|
|
36
|
+
but did not write is not a fallback.
|
|
37
|
+
|
|
38
|
+
## What to reach for, and what it costs
|
|
39
|
+
|
|
40
|
+
| Capability | Buys you | Costs | Reach for it when |
|
|
41
|
+
|---|---|---|---|
|
|
42
|
+
| `scripts/` | determinism, and output instead of code in context | none until run | the agent re-derives the same logic every run |
|
|
43
|
+
| `hooks/` | enforcement at the moment of the action | runs on the user's machine, every matching tool call | a rule matters more than an instruction can guarantee |
|
|
44
|
+
| `agents/` | a job done in a separate context window | ~100 always-on tokens per agent | the work would otherwise crowd out the main thread |
|
|
45
|
+
| `commands/` | a user-typed entry point with arguments | ~50–100 always-on tokens | a human, not the model, decides when it runs |
|
|
46
|
+
| `mcpServers` | live capability (network, credentials, a process) | a server to install, auth to hold | instructions cannot do it — see `references/mcp.md` |
|
|
47
|
+
| `lspServers`, `monitors`, `themes`, `outputStyles`, `workflows` | narrow, real, and rarely what a skill wants | always-on where they load | you can name the user who asked for it |
|
|
48
|
+
| `userConfig` | values prompted at enable time | a prompt in everyone's install | the skill genuinely cannot guess (a path, a workspace id) |
|
|
49
|
+
|
|
50
|
+
Everything in that table is Claude-Code-only. `scripts/` is the exception that
|
|
51
|
+
travels: it lives inside the skill directory, so every channel ships it.
|
|
52
|
+
|
|
53
|
+
## Hooks — events, handlers, matchers, exit codes
|
|
54
|
+
|
|
55
|
+
Plugin hooks live in `hooks/hooks.json` at the plugin root (auto-discovered; a
|
|
56
|
+
manifest key is only needed for a custom path). Shape:
|
|
57
|
+
|
|
58
|
+
```json
|
|
59
|
+
{ "hooks": { "PostToolUse": [ { "matcher": "Write|Edit",
|
|
60
|
+
"hooks": [ { "type": "command", "shell": "bash",
|
|
61
|
+
"command": "\"${CLAUDE_PLUGIN_ROOT}/hooks/check.sh\"",
|
|
62
|
+
"timeout": 20 } ] } ] } }
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Events worth a skill's attention** (the full set is larger):
|
|
66
|
+
|
|
67
|
+
| Event | Fires | Blocks? | Use for |
|
|
68
|
+
|---|---|---|---|
|
|
69
|
+
| `SessionStart` | session begins/resumes (`startup\|resume\|clear\|compact\|fork`) | no | seeding state, `additionalContext` |
|
|
70
|
+
| `UserPromptSubmit` | before the model sees the prompt | yes | injecting context, refusing a prompt |
|
|
71
|
+
| `PreToolUse` | before a tool runs | yes — `permissionDecision: deny` | guarding a destructive action |
|
|
72
|
+
| `PostToolUse` | after a tool succeeds | no | validating what was just written |
|
|
73
|
+
| `Stop` / `SubagentStop` | a turn or subagent finishes | yes | completion gates |
|
|
74
|
+
| `SessionEnd` | session ends | no | cleanup (1.5s shared budget) |
|
|
75
|
+
|
|
76
|
+
**Handler types:** `command` (a script — the portable one), `http`, `mcp_tool`,
|
|
77
|
+
`prompt`, `agent`. `command` takes `shell` (`bash`/`powershell`) in shell form,
|
|
78
|
+
or `args` for exec form with no shell tokenization.
|
|
79
|
+
|
|
80
|
+
**Matchers** are exact strings or `A|B` lists; anything with other characters is
|
|
81
|
+
an unanchored regex. Tool names are what you match (`Bash`, `Write`,
|
|
82
|
+
`mcp__server__tool`). A plugin's OWN MCP server is matched as
|
|
83
|
+
`mcp__plugin_<plugin>_<server>__<tool>`, and an `mcp_tool` hook names the server
|
|
84
|
+
as `plugin:<plugin>:<server>` — the bare key never fires. Narrow further with
|
|
85
|
+
`if`, a permission rule: `"if": "Bash(git commit *)"`.
|
|
86
|
+
|
|
87
|
+
**Exit codes are the contract:**
|
|
88
|
+
|
|
89
|
+
| Exit | Meaning |
|
|
90
|
+
|---|---|
|
|
91
|
+
| `0` | success; stdout is parsed as JSON for structured output |
|
|
92
|
+
| `2` | blocking error; **stderr goes to the model**, stdout is ignored |
|
|
93
|
+
| other | non-blocking error; the action proceeds, the transcript shows a hook error |
|
|
94
|
+
|
|
95
|
+
Structured output on exit 0: `systemMessage` (shown to the user),
|
|
96
|
+
`additionalContext` (injected for the model), `decision: "block"` with `reason`,
|
|
97
|
+
`permissionDecision` for `PreToolUse`, `suppressOutput`, `continue: false`.
|
|
98
|
+
|
|
99
|
+
**Environment:** `${CLAUDE_PLUGIN_ROOT}`, `${CLAUDE_PLUGIN_DATA}`,
|
|
100
|
+
`${CLAUDE_PROJECT_DIR}` substitute in the command and are exported. Quote them —
|
|
101
|
+
a space in the install path otherwise splits the command.
|
|
102
|
+
|
|
103
|
+
## Writing a hook that is invisible when idle
|
|
104
|
+
|
|
105
|
+
A plugin installed globally fires its hooks in every project. Two rules keep that
|
|
106
|
+
from being a nuisance, and both belong in the `description` field of
|
|
107
|
+
`hooks.json`, where a reviewer reads them:
|
|
108
|
+
|
|
109
|
+
1. **Exit 0 with no output the moment the event is not yours.** Wrong tool, wrong
|
|
110
|
+
path, no project marker file → `exit 0` before doing any work. This is why
|
|
111
|
+
`agent-sync`'s hooks open by checking for `.claude/agent-sync.json`.
|
|
112
|
+
2. **Degrade instead of erroring.** No interpreter, missing script, unparsable
|
|
113
|
+
input → `exit 0` silently. A hook that reports its own absence as a failure
|
|
114
|
+
trains the user to disable hooks.
|
|
115
|
+
|
|
116
|
+
Block (`exit 2`) only where blocking is the point, and only on `PreToolUse` or
|
|
117
|
+
another event that actually blocks. On `PostToolUse` the write already happened;
|
|
118
|
+
advice via `systemMessage` is worth more than a veto that costs a turn.
|
|
119
|
+
|
|
120
|
+
Ship the script with a shebang and `chmod +x`, and keep it dependency-free —
|
|
121
|
+
`jq` is not installed everywhere, and a hook is a bad place to discover that.
|
|
122
|
+
|
|
123
|
+
## Subagents
|
|
124
|
+
|
|
125
|
+
`agents/*.md` with `name` and `description`; optional `model`, `effort`,
|
|
126
|
+
`maxTurns`, `tools`, `disallowedTools`, `skills`, `memory`, `background`,
|
|
127
|
+
`isolation: "worktree"`. **`hooks`, `mcpServers` and `permissionMode` are
|
|
128
|
+
rejected** for plugin-shipped agents. They appear as `<plugin>:<agent>`.
|
|
129
|
+
|
|
130
|
+
A subagent earns its always-on cost when the work is *voluminous and separable* —
|
|
131
|
+
an audit across twenty skills, a survey, a long verification — because its output
|
|
132
|
+
is a summary while its reading stays in its own context. It does not earn it when
|
|
133
|
+
the main thread needs the intermediate detail anyway.
|
|
134
|
+
|
|
135
|
+
Fallback: on any other host there are no subagents. The skill body must describe
|
|
136
|
+
the same procedure inline, so a Cursor session does the work in one context.
|
|
137
|
+
|
|
138
|
+
## Commands
|
|
139
|
+
|
|
140
|
+
`commands/*.md`, frontmatter `description` plus a **quoted** `argument-hint`;
|
|
141
|
+
body receives `$ARGUMENTS`. Two rules cost a debugging round each:
|
|
142
|
+
|
|
143
|
+
- **Never name a command after a skill in the same plugin.** Commands are skills
|
|
144
|
+
now: both claim `/<name>`, the skill wins, the command is unreachable always-on
|
|
145
|
+
cost visible only in `claude plugin details`.
|
|
146
|
+
- **Quote `argument-hint`.** Bare `[a | b]` is a YAML flow sequence; a comma
|
|
147
|
+
inside it drops the entire frontmatter block, leaving a command with no
|
|
148
|
+
description and no warning.
|
|
149
|
+
|
|
150
|
+
Fallback: elsewhere there is no `/command`. The skill's own description must
|
|
151
|
+
carry the trigger phrases that reach the same behavior in plain language.
|
|
152
|
+
|
|
153
|
+
## Scripts
|
|
154
|
+
|
|
155
|
+
The one accelerator that travels. Keep it inside the skill directory
|
|
156
|
+
(`scripts/`), stdlib-only, and invoke it by a path the agent can actually
|
|
157
|
+
resolve:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
python3 "${CLAUDE_PLUGIN_ROOT}/skills/<skill>/scripts/x.py" <target> # Claude Code
|
|
161
|
+
python3 ~/.agents/skills/<skill>/scripts/x.py <target> # skills CLI
|
|
162
|
+
python3 ~/.claude/skills/<skill>/scripts/x.py <target> # plain install
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
**The absolute path differs per channel**, so the instruction that survives is
|
|
166
|
+
"run the script from the skill directory you just read this file from", with
|
|
167
|
+
`${CLAUDE_PLUGIN_ROOT}` offered as the Claude Code convenience. State the
|
|
168
|
+
no-interpreter fallback too: the manual procedure, in the reference that the
|
|
169
|
+
script implements.
|
|
170
|
+
|
|
171
|
+
## MCP servers and other plugins as dependencies
|
|
172
|
+
|
|
173
|
+
A skill may *use* an MCP server or a sibling skill; it may not *require* one
|
|
174
|
+
silently. Declare it in frontmatter `compatibility`, and write the branch:
|
|
175
|
+
|
|
176
|
+
- **Server present** → name the tool by discovery, never a hardcoded string
|
|
177
|
+
(`references/mcp.md`).
|
|
178
|
+
- **Server absent** → say so once, name what is degraded, and continue with the
|
|
179
|
+
manual path. Never loop on 401s; interactive auth is a human step.
|
|
180
|
+
- **Sibling skill absent** (`super-ux`, `agent-sync`, …) → the dependent stage
|
|
181
|
+
still runs, with its quality reduced and that reduction stated. A pipeline that
|
|
182
|
+
refuses to start because an optional companion is missing is a broken pipeline.
|
|
183
|
+
|
|
184
|
+
Claude Code's manifest `dependencies` field can express a hard requirement
|
|
185
|
+
between plugins. Use it only when the skill genuinely cannot function — and know
|
|
186
|
+
that it means nothing on any other host.
|
|
187
|
+
|
|
188
|
+
## The three degradation cases, written out
|
|
189
|
+
|
|
190
|
+
Put these in the skill body, in this shape:
|
|
191
|
+
|
|
192
|
+
```markdown
|
|
193
|
+
## Degradation
|
|
194
|
+
|
|
195
|
+
- **Not Claude Code** (Cursor, Codex, skills CLI, API): hooks, subagents and
|
|
196
|
+
`/commands` do not exist. Run <procedure> inline; the bundled `scripts/` still
|
|
197
|
+
work wherever `python3` does.
|
|
198
|
+
- **Recommended plugin absent** (<name>): <what is lost>. Continue with
|
|
199
|
+
<manual path>, and say once that the result is <weaker in this way>.
|
|
200
|
+
- **Tool or interpreter absent** (`python3`, `gh`, `npm`, an MCP server): state
|
|
201
|
+
it once, fall back to <the by-hand procedure>, never retry in a loop.
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
Three lines, one per axis. They are what a reader checks before installing, and
|
|
205
|
+
what the agent reads at the exact moment something is missing.
|
|
206
|
+
|
|
207
|
+
## Checklist
|
|
208
|
+
|
|
209
|
+
- [ ] Every host capability the skill ships has a written fallback in the body
|
|
210
|
+
- [ ] `hooks.json` `description` says when the hooks no-op
|
|
211
|
+
- [ ] Hook scripts exit 0 silently on "not mine" and on a missing interpreter
|
|
212
|
+
- [ ] `PostToolUse` advises (`systemMessage`), `PreToolUse` blocks — not the reverse
|
|
213
|
+
- [ ] Hook commands quote `"${CLAUDE_PLUGIN_ROOT}"` and set a `timeout`
|
|
214
|
+
- [ ] Hook scripts are executable, have a shebang, and need no `jq`
|
|
215
|
+
- [ ] No command named after a skill; every `argument-hint` quoted
|
|
216
|
+
- [ ] Plugin agents carry no `hooks` / `mcpServers` / `permissionMode`
|
|
217
|
+
- [ ] Scripts are stdlib-only, inside the skill dir, invoked by a resolvable path
|
|
218
|
+
- [ ] MCP and sibling-skill dependencies declared in `compatibility` with a branch
|
|
@@ -6,11 +6,27 @@ standard — including the no-argument `/make-skill` path, where a `SKILL.md`,
|
|
|
6
6
|
|
|
7
7
|
## Contents
|
|
8
8
|
|
|
9
|
+
- Run the script first
|
|
9
10
|
- How to report (the only acceptable verdict format)
|
|
10
|
-
- The
|
|
11
|
+
- The 14-item audit checklist
|
|
11
12
|
- Personal skills — the short form
|
|
12
13
|
- After the audit
|
|
13
14
|
|
|
15
|
+
## Run the script first
|
|
16
|
+
|
|
17
|
+
The mechanical half is deterministic — do not reason your way through it:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
python3 "${CLAUDE_PLUGIN_ROOT}/skills/make-skill/scripts/audit_skill.py" <skill-dir> --house
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`${CLAUDE_PLUGIN_ROOT}` is Claude Code's. On any other host the script sits at
|
|
24
|
+
`scripts/audit_skill.py` inside the make-skill directory you are reading this
|
|
25
|
+
from (`~/.agents/skills/make-skill/`, `~/.claude/skills/make-skill/`). No
|
|
26
|
+
`python3` at all? Check items 1 and 9 below by hand against
|
|
27
|
+
`references/agent-skills-spec.md` — the script implements that checklist and
|
|
28
|
+
nothing more. Either way, the judgement items are yours.
|
|
29
|
+
|
|
14
30
|
## How to report
|
|
15
31
|
|
|
16
32
|
Audit first, fix second, in the same session. One verdict per item:
|
|
@@ -25,7 +41,7 @@ about rather than executed: `python3 test/validate.py`, `claude plugin validate
|
|
|
25
41
|
… --strict`, `npx skills add <repo> --list` all produce output, and the output is
|
|
26
42
|
the evidence. Report the gap table before changing anything, then fix.
|
|
27
43
|
|
|
28
|
-
## The
|
|
44
|
+
## The 14-item audit checklist
|
|
29
45
|
|
|
30
46
|
1. **Spec floor** (`references/agent-skills-spec.md`): `name` charset + ≤64 +
|
|
31
47
|
equal to the directory + no `anthropic`/`claude` + no angle brackets;
|
|
@@ -77,6 +93,13 @@ the evidence. Report the gap table before changing anything, then fix.
|
|
|
77
93
|
`references/a2a.md`): dependency and protocol version in `compatibility`,
|
|
78
94
|
discovery instead of hardcoded tool names, the untrusted-output rule stated,
|
|
79
95
|
interactive auth handled as a human step rather than a retry loop.
|
|
96
|
+
14. **Host capabilities and their fallbacks**
|
|
97
|
+
(`references/host-capabilities.md`) if it ships a hook, subagent, command or
|
|
98
|
+
MCP server: the degradation contract written in the body for all three axes
|
|
99
|
+
(not Claude Code / recommended plugin absent / tool absent); hooks that
|
|
100
|
+
exit 0 silently when the event is not theirs; `PostToolUse` advising rather
|
|
101
|
+
than blocking; commands quoted and never named after a skill; plugin agents
|
|
102
|
+
free of `hooks`, `mcpServers` and `permissionMode`.
|
|
80
103
|
|
|
81
104
|
## Personal skills — the short form
|
|
82
105
|
|