Skip to content

Reading a plugin before you install it

A colleague shares a plugin called release-kit with you. It lists one skill, release, which cuts a release the same way in every repository, and that skill is what you want. Next to the skill, the plugin directory holds a subagent that writes release notes, a hook that runs before each shell command the agent runs, and a connection to the team’s issue tracker. In this lesson we read that plugin one part at a time and say what each part does in your sessions. The lesson ends with a decision between installing it, copying the one skill out of it and leaving it.

The plugin is invented for the course. It is in the course repository at site/examples/customizing-agents/plugins/release-kit/, next to a short Python script, inventory.py, that lists what a plugin directory holds. The script only reads files, and nothing in this lesson installs the plugin or runs its hook. Run the commands from that directory, and replace <course-repo> with the path to your copy of the course repository.

Terminal window
cd <course-repo>/site/examples/customizing-agents/plugins

Skills, subagents, hooks and Model Context Protocol (MCP) servers each work on their own in Claude Code, and a skill in ~/.claude/skills/ already reaches all your projects. A plugin is how Claude Code ships a set of them together [1]. You get the whole set with one install command, and later updates come from the same source. On disk a plugin is a directory. A manifest file in it, .claude-plugin/plugin.json, holds the plugin’s name and can hold a version and a description. Plugins can also carry other kinds of component besides the four this lesson reads.

To install a plugin, Claude Code needs to know where to fetch it from, and a marketplace tells it. That is a git repository or a local folder with a .claude-plugin/marketplace.json file, which lists plugins and their sources. After you register a marketplace, you name a plugin from it as plugin@marketplace to install it. The only marketplace Claude Code registers by itself is Anthropic’s official one, on your first interactive session [1]. A catalog that your colleagues or your employer run is a third-party one. Knowing who runs a catalog doesn’t tell you what one of its plugins does, so you review each plugin yourself [2].

The scope you pick at install time sets where the plugin is on. With user scope it is on in all your projects on this computer. Local scope keeps it to you, in one repository. Project scope writes it into the repository’s committed .claude/settings.json, and that turns it on for the whole team in that repository [1].

Whether the installed files stay the ones you read depends on the author and on the marketplace. An author who sets version in the manifest holds every install at that version until they set a new one [3]. A marketplace with auto-update turned on replaces the installed files in the background [2]. Most of Anthropic’s official marketplaces have auto-update on by default, and third-party ones have it off [4].

What a plugin costs you doesn’t depend on whether you use it. As long as it is enabled, Claude Code loads it into every session [1]. Each turn contains the names and descriptions of the skills, commands and subagents that Claude may pick by itself, which is the stage the previous lesson measured for one skill. The full text of a skill or a subagent waits until Claude uses it. The plugin’s servers run in each session and its hooks act on their events. Both run with your user account’s rights.

Checkpoint · sort

What acts in a session that never releases?

Section titled “What acts in a session that never releases?”

Before an install, the /plugin menu in Claude Code shows what a plugin will add. That list tells you a hook is there but not the command behind it, and that is why Anthropic’s review steps send you to the plugin’s own files [2]. For a plugin directory you have cloned, the same page gives the command claude --plugin-dir <directory> plugin details <name>, which lists its components without starting a session. inventory.py does a similar job for the parts this lesson reads, and it also prints each hook’s command and each server’s address. Its last line estimates the tokens that the names and descriptions add to every turn, with the same rule as measure.py in the previous lesson.

Example · run it

Run this, and compare with the output below.

Terminal window
python3 inventory.py release-kit
Output
plugin release-kit 1.4.0
skills:
  release
commands: none
agents:
  release-notes, tools: Read, Grep, Bash
hooks:
  PreToolUse, tool matches Bash: python3 "${CLAUDE_PLUGIN_ROOT}/scripts/changelog_guard.py"
servers:
  tracker: calls https://tracker.example.com/mcp
bin: none
always loaded, names and descriptions: 50

Output verified in CI from site/examples/customizing-agents/plugins/release_kit.py.

Now read each part in the plugin’s directory, and write down what it does in a session.

The skill, skills/release/SKILL.md, has the five release steps and a check that says when the release is done. Its steps read and edit the repository’s CHANGELOG.md. In a plugin, a skill’s command name starts with the plugin’s name, so this one is /release-kit:release [5]. The last line of the inventory puts the skill and the subagent at about 50 tokens per turn together, which is small.

The subagent, agents/release-notes.md, is a helper agent. Claude gives it a task, and it works on that task with its own instructions and its own context. This one writes release notes from git log. Its front matter lists Read, Grep and Bash, so it can run shell commands. A subagent file without a tools line may use every tool that subagents are allowed [6]. Read that line in every subagent a plugin brings.

The hook is in hooks/hooks.json. Nobody has to run the release skill for it to act, because it is active from the moment a session loads the plugin [5]. Its event is PreToolUse, the moment before Claude Code runs a tool call. Its matcher, a pattern on the tool name, is Bash, so it runs before shell commands only. Without a matcher, a hook runs on every occurrence of its event, and a PreToolUse hook can stop the call [7]. The inventory shows the command and not what the script does, so open scripts/changelog_guard.py. It blocks every git commit that doesn’t stage CHANGELOG.md, in every repository where the plugin is enabled.

The server is in .mcp.json. It is an MCP server at tracker.example.com that gets the value of the TRACKER_TOKEN environment variable as a bearer token. While the plugin is enabled, Claude has this server’s tools, and Claude Code talks to the server for it. If an entry has a command and no url, Claude Code starts that command as a process on your own machine [2]. The server can do on the tracker what that token allows, so the token’s access is the access you grant.

This plugin has no bin/ directory. In a plugin that has one, the agent’s shell can run every file in it by name, because Claude Code adds the directory to that shell’s PATH. Anthropic’s review steps say to read all of those files [2].

Your permission rules are the allow and deny rules in your settings that decide which tool calls Claude may make. They check a call to one of the plugin’s MCP tools, and they check a shell command that runs a file from bin/. Claude Code’s sandbox for shell commands covers only the second of those, because the server behind an MCP tool runs outside it. Hooks and server processes are outside both. They run with your full user rights, and no permission rule sees them [2].

Checkpoint · multi-choice

Which two of these do your permission rules check?

Select exactly 2.

Checkpoint · multi-choice

Before you install the plugin, which three of these show you what it would run in your sessions?

Select exactly 3.

A plugin is a dependency, and it gets the same kind of review as a package in the lockfile (Reviewing what the agent pulled in). Spend the review effort in proportion to the risk, and count what the plugin costs you later as well as what it gives you today. Weigh it the way Instruction, skill or tool? weighed each option: by what it adds to the context window on every turn, and by what it adds to the things that can act in your sessions.

  • Install it when you want what most of its parts do. Choose the narrowest scope that fits, and read the plugin again when an update arrives.
  • Copy one skill out of it when a skill is all you want and the plugin’s license lets you copy it. A skill works without a plugin [1]. The copy goes into your project’s .claude/skills/ and doesn’t get updates. You own it from then on. A skill that calls a script from elsewhere in the plugin needs that script too.
  • Leave it when what the parts cost is more than what they do for you, or when you can’t read what a part runs.

For release-kit, you wanted one skill. Your team updates CHANGELOG.md only when it cuts a release. The hook would block all the other commits in each repository where the plugin is enabled. The tracker server needs a token, and you don’t use that tracker. The skill uses only the files in its own directory. So copy the skill. If the team decides later that every commit needs a changelog entry, that’s a rule for the repository, and it goes into a hook in the repository’s own settings.

Checkpoint · choice

Which of these is the right decision for release-kit?

Exercise

Read the hookify plugin in Anthropic’s public claude-code repository, at the commit the link names, and decide what to do with it. Know what it can change before you start. Its hooks run on every tool call, before and after, on every prompt you submit and every time Claude stops. They can block a tool call and keep Claude from stopping, and its /hookify:hookify command has Claude write rule files into the project’s .claude/ directory. The exercise is a read, so it doesn’t install the plugin. If you decide after the read to try it, install it at local scope in a scratch repository, never where you have real work. An install comes from the marketplace, claude-code-plugins, so it gets that marketplace’s current hookify and not the commit you read. That marketplace has an official name, and those have auto-update on by default [4]. Read the installed copy again before you use it, or turn off auto-update for that marketplace first.

These commands fetch only the plugin’s directory, into ~/plugin-read, and run the inventory on it. The first line deletes ~/plugin-read, so the commands also work on a second attempt.

Terminal window
rm -rf ~/plugin-read
git clone -q --filter=blob:none --sparse https://github.com/anthropics/claude-code ~/plugin-read
cd ~/plugin-read
git sparse-checkout set plugins/hookify
git checkout -q e1bb7b065bc29117ab5923f8772fee16a4630a0d
python3 <course-repo>/site/examples/customizing-agents/plugins/inventory.py plugins/hookify

Then read hooks/hooks.json, the four scripts it names, the skill and the agent. Write one line per part: what it is, when it acts, and what it can change. End with your decision and one sentence of reasons.

A good result names one skill, four commands, and an agent with Read and Grep. It names four hooks without a matcher, on PreToolUse, PostToolUse, Stop and UserPromptSubmit, and no servers. The inventory estimates 358 tokens per turn for the names and descriptions. The scripts read rule files named .claude/hookify.*.local.md in the project, and some rules read the session transcript. They print a decision that can deny a tool call or keep Claude from stopping. Copying the skill out is not a real option here, because it teaches the format of rule files that only the plugin’s hooks read. The repository’s LICENSE.md also reserves all rights, so check the license before you copy any file from it. What would the hooks cost you in a session where you have no rules at all?

Stretch: Run the same read on a second public plugin that declares an MCP server, and say what access the server asks for.

Recap

  1. A plugin ships skills, subagents, hooks and MCP servers together, and you usually install it by name from a marketplace [1].
  2. An enabled plugin costs context on every turn and runs its hooks on their events, also in sessions that never use it [1] [5].
  3. Your permission rules check the calls Claude makes to a plugin’s tools. Hooks and server processes run with your user rights, outside both the rules and the sandbox [2].
  4. Read hooks/hooks.json, the scripts it names, .mcp.json and bin/ before you install. Claude Code’s install screen names each hook but doesn’t show the command behind it [2].
  5. Weigh a plugin like a dependency: install it, copy one skill out of it when the license allows, or leave it.

You can now

  • Reads a plugin's parts before installing it and takes only what is needed

  1. Anthropic. Plugins overview. Claude Code documentation. Reference. Claude Code plugins
  2. Anthropic. Plugin security and trust. Claude Code documentation. Reference. Claude Code plugin security
  3. Anthropic. Plugin manifest reference. Claude Code documentation. Reference. Claude Code plugin manifest
  4. Anthropic. Install and manage plugins. Claude Code documentation. Reference. Claude Code plugin install
  5. Anthropic. Add components to a plugin. Claude Code documentation. Reference. Claude Code plugin parts
  6. Anthropic. Create custom subagents. Claude Code documentation. Reference. Claude Code subagents
  7. Anthropic. Hooks reference. Claude Code documentation. Reference. Claude Code hooks