Individual skill
plugin-authoring
Make a mod: a change to Claude's own interface or behaviour, such as a panel or pane that stays beside the chat and updates, a band, status line, toast, slash command, or hook on tool calls. Use to make, change or debug a mod or its hooks module.
Anthropic/claude-code/skills/plugin-authoring/SKILL.md
Source commit a2d33761e49b98f6ec1b48f12143264eb9b4ff4f
What was checked
- Matches the observed repository HEAD
- Yes
- Scanner rules are current
- Yes
- Repository scan complete
- No
- Skill scan complete
- No
- Observed behavior
- Network or broad shell
- Last checked
- Nov 10, 2026
These are observations at the recorded commit, not a guarantee of safety. Review the source before running it.
Install this skill
Choose an agent in your Stack or copy a command below. Commands fetch the pinned commit and copy only this skill directory. Existing destinations are refused. Copying a command does not install anything.
An install command is unavailable: current rules, complete repository and skill scans, an eligible behavior level and a permitted license are required.
Repository context
- Repository stars (not skill ratings)
- 71,166
- Repository last updated
- Nov 10, 2026
- License
- CC0-1.0
Observed agent integration: No specific integration evidence. Standard SKILL.md installation does not imply verified compatibility.
- ai Repository topic
- anthropic Repository topic
- chatbot Repository topic
- chatgpt Repository topic
- claude Repository topic
- claude-code Repository topic
- codex Repository topic
- gemini Repository topic
- generative-ai Repository topic
- google Repository topic
- engineering Derived category
Files and excerpt
File metadata and permitted, redacted excerpts come from the recorded scan. Source links are pinned to that commit.
Browse files
SKILL.mdcore · 10,684 bytesSKILL.mdcore · 10,684 bytesexamples/band-state.d.tsruns · 176 bytesexamples/band.tsxruns · 1,447 bytesexamples/pane-state.d.tsruns · 181 bytesexamples/pane.test.tsxruns · 2,128 bytesexamples/pane.tsxruns · 1,732 bytesexamples/tool-call.tsruns · 701 bytesreference.mddoc · 84,518 bytestypes/claude-code.d.tsruns · 897,072 bytes
Read excerpt
WHERE TO WRITE IT. Write each mod in its own child folder, `/Users/asgeirtj/.claude/dev-mods/a65bc9bc-4a4f-4aff-8f7a-3cc96be406ad/<mod-name>/`, three files written directly:
- `.claude-plugin/plugin.json`: `{ "name": "<mod-name>", "version": "0.1.0", "description": "<one line>" }`
- `hooks/hooks.json`: `{ "modules": ["./register.tsx"] }`, one path, relative to that file
- `hooks/register.tsx` (or `.ts`): the hooks module, `export const register: Register = (on, options) => { ... }`, the type imported from `'claude-code'`
A mod that keeps values in `$.state` has a fourth file, `types/index.d.ts`: its type contract, declaring each value in `interface PluginState` under the mod's name, named in `plugin.json` as `"types": "./types/index.d.ts"`. The module imports its value types from `'../types'`, and `claude plugin validate` holds every `$.state` key the module names to that contract.
WHERE THE TYPES ARE. The engine writes them; there is no command to run. Before the mod has loaded: `/private/tmp/claude-501/bundled-skills/2.1.321/07e00bde5f1d8749804513a46a71efb0/plugin-authoring/types/claude-code.d.ts`, this build's API and built-in tools, written as this skill loaded (this process's own folder: after a restart the next load of this skill writes and names a new one). Once the engine has loaded the mod (from this mods folder, or a `--plugin-dir` folder it hot-reloads), `<mod folder>/.claude-plugin/types/` holds the same for the editor: `claude-code/index.d.ts`, the API; `claude-code-tools/index.d.ts`, so `e.tool === "Bash"` narrows `e`; `claude-code-mcp/index.d.ts`, the MCP tools connected when the mod last reloaded; each `dependencies` plugin's contract; and a `tsconfig.json` the mod's own extends, so `tsc -p <mod folder>` type-checks it. The API file carries every event's input and result, every noun and method on `$` with its doc comment and an example, and every element's props, in about 14,000 lines: grep it for the name at hand (`'tool.call'`, `Pane: {`, `export type ToolCallResult`).
WHAT HAPPENS WHEN THE TURN ENDS. Loading this skill through the Skill tool or its slash command starts the engine's watch on the folder that holds the mod folders. The first file written under it makes the engine ask the person, once, right then: "Turn on the mods Claude writes in this session?", with `How does this work?` first, then `Turn them on` and `Not now`. That question is the switch, and the person alone answers it: no rule or hook does. In bypass, or auto while its classifier runs, nobody is asked and the first write turns it on, unless the person said `Not now` first. dontAsk neither asks nor loads. Once on, the folder joins the session's plugin folders and the mod loads when the turn ends, whole, and each later edit reloads it when the turn that made the edit ends. The answer reaches you as a notice at your next turn, which the engine may start for an enabling: enabled, with what the load came to; declined (the mods are written and load the next time this session starts); still open (dismissed or closed; asked again); or off, with the reason (nobody could be asked, as under `claude -p`; the question got no pick three times; an organization's policy; an untrusted workspace). A restart loads a folder the person enabled by itself; otherwise its watch starts the next time this skill loads, and a manifest already in the folder raises the question when that turn ends.
A reload runs `register` and `session.start` again. `$.state` (the session's) and `$.store` (across sessions) stay; the module's own variables start over. New code meets old values: `shape`, in `reference.md`.
THIS SESSION is drawn in a terminal. A pane the person opened seats at any width; one opened unasked seats from 144 columns, or 110 as `$.ui.open`'s doc says, and waits below that. Where hot reloading is off as nobody could be asked, `claude --plugin-dir <mod folder>` starts a session with the mod loaded.