# Plugins

Use and build shareable Droid packages for skills, commands, droids, hooks, and MCP servers.

Plugins package reusable Droid extensions so a team can
install the same skills, commands, droids, hooks, and MCP servers across projects. Use
standalone `.factory/` configuration for personal or project-local experiments, then
turn the pieces into a plugin when they should be shared, versioned, or governed.

For org-approved catalogs and managed marketplace sources, see [Internal Plugin Marketplaces](/enterprise/internal-plugin-marketplaces).

## What plugins contain

| Component | Location in a plugin | Loaded as | Use for |
| :-------- | :------------------- | :-------- | :------ |
| Skills | `skills/<name>/SKILL.md` | Model-invoked skill | Reusable procedures and domain knowledge. |
| Slash commands | `commands/<name>.md` or executable command files | `/name` command | User-invoked workflows. |
| Droids | `droids/<name>.md` | Task-callable subagent | Specialized agents with scoped prompts, tools, and models. |
| Hooks | `hooks/hooks.json` plus scripts | Lifecycle hooks | Validation, policy, formatting, logging, and context injection. |
| MCP servers | `mcp.json` | MCP tool configuration | External tools and data sources made available when the plugin is active. |

Native Droid plugins use `.factory-plugin/plugin.json`. Claude Code plugin layouts are also supported: `.claude-plugin/` is translated to `.factory-plugin/`, `agents/` is translated to `droids/`, and `.mcp.json` is translated to `mcp.json` when Droid copies the plugin into its cache.

## Manage plugins

Use the interactive UI for browsing and one-off work:

```text
/plugins
```

| Tab | Purpose |
| :-- | :------ |
| Browse | View and install plugins from registered marketplaces. |
| Installed | Update, uninstall, or inspect installed plugins. |
| Marketplaces | Add, update, or remove marketplaces. |

Use CLI commands for scripts and onboarding:

```bash
# Marketplace management
droid plugin marketplace add <url-or-local-path>
droid plugin marketplace list
droid plugin marketplace update [name]
droid plugin marketplace remove <name>

# Plugin management
droid plugin install <plugin@marketplace> --scope user
droid plugin install <plugin@marketplace> --scope project
droid plugin list --scope user
droid plugin update [plugin@marketplace] --scope project
droid plugin uninstall <plugin@marketplace> --scope project
```

Plugin IDs use `pluginName@marketplaceName`. Scoped npm package names are supported because Droid splits on the first `@` after the first character, so `@scope/plugin@marketplace` is valid.

## Build a plugin

A minimal native plugin looks like this:

```text
my-plugin/
├── .factory-plugin/
│   └── plugin.json
├── commands/
│   └── hello.md
├── skills/
│   └── code-review/
│       └── SKILL.md
├── droids/
│   └── reviewer.md
├── hooks/
│   ├── hooks.json
│   └── check.sh
├── mcp.json
└── README.md
```

<Warning>
  Keep `commands/`, `skills/`, `droids/`, `hooks/`, and `mcp.json` at the plugin root. Do not put them inside `.factory-plugin/`; that directory is for plugin metadata.
</Warning>

### Plugin manifest

Create `.factory-plugin/plugin.json`:

```json
{
  "name": "my-plugin",
  "description": "A helpful plugin description",
  "version": "1.0.0",
  "author": {
    "name": "Your Team"
  },
  "homepage": "https://github.com/your-org/my-plugin",
  "repository": "https://github.com/your-org/my-plugin",
  "license": "MIT",
  "keywords": ["review", "security"]
}
```

| Field | Source-validated behavior |
| :---- | :------------------------ |
| `name` | Plugin identity. Include it for native Droid and Claude Code compatibility. |
| `description` | Shown in browsing and installation surfaces when available. |
| `version` | Documentation metadata for the plugin. Git-based installation still tracks the installed commit hash. |
| `author`, `homepage`, `repository`, `license`, `keywords` | Optional metadata for attribution and discovery. |

### Commands

A Markdown command at `commands/review-pr.md` becomes `/review-pr`:

```markdown
---
description: Review the current PR for issues
---

Review the current pull request. Focus on: $ARGUMENTS
```

### Skills

A skill lives at `skills/<name>/SKILL.md`:

```markdown
---
name: code-review
description: Reviews code for correctness, safety, and maintainability. Use when reviewing code, checking PRs, or analyzing code quality.
---

Check for logic errors, security issues, missing tests, and unclear ownership. Return specific, actionable findings.
```

### Droids

A droid lives at `droids/<name>.md`:

```markdown
---
name: reviewer
description: Specialized code reviewer subagent
model: inherit
tools: ["Read", "Grep", "Glob"]
---

You are a senior code reviewer. Report correctness, security, and test coverage issues with severity and evidence.
```

See [Custom Droids](/harness/subagents) for the full droid configuration surface.

### Hooks

Plugin hooks live at `hooks/hooks.json` and may reference scripts in the plugin:

```json
{
  "PostToolUse": [
    {
      "matcher": "Create|Edit|ApplyPatch",
      "hooks": [
        {
          "type": "command",
          "command": "${DROID_PLUGIN_ROOT}/hooks/check.sh",
          "timeout": 30
        }
      ]
    }
  ]
}
```

Droid expands `${DROID_PLUGIN_ROOT}`, `$DROID_PLUGIN_ROOT`, `${CLAUDE_PLUGIN_ROOT}`, and `$CLAUDE_PLUGIN_ROOT` to the installed plugin cache path when the plugin loads. See [Hooks](/harness/hooks#plugin-hooks) for hook events, input, and output behavior.

### MCP servers

Plugin MCP servers use `mcp.json` at the plugin root:

```json
{
  "mcpServers": {
    "my-api": {
      "command": "npx",
      "args": ["-y", "@example/mcp-server"],
      "env": {
        "API_KEY": "${MY_API_KEY}"
      }
    }
  }
}
```

## Test locally

During development, add the plugin directory as a local marketplace and install from it:

```bash
mkdir -p my-plugin/.factory-plugin
# create my-plugin/.factory-plugin/plugin.json and any plugin components

droid plugin marketplace add ./my-plugin
droid plugin install my-plugin@my-plugin --scope user
```

Before sharing, verify:

- The plugin installs from a clean checkout.
- Commands work with and without `$ARGUMENTS`.
- Skills and droids have clear names and routing descriptions.
- Hook scripts use absolute paths or plugin-root variables.
- MCP servers do not embed secrets directly in `mcp.json`.
- The README explains what the plugin does, when to use it, and prerequisites.

## Marketplaces

A marketplace is a catalog of installable plugins. Droid reads `.factory-plugin/marketplace.json` first and falls back to `.claude-plugin/marketplace.json` for Claude Code compatibility.

```text
your-marketplace/
├── .factory-plugin/
│   └── marketplace.json
├── plugin-one/
│   └── .factory-plugin/
│       └── plugin.json
└── plugin-two/
    └── .factory-plugin/
        └── plugin.json
```

```json
{
  "name": "your-marketplace",
  "description": "A collection of team plugins",
  "owner": {
    "name": "Platform Team"
  },
  "plugins": [
    {
      "name": "plugin-one",
      "description": "Description of plugin one",
      "source": "./plugin-one"
    }
  ]
}
```

| Marketplace field | Required | Description |
| :---------------- | :------- | :---------- |
| `name` | Yes | Marketplace identifier. |
| `description` | No | Shown when browsing marketplaces. |
| `owner` | No | Contact metadata. |
| `plugins[].name` | Yes | Plugin identifier inside this marketplace. |
| `plugins[].source` | Yes | Relative path string or source object. |
| `plugins[].description`, `category`, `homepage`, `tags` | No | Browsing metadata. |

## Plugin sources

Each marketplace plugin entry has a `source` field.

| Source type | Shape | Use when | Pinning |
| :---------- | :---- | :------- | :------ |
| Relative path | `"./plugin-one"` | Plugin lives inside the marketplace repository. Absolute paths and paths that escape the marketplace directory are rejected. | Pin the marketplace source. |
| `github` | `{ "source": "github", "repo": "org/repo", "ref": "v1.0.0" }` | Plugin or marketplace is in a GitHub repository. | `ref` branch/tag or full 40-character `sha`. |
| `url` | `{ "source": "url", "url": "https://gitlab.com/org/repo.git" }` | Plugin or marketplace is on another Git host. | `ref` branch/tag or full 40-character `sha`. |
| `git-subdir` | `{ "source": "git-subdir", "url": "https://github.com/org/repo", "path": "plugins/foo" }` | Plugin lives in a subdirectory of a larger repository. | `ref` branch/tag or full 40-character `sha`. |
| `npm` | `{ "source": "npm", "package": "@org/plugin", "version": "^2.0.0" }` | Plugin is published to npm or a private npm-compatible registry. | `version` semver, range, or dist-tag. |

`npm` is valid only inside a marketplace's `plugins[].source`. `droid plugin marketplace add npm:<package>` is intentionally rejected. To distribute one npm plugin, create a small wrapper marketplace that lists the npm source.

### Add and pin marketplaces

`droid plugin marketplace add` accepts a GitHub URL, any other Git URL, or a local path. For Git URLs, append `#<ref>` to follow a branch or tag, or `@<40-character-sha>` to pin an exact commit:

```bash
droid plugin marketplace add https://github.com/Factory-AI/factory-plugins
droid plugin marketplace add 'https://github.com/your-org/plugins#v1.2.0'
droid plugin marketplace add https://github.com/your-org/plugins@1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b
droid plugin marketplace add ./your-local-marketplace
```

Local marketplace paths are resolved to absolute paths and cannot carry a ref or SHA pin.

### npm source details

| Field | Required | Description |
| :---- | :------- | :---------- |
| `package` | Yes | npm package name. Scoped packages such as `@scope/name` are supported. |
| `version` | No | Version, range, or dist-tag. Defaults to `latest`. URL, path, `file:`, `git+...`, and `npm:` alias specs are rejected. |
| `registry` | No | HTTPS registry URL with no embedded credentials, query string, or fragment. |
| `authTokenEnvVar` | No | Environment variable name containing the private registry token. Requires `registry` to have an effect. |

Droid installs npm-source plugins in a per-plugin scratch directory with `npm install --ignore-scripts --no-save --no-audit --no-fund`, then copies the resolved package root into the plugin cache. Lifecycle scripts do not run, global npm configuration is not mutated, and the package must ship ready-to-use files.

## Team and enterprise distribution

Register marketplaces and enable plugins through settings when you want teams to get them automatically:

```json
{
  "extraKnownMarketplaces": {
    "your-org-internal-plugins": {
      "source": {
        "source": "github",
        "repo": "your-org/internal-plugins",
        "ref": "v1.2.0"
      }
    }
  },
  "enabledPlugins": {
    "code-standards@your-org-internal-plugins": true
  }
}
```

The installation scope follows where the setting is defined: org-managed settings install as org scope, user settings install as user scope, and project settings install as project scope.

Use `strictKnownMarketplaces` in managed settings when an organization wants to restrict marketplace sources to an approved list. See [Internal Plugin Marketplaces](/enterprise/internal-plugin-marketplaces) for centralized governance.

## Versioning and updates

| Source | Tracked version | Update behavior |
| :----- | :-------------- | :-------------- |
| Relative path inside a Git marketplace | Marketplace commit hash | Update the marketplace to move the plugin. |
| `github`, `url`, `git-subdir` plugin source | Plugin source commit hash | Update fetches the latest allowed commit unless pinned by `sha`. |
| `npm` plugin source | Resolved npm package version and metadata | Update follows the `version` spec, such as `latest` or `^2.0.0`. |
| Plugin manifest `version` | Metadata only | Useful for humans and release notes, but Git-based installs are tracked by commit. |

## Discover plugins

Factory maintains an official marketplace at `Factory-AI/factory-plugins`:

```bash
droid plugin marketplace add https://github.com/Factory-AI/factory-plugins
```

Common official plugins include:

| Plugin | Purpose |
| :----- | :------ |
| [droid-control](/software-factory/droid-control) | Terminal, browser, and computer automation for demos, QA, and verification. |
| droid-evolved | Skills for session navigation, writing, skill creation, design, frontend work, and browser automation. |
| security-engineer | Security review, threat modeling, commit scanning, and vulnerability validation. |

Droid can also install compatible Claude Code plugins. Claude Code layouts are translated during cache copy, not by mutating the source repository.

## Best practices

| Practice | Why it matters |
| :------- | :------------- |
| Keep plugins focused | Small plugins are easier to review, compose, and retire. |
| Document capabilities and boundaries | Users need to know when to use the plugin, prerequisites, and what data or tools it touches. |
| Avoid hardcoded machine paths | Use plugin-root variables for plugin files and environment variables for secrets. |
| Test on a clean machine | Plugin installs should not depend on uncommitted local files or global state. |
| Ship prebuilt npm packages | `--ignore-scripts` means npm plugin sources cannot rely on postinstall builds. |
| Govern high-trust plugins | Use managed settings and [Internal Plugin Marketplaces](/enterprise/internal-plugin-marketplaces) for approved enterprise distribution. |

<RelatedLinks>
  <RelatedLink href='/harness/subagents' title='Custom droids (subagents)'>
    Define specialized subagents packaged inside a plugin.
  </RelatedLink>
  <RelatedLink href='/enterprise/internal-plugin-marketplaces' title='Internal Plugin Marketplaces'>
    Govern approved plugin catalogs for your organization.
  </RelatedLink>
</RelatedLinks>
