Quick start
Here’s the whole journey, from an empty list to a working plugin — all from Desktop → Settings → Plugins:1
Install a plugin
In the Install Plugin form, paste a source — a git repo (
git:owner/repo), a download URL, or a path to a folder on your machine (/path/to/plugin) — and click Install. Leave Name blank to take the name from the plugin’s manifest (or the source). See Installing a plugin for all three source forms.2
See it in the list
The plugin appears with a status badge — Loaded, Disabled, or Error — and a row of contribution tags showing what it adds (such as skills, commands, agents, mcp, hooks, providers, bin). It lands enabled but untrusted: its skills and commands work right away; its code components wait for you to trust it.
3
Enable / disable it
Use the Enable / Disable button to turn the plugin’s markdown components (skills, commands, subagents) on or off. A freshly installed plugin is already enabled.
4
Trust it (only if it ships code)
If the plugin includes code or credential components — MCP servers, hooks,
bin/ executables, or LLM providers — click Trust, review the confirmation listing exactly what will run, and confirm. A markdown-only plugin needs no trust. See the Security model.5
Use it
Skills become loadable by any agent; commands and subagents are available as
/<plugin>:<command> slash commands; trusted MCP servers and hooks wire in automatically; trusted providers show up on the AI Providers screen once you add a key. See Invoking each component.~/.dash/gateway/plugins/) and edit config.json by hand — see Where plugins live, Configuration → Plugins, and the complete example below.
Where plugins live
Installed plugins live in your HQ’s managed plugins folder:~/.dash (overridable with $DASH_HOME), and its own data lives in ~/.dash/gateway — so plugins land in ~/.dash/gateway/plugins/. Running the HQ standalone with --data-dir <path> puts them in <path>/plugins/ instead. See the data directory layout for the full picture.
You rarely need to touch this folder — Desktop’s Plugins screen and the management API manage it for you. But it’s there if you want to drop in a plugin by hand or inspect config.json directly.
What’s in a plugin
A plugin is a directory with an optional.claude-plugin/plugin.json manifest plus any of these components:
The first three components are markdown — they only contribute instructions, so an enabled plugin loads them right away. The last four run code or carry credentials, so they stay inert until you explicitly trust the plugin (see Security model).
The
.claude-plugin/plugin.json manifest is optional. When present it can set name, displayName, description, and version; when absent, the install name comes from the source (or the directory name).
Installing a plugin
You install a plugin by source from Settings → Plugins in Desktop — fill in the Install Plugin form and click Install — or, if you’re scripting, by calling the management API’sPOST /plugins/install endpoint directly. Either way the installer fetches the plugin, scans it, and drops it into your HQ’s managed plugins directory at ~/.dash/gateway/plugins/<name> — no restart needed; the HQ hot-reloads.
A plugin install takes a single source string in one of three forms:
For example, installing from git:
name, on-disk location, and the source it came from. The plugin lands enabled but untrusted — its skills and commands work immediately; its code components wait for you to trust it.
Pass an optional name to override the install name. The manifest’s name still wins when one is present.
Pinning a version
For git sources, append@ref to pin the plugin to a branch, tag, or commit:
@main always installs the latest, which is convenient but means a later reinstall can bring in different code.
Managing plugins in Desktop
Desktop’s Settings → Plugins screen is where you install, inspect, enable, trust, and remove plugins without touching a config file. Changes take effect immediately; the HQ hot-reloads as you go. Install Plugin form. At the top of the screen, a Source field takes any install source (git, URL, or local path — see Installing a plugin) and an optional Name field overrides the install name (the manifest’sname still wins when one is present). Click Install to fetch, scan, and load the plugin. If the scan flags the plugin as suspicious or dangerous, the screen shows the verdict so you can decide whether to keep it.
The plugin list. Each installed plugin is a card showing its name, version, a status badge, and its contributions:
Below the badge, contribution tags show which component types the plugin ships. A tag is shown activated (green) when that component is actually running, or noop (greyed out, struck through) when it’s present but not active yet — for example, a code component on an untrusted plugin, which stays inert until you trust it.
Per-plugin controls. Each card has:
- Enable / Disable — toggles the plugin’s markdown components (skills, commands, subagents) on or off.
- Trust / Revoke Trust — shown only when the plugin is enabled. Trust opens a confirmation (below); Revoke Trust immediately stops the plugin’s code components from running.
- Remove — deletes the plugin’s directory from your machine, after a confirmation prompt.
The trust confirmation
Clicking Trust opens a confirmation dialog before any code runs. It carries a high-contrast warning — “This code will run on your machine.” — and lists the exact code component types that will activate once you trust the plugin: any ofbin, hooks, mcp, and providers the plugin ships. Confirm with Trust Plugin, or cancel to leave the plugin untrusted.
The Trust Plugin button is disabled until the plugin is enabled — you enable a plugin first, then trust it. Trust is a deliberate, separate action; nothing trusts a plugin on your behalf. See the Security model for why.
Security model
Installing a plugin brings someone else’s instructions — and potentially their code — onto your HQ. Dash treats every install as untrusted by default and layers several defenses:-
Untrusted on arrival. A freshly installed plugin is
enabledbut nottrusted. Its markdown components (skills, commands, subagents) load, but its code components stay inert — MCP servers, hooks,bin/executables, and provider catalogs do nothing until you trust the plugin. Nothing a plugin ships can execute on your HQ from the install alone. -
Trust is a separate, deliberate action. Marking a plugin
trustedis a distinct step you take after you’ve reviewed it — never something an install, a marketplace entry, or the plugin itself can do on your behalf. Only trust plugins whose code you’ve read and are willing to run inside the HQ process. -
A heuristic scan, fail-closed. Before a plugin is installed, its manifest and code payloads (
bin/,hooks/hooks.json,.mcp.json,providers/) are scanned for dangerous patterns — downloads piped into a shell, destructive deletes, prompt-injection, secret exfiltration, and embedded private keys. A plugin the scan flags as dangerous is refused (the install fails; nothing lands on disk), and the scan is fail-closed: if it can’t complete, the install is rejected rather than waved through. Softer suspicious signals — reading environment variables, base64 decoding, or prototype-pollution keys in a config file — are noted but do not block the install; treat them as a prompt to review the plugin before you trust it. -
Path-traversal (zip-slip) protection. Archives are extracted with hard guards: any entry whose path would escape the destination — via
../, an absolute path, or a symlink pointing outside — is rejected and the whole install fails. A malicious archive can’t write files outside its own plugin directory.
Provider credentials
Some plugins ship LLM provider catalogs (providers/*.json) that add extra AI providers — your company’s internal model HQ, a regional endpoint, or any OpenAI-compatible service. When you’ve trusted a plugin that ships one, its providers appear automatically on the Settings → AI Providers screen in Desktop (AI Providers), listed right alongside the built-in ones (Claude, OpenAI, Google, Kimi, OpenRouter).
Adding a key works exactly like a built-in provider: open AI Providers, pick the plugin’s provider, and paste your key. Each provider needs its own API key.
Multiple named keys. A provider can hold more than one key — a default plus extras like backup — so you can keep an alternate credential ready. Keys are stored in the same encrypted credential store as your built-in providers, under slots named:
myprov stores its primary key under myprov-api-key:default and a second under myprov-api-key:backup.
A plugin’s providers only show up if the plugin is trusted. An untrusted plugin’s provider catalog is withheld — its providers won’t appear on the AI Providers screen, and there’s nowhere to add a key for them — until you trust the plugin (see Security model). This is the same trust gate that holds back MCP servers, hooks, and
bin/ executables.anthropic, openai, google, moonshotai, openrouter), that provider is dropped and never offered, even from a trusted plugin.
Invoking each component
Once a plugin is loaded (and trusted, where needed), its components show up in different places. Here’s how each one is reached:Skills
A plugin’sskills/<name>/SKILL.md files join the agent’s skill index — the compact list of available skills the agent sees in its system prompt. The agent loads a skill’s full instructions on demand with its load_skill tool, so the agent needs load_skill in its tool list (it’s there by default whenever skills are configured). See Skills for the format and how discovery works.
Commands and subagents
A plugin’scommands/<name>.md becomes a slash command /<plugin>:<command> — a plugin named research with commands/triage.md exposes /research:triage. A plugin’s agents/<name>.md (Claude Code subagent format) becomes a sub-agent type named <plugin>:<agent>, which an agent launches with the agent tool. Both are markdown, so they work on enabled alone — no trust needed. The plugin name namespaces them, so neither can clash with anything else.
Plugin sub-agents run in their own context, not in the main session. Their
tools and model frontmatter is enforced — earlier releases loaded these files into the current conversation and treated tools as advisory. A sub-agent still never receives a tool or MCP server its parent lacks. See Configuration → Plugin sub-agent types.MCP servers, hooks, and executables
These are trusted code components, and none of them is invoked by a slash command — they wire in behind the scenes:- MCP servers (
.mcp.json) register with the HQ at startup. Their tools become part of the agent’s toolset; registration is fail-isolated, so a server that won’t start is logged and skipped without taking down the HQ. - Hooks (
hooks/hooks.json) run automatically at key points in a run — session start, before and after tools, and run completion. You don’t call them; they fire on events. For the full event list and behavior see Hooks in the configuration reference. - Executables (
bin/) are prepended to the HQ’sPATH, so a plugin’s tools resolve ahead of system binaries when a command, hook, or the agent’s shell tools invoke them by name.
LLM providers
A trusted plugin’sproviders/*.json catalogs add selectable models. Once the plugin is trusted and you’ve added a key (see Provider credentials), the provider’s models appear in the agent’s model picker as <id>/<model-id>, exactly like the built-in providers — point any agent at one the same way.
Choosing plugins per agent
By default, every agent sees every loaded plugin. You can scope an individual agent to a subset from its configuration:1
Open the agent's config
In Desktop, go to Squad, open the squad member, and switch to its Config tab.
2
Open the Plugins card
Expand the Plugins card. When no plugins are selected it reads “All plugins (default)” — the agent sees every loaded plugin.
3
Select the plugins this agent should see
Use Add plugin… to pick from the loaded plugins. Each one you add appears as a chip; remove a chip with its × button. As soon as you select at least one, the agent is scoped to exactly those plugins. Clear all the chips to return to the all-plugins default.
Per-agent selection controls visibility only — it does not trust a plugin. Trust is HQ-wide: selecting a plugin for an agent never makes its code run if the plugin isn’t trusted, and a trusted plugin stays trusted regardless of which agents are scoped to it. Only loaded plugins are offered in the picker — a disabled or errored plugin contributes nothing to route.
Choosing AI providers per agent
Alongside the Plugins card, each agent’s Config tab also has a Providers card. By default it reads “All providers (default)” — the agent can use models from every available AI provider. Add one or more providers to restrict the agent to just those: its model dropdown immediately narrows to the allowed providers, and if the agent’s current model belongs to a provider you removed, it stays visible marked “(not allowed)” so you can pick a replacement. An agent that tries to run on a disallowed provider gets a clear error instead of a response. Clear all the chips to return to the all-providers default. This is useful when an agent must only ever talk to a specific vendor — for example, keeping a customer-facing agent on Anthropic models only, regardless of which other providers are configured on the HQ.Marketplaces
A marketplace is a published catalog of plugins you can browse and install by name. You point Dash at a marketplace source — a local path, a URL, or a git repo — and Dash reads itsmarketplace.json to list the plugins it offers.
A marketplace.json looks like this:
Each entry’s
source is just an ordinary install source. When you install a marketplace plugin, Dash resolves the name to its source and runs the same untrusted, scanned install path as a direct install — a marketplace listing is never a shortcut to trust. Installing from a marketplace is exactly as safe as installing the source by hand.
Config flags
Each plugin has an entry in~/.dash/gateway/plugins/config.json describing its state. You may see these fields:
For the full config-file format — directory layout, manual enabling, loading a plugin from an arbitrary
path, and per-component details — see Configuration → Plugins.
A complete example plugin
Here’s a minimal but realistic plugin you can copy and install from a local folder. It bundles a skill, a slash command, and — optionally — an LLM provider and a hook. Directory layout:.claude-plugin/plugin.json — the manifest. Only name is meaningful-required (and must be kebab-case); the rest is metadata.
skills/summarize/SKILL.md — a skill. Markdown, so it loads on enabled alone.
commands/triage.md — a slash command, reachable as /my-plugin:triage. Optional frontmatter (name, description) overrides the command name and supplies a description.
providers/myprov.json (optional — a code/credential component, so it only runs once the plugin is trusted). The credentialPrefix must equal <id>-api-key, and models must list at least one model.
hooks/hooks.json (optional — also trust-gated). Claude Code hooks format; ${CLAUDE_PLUGIN_ROOT} resolves to the plugin’s own directory.
/Users/you/plugins/my-plugin) and click Install. The plugin lands enabled but untrusted — the summarize skill and /my-plugin:triage command work right away. To turn on the provider and hook, click Trust and confirm. Then add a key for the provider on the Settings → AI Providers screen, and its myprov/my-fast model becomes selectable for any agent.
What the errors mean
If an install fails, the response code tells you why:Not yet supported
A couple of capabilities are planned but not available yet, so you know not to rely on them:- Signature verification — installs are scanned heuristically but not cryptographically verified against a publisher signature.
- npm / registry sources — plugins install from git, URL, and local sources only; there’s no
npm:-style package registry source yet.