← Alle Playbooks
Playbook· build

Distributing plugin bundles via URL, --plugin-url in 30 minutes

Since Claude Code 2.1.129 (April 2026) you can fetch plugin ZIPs directly from a URL. No marketplace entry, no repo setup. How the flag works, when it beats the marketplace path, and where the trust pitfalls hide.

Claude Code 2.1.129 got a new flag in April 2026: --plugin-url. You give it a URL to a plugin ZIP, it fetches the archive at start, loads the plugin only for this session, and after you quit it is gone again. That is the simplest plugin distribution method Anthropic offers so far.

Sounds small. But it has practical consequences when you test plugins, share them with colleagues or distribute them as a CI build artifact. Here is when that makes sense and when it does not.

1. What --plugin-url does exactly

When you start claude --plugin-url https://example.com/my-plugin.zip, the following happens:

  1. Claude Code loads the ZIP from the URL at session start.
  2. The archive is unpacked into a temporary directory under ~/.claude/plugins-session-cache/.
  3. The plugin is activated for this session. Skills, agents, hooks, MCP servers, everything like a normal plugin.
  4. After session end the cache directory is deleted at the next cleanup. The plugin is not persistently installed.

That is explicitly session-only. If you want the plugin permanently, you have to go the marketplace path or mount it locally via --plugin-dir.

On a fetch error or an invalid archive (no .claude-plugin/plugin.json, broken ZIP structure) Claude Code reports a plugin load error and starts without the plugin.

2. When you should use --plugin-url

Three clear use cases.

First use case: quick sharing with colleagues. You built a plugin, want to show it to a colleague without them setting up a marketplace or pulling GitHub clones. You pack the plugin as a ZIP, send the URL (S3 bucket, GitHub release asset, Dropbox link), the colleague starts claude --plugin-url <link>, done. Both work against the same version, the colleague does not need to install anything permanently.

Second use case: testing CI build artifacts. Your CI builds a plugin ZIP on every push and pins it to a versioned URL. You want to test the last build version before the tag release. claude --plugin-url https://ci.example.com/builds/main-abc123/plugin.zip, test, done. No local setup needed, you test against the exact CI version.

Third use case: throwaway plugins. You need a special plugin for a one-off task (e.g. migration from one framework to another). You do not want to install it permanently because it is dead after the migration. Call the URL once, do the job, close the session, gone.

3. When you should not use it

Three clear anti-patterns.

You use the plugin daily. Fetching a 5 MB ZIP at every session start is waste. Pack the plugin into a marketplace or clone it locally with --plugin-dir. URL loading is for spike use, not the daily driver.

The plugin needs persistent state. If your plugin stores data in ~/.claude/plugins/<name>/state.json or maintains a local DB, that does not work with --plugin-url. The cache directory is not synced between sessions.

The plugin URL comes from a dubious source. ZIP archives you do not control, from forum posts or Discord links, never fetch blind. Same trust problem as with npm install of random packages.

4. Plugin bundle format

You have to structure the ZIP exactly like a normal plugin directory. Root of the ZIP:

my-plugin.zip
├── .claude-plugin/
│   └── plugin.json
├── skills/
│   └── my-skill/
│       └── SKILL.md
├── agents/
│   └── my-agent.md
├── hooks/
│   └── hooks.json
└── README.md

plugin.json is mandatory, everything else optional depending on the plugin type. Important: the ZIP must not have a wrapper folder. If you have my-plugin/ as the top-level folder in the ZIP instead of .claude-plugin/ directly, Claude Code does not find the manifest and fails.

Create it with cd my-plugin && zip -r ../my-plugin.zip . (from inside the plugin contents, not from the parent folder).

5. URL hosting options

Where do you put the ZIP. Three pragmatic paths.

GitHub Releases. If you have a GitHub repo, put the ZIP as a release asset. The URL is https://github.com/user/repo/releases/download/v1.0/plugin.zip. Versioned, free, cached by the GitHub CDN.

S3 or Cloudflare R2. For your own plugins without a public repo. Bucket with public read for the ZIP, the URL is the bucket URL. R2 has no egress costs, which is relevant with frequent downloads.

Direct server. If you already have a domain (e.g. studiomeyer.io), just put the ZIP under studiomeyer.io/downloads/my-plugin.zip. The webserver has to deliver Content-Type: application/zip correctly, that is it.

With all options watch out for TLS. Claude Code will (my expectation, not explicit in the docs) either reject or warn about HTTP URLs. Plus: HTTP plugin URLs are an obvious MITM vector. Always HTTPS.

6. Trust and security

Anthropic says explicitly in the docs: the same trust considerations apply as for all plugin sources. That means a plugin from a URL can be just as harmful as a maliciously set-up marketplace. Only load plugins from sources you control yourself or that you can clearly attribute to a trustworthy person.

Concrete risks:

The plugin can run arbitrary Bash commands via allowed-tools if you do not restrict the hooks setup. allowed-tools: Bash(*) in a skill means full access.

The plugin can make external HTTP calls via MCP server configs. A malicious MCP server snippet in the plugin can exfiltrate data.

The plugin can trigger via hooks on every UserPromptSubmit or PostToolUse event and use that to send data to a remote server.

Protective measures:

--plugin-url with locally controlled URLs is OK. With foreign URLs without code review, no.

For critical plugins (e.g. for production repos) always download the ZIP, open it manually, code review, then activate. Not directly via URL.

If you distribute plugins for your team, sign the ZIPs (e.g. with cosign) and put a verify step in your onboarding docs.

7. Marketplace vs --plugin-url, the decision

The official plugin distribution goes via marketplaces. You put a marketplace.json in a repo, users register it with /plugin marketplace add <repo>, you publish updates via commit. Versioning via the version field or git SHA.

For long-lived plugins you distribute permanently, that is the right method. The marketplace gives users auto-updates, an easy browse experience, clear version management.

--plugin-url is the short variant for cases where the marketplace is overkill. Single use, test build, throwaway, demo. No marketplace maintenance.

Practical rule of thumb: if you need a fixed slug and several users should maintain it, marketplace. If you want to fetch the plugin fresh on every run or only need it for a demo, URL.

8. Migration from --plugin-dir to --plugin-url

You have probably already tested with --plugin-dir ./my-plugin. The step to --plugin-url is small.

# Before: locally with --plugin-dir
claude --plugin-dir ./my-plugin

# Pack the ZIP
cd my-plugin && zip -r ../my-plugin.zip .

# Upload, S3 example
aws s3 cp ../my-plugin.zip s3://your-bucket/my-plugin.zip --acl public-read

# Start with the URL
claude --plugin-url https://your-bucket.s3.amazonaws.com/my-plugin.zip

What does not change: the plugin behaviour, the skills, the hooks. Identical to --plugin-dir.

What changes: no live reload on edit. If you are building on the plugin, --plugin-dir is much more practical, the /reload-plugins command picks up changes directly. URL mode is snapshot-based, you have to re-zip and re-upload for every change.

9. The two pitfalls

ZIP wrapper folder. If you zip the plugin directory from outside (zip -r my-plugin.zip my-plugin/) the ZIP has a top-level folder. Claude Code then finds .claude-plugin/plugin.json under my-plugin/.claude-plugin/plugin.json instead of directly under .claude-plugin/plugin.json and fails. Mandatory: zip from inside the plugin contents with cd my-plugin && zip -r ../my-plugin.zip ..

Cache persistence is underestimated. There is an implicit cache entry for URL plugins so you do not fetch fresh at every start. If you change the ZIP at the URL, you have a stale cache hit in the worst case. Workaround: on plugin updates change the URL path (versioning), e.g. plugin-v1.zip, plugin-v2.zip. Or delete the cache before the next run with rm -rf ~/.claude/plugins-session-cache/.

10. What comes next

If you have never built a plugin, start with --plugin-dir, get familiar with the format, then URL distribution. Mandatory reading is the official Anthropic plugins docs.

If you already have plugins in the marketplace, --plugin-url is worth it as a test pipeline. CI builds a ZIP on every commit, you test against the last pre-release version, then you tag for the marketplace release.

Plus check lesson L4-06 in the Academy for marketplace discovery patterns. It goes into detail on how you build the marketplace.json and distribute plugins via the official Anthropic marketplace.

If you want to host your own plugin marketplaces (e.g. for your team or your open-source project), the playbook mcp-server-publishen is complementary, it is about MCP server listings, but the marketplace logic behind it is related.

Source

Specs verified via official Anthropic documentation on 2026-05-07:

Consulted secondary sources:

  • claude-world.com Claude Code 2.1.129 release notes (URL plugin fetching coverage)
  • github.com/anthropics/claude-plugins-official/marketplace.json (official marketplace format example)

Consulted recipes in the Academy:

  • Phase 1 Recipe 1.5 Plugins setup
  • Lesson L4-06 MCP discovery and marketplaces
  • Playbook eigene-slash-commands-für-claude-code (plugin counterpart)