← Claude Code Hub
✦ Tip #198 Sep 15, 2026

--plugin-dir in Claude Code: test plugin changes before you ship them

You edit your plugin and the session keeps loading the installed version. One flag makes your local copy win for that session.

Two sessions compared: without the flag the installed 3.0.0 plugin loads and craft:worktree is missing; with --plugin-dir your local 3.1.0 copy loads and it shows up

TL;DR Start with claude --plugin-dir ./path and your local copy beats the installed plugin of the same name for that session. No uninstall, no version bump, no push just to see your own change.

You have a plugin installed, yours or your team's. You edit a skill, save, and want to watch it run. That is where the detour starts: commit, push, bump the version in plugin.json, update the marketplace, reinstall. Meanwhile the session you already have open keeps loading the old copy and never says a word about it.

The flag that skips the whole detour has been in the docs for a while, framed as "this is how you test the plugin you are building from scratch". The rule that makes it genuinely useful sits halfway down a long section: a copy loaded with --plugin-dir shadows an installed plugin of the same name for that session.

The proof, on my own machine

I have craft installed from my marketplace at 3.0.0, and the repo at ~/code/craft sitting at 3.1.0. The difference between them is one new skill, worktree, that only exists locally.

Start with --debug and Claude Code writes where each plugin came from into ~/.claude/debug/<session-id>.txt. Without the flag:

[DEBUG] Attempting to load skills from plugin craft default skillsPath:
        /Users/juan.nunez/.claude/plugins/cache/craft/craft/3.0.0/skills
[DEBUG] Loaded 7 skills from plugin craft default directory

And pointed at my local copy:

[DEBUG] Loaded inline plugin from path: craft
[DEBUG] Plugin "craft" from --plugin-dir overrides installed version
[DEBUG] Attempting to load skills from plugin craft default skillsPath:
        /Users/juan.nunez/code/craft/skills
[DEBUG] Loaded 8 skills from plugin craft default directory

That second line is the rule stated by the product itself, and that sentence is nowhere in the documentation. Seven skills against eight, and the eighth is worktree, the one I only have locally.

No duplicate namespace, no conflict: the local copy stands in for the installed one and the name is still craft. Close the session and everything is back as it was. Nothing was uninstalled, your settings.json was never touched, and the installed plugin is still there for every other session.

The one exception is a plugin your organization's managed settings force on or off. The flag cannot override those.

The loop while you edit

Inside the session, /reload-plugins picks up whatever you change without a restart: skills, agents, hooks, and the plugin's MCP and LSP servers.

Reloading is not free, though. Changing tool definitions invalidates the prefix cache, so the next turn reprocesses the whole conversation at full price. On a short session it does not matter; on a session that has been running for hours it shows. If you would rather see the number than guess, the /cost line names what broke your cache and why, and tool definitions changed is exactly this cause. The move is the usual one: batch a few edits and reload once, rather than reloading after every save.

A whole folder, not one plugin

If you keep several plugins together, you do not need to repeat the flag for each. Point it at the parent folder and it loads everything inside:

claude --plugin-dir ./plugins

I tried it with three throwaway plugins and one loose directory with no manifest, and the --debug log spells it out in a single line:

[DEBUG] --plugin-dir ./plugins is a folder of plugins: loading alpha, beta,
        gamma; no manifest in notaplugin
[DEBUG] Loaded 3 directory-loaded plugins

It reads the top level only: every subfolder with a .claude-plugin/plugin.json loads as its own plugin, and anything without a manifest stays out without erroring. That is the reason to start with --debug the first time: a normal session never prints that line, so a plugin whose manifest you forgot simply does not show up. When something refuses to load, claude plugin validate tells you why.

In an interactive session it also watches the folder: drop a subfolder in and it loads as a new plugin on the spot, take one out and it unloads. Claude Code prints a line for each change. When applying one mid-conversation would break the cache, it holds the change and tells you to run /reload-plugins yourself.

A zip that is not on your disk

For something that already comes packaged, a CI artifact or a release candidate, there is the sibling flag:

claude --plugin-url https://example.com/my-plugin.zip

It is fetched at startup and lives for that session only. If the fetch fails or the archive is invalid, Claude Code still starts and leaves the error in the Errors tab of the /plugin manager. The same caution applies as with any other source: point it only at archives you control.

Both flags repeat to load several, and --plugin-url also takes space-separated URLs inside one quoted argument.

Reference

How you load it What comes in When you reach for it
--plugin-dir ./my-plugin That folder, as one plugin You are editing one specific plugin
--plugin-dir ./my-plugin.zip The zip, unpacked Someone handed you a package
--plugin-dir ./plugins Every subfolder with a manifest You maintain several at once
--plugin-url https://… A remote zip, that session only CI artifact, release candidate
/plugin install Permanent, in your config You already trust it

The first four never touch your configuration and vanish when you close the session. The one that really installs is the fifth, and from there the weight rides along in every message.

With this the development loop comes down to edit, /reload-plugins, look. The commit becomes the last step instead of the toll you pay to test. If you do not have a plugin yet, start with what one actually is; when you want to hand it out, the marketplace is the next step.

Official docs: Create plugins

Requirements

  • Claude Code v2.1.265 or later to point --plugin-dir at a folder of plugins. Pointed at a single plugin or a .zip, the flag has worked since earlier versions.
  • Everything above was run on v2.1.272. I verified --plugin-url by serving the zip from a local server, not from a public URL.
  • The live folder watch is interactive-session only, and that part comes from the documentation: I did not capture it.
  • In the --debug blocks I shortened the absolute paths from my own disk. Everything else is verbatim.
Free guide

The 51 essentials, as a guide.

One page per tip. Five chapters. What I actually use daily in production. No theory, no fluff.

  • I. Getting started 10 tips
  • II. Awareness 3 tips
  • III. Mastery 22 tips
  • IV. Autonomy 10 tips
  • V. Comparison 6 tips
Are you a professional Web developer?

You'll receive the guide by email · You join the Gravitas newsletter · Unsubscribe anytime

of 51
#

Wmedia · 51 Tips
Free guide · 51 tips · 5 chapters

The 51 essentials, as a guide.

Are you a professional Web developer? · Unsubscribe anytime
Workshop for teams

Multiply your team's output without sacrificing quality: a 6 to 8 hour AI First workshop, online, on the Claude platform.

See the workshop

Want the 51 Claude Code essentials as a guide?