Reinventing.AI
Claude Code plugin-authoring skill for function hook plugins
Agent OperationsSeptember 6, 2026• 9 min read

What /plugin-authoring Unlocks in Claude Code: Plugins From a Sentence

Turn on the function hooks preview and a new built-in skill appears in the slash command list. It carries the contract for the whole plugin system, so a one-paragraph description becomes a working plugin that can block, rewrite, draw, ask, speak, and register tools. This is what it knows, what it can build, and how to work with it.

Turning it on, briefly

The skill is gated behind CLAUDE_CODE_ENABLE_FUNCTION_HOOKS=1 on Claude Code 2.1.260 or later. In the desktop app that means one block in ~/.claude/settings.json:

~/.claude/settings.json
{
  "env": {
    "CLAUDE_CODE_ENABLE_FUNCTION_HOOKS": "1"
  }
}

Type / in a session and plugin-authoring is in the list. The full setup, the plugin folder layout, and a tested plugin to copy are in the secret redactor install guide. The background on hooks themselves is in the complete hooks guide.

What the skill is

Inside the 2.1.260 binary the skill describes itself as the way to "write or debug a Claude Code plugin made of function hooks." It is not a code generator bolted on the side; it is an orientation note that loads into the session before Claude writes a plugin, and it tells Claude four things: what a function hook plugin is, where the exact contract for the running build is written down, how to run a plugin under development, and where the engine reports what it refused. Ray Amjad's September 2026 walkthrough shows the effect: one sentence describing a transcript secret redactor produced a working 300-line plugin, and a request for a deployment status row produced a live panel beneath the prompt with a hide button.

The contract the skill hands Claude is short enough to state:

  • A plugin is a folder with a manifest. Its function hooks live in one module named by hooks/hooks.json under modules, exporting register(on, options).
  • Every hook has the shape ($, e, next). $ is the engine interface, e is the event's input as a plain value, and next(e) continues to the other plugins and then the engine. Returning without calling next answers for itself; calling next with a changed event rewrites what the rest of the chain sees.
  • The module runs in an environment of its own, with no DOM and no Node. Everything outside it is reached through $. JSX is available with h as the factory.
  • The types are the reference. /plugin-types writes them from the running build, and the skill tells Claude not to guess at an event's input or a method on $.

What it unlocks

The events cover tool calls and their descriptions, the prompt as submitted, the system prompt's sections, what the interface draws, the turn's start and completion, the session's start, skills, and subagents. The engine interface adds the verbs. Together they make the following buildable from a description, and several were built on camera in the video or verified by community testers on the proposal thread.

CapabilityPrimitiveExample
Guard a tooltool.call returning denyRefuse destructive database commands or force pushes, with the reason sent to the model
Rewrite a tool calltool.call with next and a changed eventSwap npm for pnpm, add a flag, route a fetch through a proxy
Answer a tool yourselftool.call returning resultServe a cached page instead of refetching; replace the built-in search with a preferred provider
Rewrite or drop a promptprompt.submitRedact secrets; add context from a knowledge base; refuse a prompt with a reason
Draw in the interfaceui.render with $.ui.resolve and JSXA deployment status row with stage and elapsed time and a hide button; hidden values revealed on hover in the desktop app
Ask the user$.ui.askOffer to split a file that has grown past a thousand lines before editing it; gate a newsletter send behind a confirmation
Register a tool the model can call$.tool.register plus a matched tool.call hookA tool listed as mcp__<plugin>__<name> that the plugin serves itself
Call a model from a hook$.model.complete, classify, forkSummarise the finished turn with a small model, then speak it with $.audio.speak
Wake a quiet sessionsession.start plus $.clock.every and $.prompt.submitAn inbox folder watcher that turns dropped text files into prompts, verified by a community proof of concept
Remember across sessions$.storeCounters, caches, and preferences; not secrets, since the store is a file on disk
See everythingon("*")One function that forwards every event to an audit log
Show state without a turn$.ui.status, $.ui.toast, $.ui.logA pinned status line, a passing notice, a dim transcript line that the model never reads

Preview, with the rough edges stated

Function hooks have not shipped. The proposal is open, the API is marked early access in its own declarations file, and community testers reported that a hook which throws is skipped silently, that some methods listed in the declarations were not wired at runtime in 2.1.261, and that a plugin has to sit in the user level skills folder to load. Expect the skill's output to need a validate and reload loop, not a one-shot.

Six prompts to try

Each of these is the whole message. The skill prefers an outcome and a constraint over an implementation. Asking it to interview first, as the video does for the deployment row, produces better plugins for anything with a visual component.

Chat
/plugin-authoring Make a plugin that blocks any Bash command which deletes a Supabase project or branch, drops a table, or force pushes without a lease. Deny with a one-line reason the model can act on. Log every deny with $.ui.log.
Chat
/plugin-authoring Make a plugin that rewrites every Bash command starting with npm to use pnpm instead, and shows a toast the first time it does so in a session.
Chat
/plugin-authoring Make a plugin that caches WebFetch results in $.store for one hour, keyed by URL, and answers the tool call from the cache when a fresh copy exists. Include a way to bypass the cache when the prompt says "refetch".
Chat
/plugin-authoring Interview me first, then build a plugin that shows the current Vercel deployment for this repo in a row under the prompt: stage, elapsed time, and a button to hide the row. Keep finished deploys visible for an hour.
Chat
/plugin-authoring Make a plugin that asks me with $.ui.ask whether to split a file into smaller modules whenever an Edit or Write targets a file longer than 1,000 lines, and passes the edit through untouched if I say no.
Chat
/plugin-authoring On turn.complete, send the turn's answer to a Haiku model for a two sentence summary and speak it with $.audio.speak. Skip turns shorter than 200 characters.

The video's closing suggestion is the one with the most leverage: point the skill at an existing CLAUDE.md and ask which of its rules could become hooks. A rule that lives in a hook no longer depends on the model's attention.

The working loop

  1. Describe the outcome with /plugin-authoring. Claude reads the skill, runs /plugin-types if the declarations are stale, and writes the folder.
  2. Validate with the bundled binary: claude plugin validate <folder> --json. The notes list what the module hooks and which $ calls it makes, which is the quickest check that the engine sees what was meant.
  3. Load with /reload-plugins in the session, or claude --plugin-dir <folder> in a terminal, where saving a file reloads the module.
  4. Read the debug log when nothing seems to happen. Anthropic's note is blunt that a plugin that seems to do nothing has usually been told why there: a module it did not load, a hook that threw or overran its budget, a drawing that did not validate.
  5. Share the folder through a git repository or a private marketplace once it holds. Older builds ignore the modules key, so the rest of the plugin still loads for teammates who have not turned the preview on.

FAQ

Why is /plugin-authoring not in my slash command list?+

It is gated behind the function hooks preview. Set CLAUDE_CODE_ENABLE_FUNCTION_HOOKS to 1, most simply through the env key in the user settings file, and the skill appears in the slash command list. Claude Code 2.1.260 or later is required.

Does the skill write plugins for the terminal or the desktop app?+

Both. The plugin runs inside the Claude Code binary, which the terminal and the desktop app share. Drawing hooks receive a surface field that says whether the terminal or the desktop is rendering, and the element tables differ per surface, so a plugin that draws should check which one it is on.

Can a plugin the skill writes be shared with a team?+

Yes. A plugin is a folder with a manifest, and Anthropic's plugin documentation covers distributing plugins through a git repository or a private marketplace. A team member needs the same preview flag set to load the function hook module; older builds skip the modules key and load the rest of the plugin.

Sources

Agent Ops Club by Reinventing.AI

Reading about AI agents is step one.Running them for your business is the Club.

8 open source AI Employees, the 45 lesson Agent Ops Masterclass, and 22 premium systems you can customize, deploy for clients, and charge for under a resale license.

Get Lifetime for $499See what is inside →

Pro is $99 a month or $349 a year. Lifetime is $499 until October 31, then $999.