# Reading a plugin before you install it

> Read an invented release plugin part by part, name what each skill, hook, subagent and server does in your sessions, and decide whether to install it, copy one skill out of it, or leave it.

Page: https://schubergphilis.github.io/ai-training/customizing-agents/plugins/
License: CC BY-SA 4.0, https://creativecommons.org/licenses/by-sa/4.0/

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.

```sh
cd <course-repo>/site/examples/customizing-agents/plugins
```

## What a plugin bundles

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 (Plugins overview, Claude Code documentation). 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 (Plugins overview, Claude Code documentation). 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 (Plugin security and trust, Claude Code documentation).

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 (Plugins overview, Claude Code documentation).

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
(Plugin manifest reference, Claude Code documentation). A marketplace with auto-update turned on
replaces the installed files in the background
(Plugin security and trust, Claude Code documentation). Most of Anthropic's official marketplaces
have auto-update on by default, and third-party ones have it off
(Install and manage plugins, Claude Code documentation).

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
(Plugins overview, Claude Code documentation). 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: What acts in a session that never releases?

Buckets:

- In every session where the plugin is enabled
- Only in a session that uses the part

Items:

- The name and description of the release skill
- The hook that runs before each shell command
- The connection to the issue tracker server
- The numbered release steps in the body of the skill
- The instructions of the release-notes subagent

## Read one plugin, part by part

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 (Plugin security and trust, Claude Code documentation). 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: List what release-kit holds

Run this, and compare with the output below.

```sh
python3 inventory.py release-kit
```

Output:

```text
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
```

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`
(Add components to a plugin, Claude Code documentation). 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 (Create custom subagents, Claude Code documentation). 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 (Add components to a plugin, Claude Code documentation). 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 (Hooks reference, Claude Code documentation). 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
(Plugin security and trust, Claude Code documentation). 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 (Plugin security and trust, Claude Code documentation).

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 (Plugin security and trust, Claude Code documentation).

#### Checkpoint: What do your permission rules check?

Which two of these do your permission rules check?

Select exactly 2.

- Claude calling one of the plugin server's tools
- The hook script that runs before each shell command
- Claude running the file in bin/ with a shell command
- The local server process that Claude Code starts

#### Checkpoint: Where do you see what it runs?

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

Select exactly 3.

- hooks/hooks.json and the scripts it names
- The list of parts in the /plugin menu before the install
- The .mcp.json file
- The plugin's README
- The files in the bin/ directory

## Install it, copy one skill, or leave it

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](https://schubergphilis.github.io/ai-training/coding-with-agents/dependency-review/)).
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?](https://schubergphilis.github.io/ai-training/customizing-agents/skill-or-tool-or-instruction/)
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
  (Plugins overview, Claude Code documentation). 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: What do you do with release-kit?

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

- Install it at user scope, and add a permission rule that denies the hook script.
- Install it at project scope, so only this one repository gets the hook.
- Install it and keep it, since the hook runs only on release commits.
- Copy the release skill into the repository's skills and don't install the plugin.

#### Pitfall: The hook that came with the release skill

A developer installs `release-kit` at user scope to get the release
skill. Their team updates `CHANGELOG.md` only when it cuts a release. A
week later, the agent's everyday commits start to fail with a message
about `CHANGELOG.md`, and the agent adds a changelog entry to each commit
to get past the check. The developer looks for the cause in the release
skill and finds nothing there, because the cause is the hook, which runs
before each shell command in every project. The plugin was installed for
one part and brought all of them. Read `hooks/hooks.json` and the scripts
it names before you install a plugin, and don't install a plugin for one
skill that you can copy.

## Exercise

Read the `hookify` plugin in Anthropic's public
[claude-code repository](https://github.com/anthropics/claude-code/tree/e1bb7b065bc29117ab5923f8772fee16a4630a0d/plugins/hookify),
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 (Install and manage plugins, Claude Code documentation). 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.

```sh
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
   (Plugins overview, Claude Code documentation).
2. An enabled plugin costs context on every turn and runs its hooks on
   their events, also in sessions that never use it
   (Plugins overview, Claude Code documentation) (Add components to a plugin, Claude Code documentation).
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 (Plugin security and trust, Claude Code documentation).
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 (Plugin security and trust, Claude Code documentation).
5. Weigh a plugin like a dependency: install it, copy one skill out of it
   when the license allows, or leave it.

#### Habit

The next time someone suggests a plugin, open its `hooks/hooks.json`
before you install it. Name each event it runs on.

## References

- Plugins overview, Claude Code documentation, https://code.claude.com/docs/en/plugins
- Plugin security and trust, Claude Code documentation, https://code.claude.com/docs/en/plugins/security
- Plugin manifest reference, Claude Code documentation, https://code.claude.com/docs/en/plugins/manifest-reference
- Install and manage plugins, Claude Code documentation, https://code.claude.com/docs/en/plugins/install
- Add components to a plugin, Claude Code documentation, https://code.claude.com/docs/en/plugins/components
- Create custom subagents, Claude Code documentation, https://code.claude.com/docs/en/sub-agents
- Hooks reference, Claude Code documentation, https://code.claude.com/docs/en/hooks
