@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.
@@ -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
- │ └── skills/<skill>/SKILL.md + references/*.md (+ scripts/, assets/)
52
- │ (commands/*.md too — but never named after a skill)
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 what
69
- the installers touch. A skill is text an agent executes, so "review before
70
- installing" belongs in writing.
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 publish if applicable (human 2FA the first time); e2e `npx <name>@<ver>`
299
- from a non-repo cwd.
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 13-item audit checklist
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 13-item audit checklist
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