Claude Code Plugins: Install, Inspect, Update and Remove One Cleanly
- claude-code
- skills
- agent-ops
Before installing a Claude Code plugin, I want an answer to one question: what will be different in the next session? A new skill is easy to see. A hook that runs a command, a server that starts in the background, or instructions carried into every task deserve more attention. All of them can arrive in the same package.
That is why I would inspect one small plugin before browsing another "best plugins" list. The install command is the short part. Knowing what it installed, where it applies and how to remove it is the work.
- Contents: skills, agents, hooks and servers create different review obligations.
- Scope: a repository experiment can stay local without changing everybody's setup.
- Loading: declared, fetched and loaded are different states.
- Cost: a context estimate needs a task result beside it.
- Removal: disabling a component, uninstalling its package and deleting its data are different decisions.
The broader Claude Code review covers the tool itself. This guide uses Anthropic's lifecycle documentation and a proposed review-helper fixture. I have not completed a fresh native install-to-uninstall test for that fixture, so there are no runtime results or cost savings to report here.
What is the difference between a plugin, a skill and an MCP server?
A plugin is the package. A skill supplies task instructions; an MCP server supplies callable tools. You can use skills and servers without a plugin, or bundle them with agents and hooks. The plugin overview describes those components.
The distinction matters before you click install. Read a writing skill's instructions and references. For a server, find the startup command and the resources it can access. For a hook, find the event that triggers it. A package description saying "helps with reviews" does not answer any of those questions.
For the first experiment, I would use one headings skill: it reads a dummy text file and returns its headings without changing anything. No server, secrets, hooks or saved state. Call the example review-helper; it is a fixture specification, not a marketplace recommendation.
The acceptance condition is equally small. The returned headings must match the file, and the file must remain unchanged. An OAuth failure should not be able to obscure whether the plugin's own instructions loaded. Keep the first test boring enough that you can locate the failure.
Which installation scope should I choose?
Use local scope for your experiment in one repository, user scope for your setup across repositories, and project scope for a shared repository requirement. They affect different settings files. A committed project setting enables the plugin for collaborators, but does not install it on each collaborator's machine. See install scopes.
| Scope | Who it is for | Configuration |
|---|---|---|
| Local | You, in this repository | .claude/settings.local.json |
| User | You, across repositories | ~/.claude/settings.json |
| Project | Collaborators in this repository | .claude/settings.json |
Start in a disposable repo with dummy inputs. Write the chosen scope beside the package identity. You will need both when an update fails or when you want the plugin gone.
Being inside the test directory is not enough. The command's default scope may be broader than you intended. Check the flag and the settings file it changes before running a copied install command. Otherwise your local experiment becomes part of every session you start later.
Read the package before trusting the label
The manifest lives at .claude-plugin/plugin.json. It declares metadata and component configuration; the component files live elsewhere in the plugin structure. The directory name alone does not establish the command namespace. The manifest reference is the place to check it.
For the proposed fixture, the file inventory would be:
review-helper/
.claude-plugin/plugin.json
skills/headings/SKILL.md
That is an inventory to inspect, not a complete recipe for a valid manifest. Check the current schemas when creating the fixture. Keep its version and files as your baseline, because "the same plugin" can contain different code after an update.
I want to see any command it executes, any process it starts and any host it sends content to. I also want to know where it writes output. If those answers require chasing several scripts, chase them before loading the package. An unanswered question about execution is still an unanswered question after installation succeeds.
Anthropic's security and trust guidance says plugin components can run with your user privileges. The marketplace label does not isolate that execution for you. Treat executable components as code you are choosing to run.
Installation is only one loading stage
For a marketplace package, use its qualified identity, plugin-name@marketplace-name. Interactive /plugin install opens details for review and scope selection. The shell command installs directly, with an explicit scope available. Replace these placeholders with the package you actually reviewed; the install workflow covers the choices.
claude plugin install plugin-name@marketplace-name --scope local
claude plugin list --json
For a local author fixture, there is a different path:
claude --plugin-dir ./review-helper
--plugin-dir loads the directory for that session without installing it. Useful for development, but it does not test marketplace installation. The distinction is in the session-only loading flags.
Once the session starts, find the namespaced skill and invoke it on the dummy file. Compare the headings and compare the file before and after. "I loaded the plugin" in Claude's reply is not the result of that test.
The loading reference separates settings declarations, fetched files and components loaded by a running session. Changing a package on disk does not mean the current session has changed with it; reload or a new session may be needed. This is why I would keep the identity, scope, files and visible command together when diagnosing a failure.
Why does an installed plugin not load?
Find the failed stage before reinstalling. A fetched package can be disabled, missing a component or dependency, or absent from the running session. Preserve the exact message in the /plugin Errors tab and check the troubleshooting reference.
| What you see | Where to look next |
|---|---|
| No installation record | Identity, marketplace and install scope |
| Installed but disabled | Effective enable setting and its source |
| Enabled but skill missing | Component files, namespace and load error |
| Skill present but task wrong | Instructions and dummy input |
| Updated files but old behavior | Version loaded in this session |
Reinstalling, changing scope and renaming the package all at once can make the problem disappear without explaining it. Keep the original error and change one cause. You want the next failure to be cheaper to understand.
A loaded skill that Claude does not choose automatically is a different problem again. Read its description and frontmatter. Disable-model-invocation covers the invocation policy; reinstalling healthy files will not change that policy.
A plugin has to earn the context it takes
Use claude plugin details to inspect the always-on footprint and contributions from components:
claude plugin details plugin-name@marketplace-name
Anthropic separates repeatedly included metadata from content loaded when invoked, and describes usage views for identifying components that consume context without being used. See plugin cost and usage.
Keep that output beside the version. A smaller footprint is not automatically a better result. A plugin that prevents a second attempt may justify more startup context; irrelevant instructions can make a short task harder. I would compare the same input with the package enabled and disabled, judging the task result and the correction work as well as tokens.
There is no measured comparison in this article. That is the comparison I would require before claiming a saving.
Memory plugins add another ownership question: where does the saved material live, and how is it deleted? The Claude Code memory guide covers the underlying workflow. Removing a package is not evidence that records it wrote elsewhere have disappeared.
Updating and removing the right installation
Record the version before updating, then repeat the acceptance task in a new or reloaded session. These commands do separate jobs; they are not one script to paste and run:
claude plugin update plugin-name@marketplace-name --scope local
claude plugin disable plugin-name@marketplace-name --scope local
claude plugin uninstall plugin-name@marketplace-name --scope local --keep-data
Disable for a reversible comparison. Uninstall when you want that installation removed, deciding first whether its data should remain. The management reference documents scopes and --keep-data; inspect any external state in the package's own documentation too.
After removal, check the installed list and open a new session without --plugin-dir. If the command remains, identify its source. Another scope or a second origin is a better explanation to investigate than "uninstall harder."
How do Claude Code plugins compare with Codex plugins?
OpenAI also describes bundles containing skills and MCP servers, with lifecycle hooks for Codex runtimes. That shared packaging idea does not make Claude marketplace commands or manifests portable. Check the target runtime's skills and plugins documentation before transferring a package.
My decision would stay the same across clients: one reviewed package, one explicit scope, one observable task result, and a known way out. A successful install answers only part of that.
Frequently asked questions
What is the difference between a plugin, a skill and an MCP server?
A plugin packages components. A skill supplies task instructions and resources; an MCP server exposes tools. Skills and servers can also be used independently.
Which installation scope should I choose?
Local for your experiment in one repo, user for your setup across repos, project for a shared requirement. Verify the same scope when updating or removing it.
Why does an installed plugin not load?
Check enable settings, fetched files and the running session separately. Preserve the load error. A visible command that gives the wrong result is a task failure, not necessarily a loading failure.
How do I disable or remove a plugin?
Disable the intended scope for a reversible test. Uninstall that scope when finished, choosing whether to preserve data. Check a fresh session for other copies or origins.