Thirty-five wrappers that stopped doing anything

Every user-invocable skill was mirrored into commands/<name>.md because Claude Code once surfaced only command files as slash commands. On 2.1.251 it surfaces skills natively, so each wrapper only registered its skill a second time. Pick a fixture and read what the model actually received.

1. Three fixtures, one request body

prompt/ork:glyph hello world through claude -p, model = loopback stub
first model request
ork:glyph in system prompt / tool descriptions
system prompt size

All three are byte-identical in what reaches the model. The duplication lived only in the palette and in claude plugin details (Skills (141) for 106 on disk, /ork:glyph three times), which cost no tokens but poisoned every count read from it.

2. What ships now

plugins/ork/ ├── skills/<name>/SKILL.md 106, surfaced by CC as /ork:<name> natively ├── .claude-plugin/plugin.json no `commands` key, no commands/ dir at the default path └── .cursor-plugin/ ├── plugin.json "commands": "./.cursor-plugin/commands/" └── commands/<name>.md 35 wrappers, Cursor host only

Cursor's loader reads its own manifest's commands path; CC's default scan looks only at commands/, which no longer exists. The frontmatter-passthrough gate now reads the Cursor path, so the wrappers stay correct for the one host that uses them.

3. The tripwire, pointed the other way

npm run verify:cc-commands used to read a loader debug counter that stopped existing before 2.1.251 (it reported "cannot observe" against the current binary, which is how this was found). It now drives the wrapper-free plugin through the stub and asserts the expansion tag in the first request: exit 0 while CC surfaces skills natively, exit 1 the day it stops, exit 2 when it cannot observe.