> ## Documentation Index
> Fetch the complete documentation index at: https://docs.devinenterprise.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Plugins

> Install and share bundles of skills from a repo, git URL, or local folder.

<Note>
  Plugins are in **beta**. Behavior and configuration may change in future releases.
</Note>

A **plugin** is a bundle of [skills](/cli/extensibility/skills/overview) you can
install from a GitHub repo, a git URL, or a local folder and reuse across
projects. Installing a plugin makes its skills available as
`/<plugin>:<skill>` slash commands, and it can pull in other plugins it depends
on automatically.

A plugin is just a source that contains:

```
my-plugin/
├── .devin-plugin/
│   └── plugin.json     # The plugin manifest
└── skills/
    └── review/
        └── SKILL.md    # An ordinary skill
```

The `skills/` directory holds ordinary skills — plugins introduce no new skill
format. See [Creating Skills](/cli/extensibility/skills/creating-skills) for the
`SKILL.md` format.

***

## Installing a plugin

A plugin source can be a GitHub `owner/repo`, a git URL, or a local path:

```bash theme={null}
# From GitHub
devin plugins install acme/review-tools

# From any git host
devin plugins install https://gitlab.com/acme/review-tools.git

# From a local folder (great for authoring)
devin plugins install ./my-plugin
```

Before installing, Devin shows what the plugin adds — the skills it provides,
any required plugins that will be auto-installed, and any policy it introduces
(for example, if it forbids other plugins). Pass `-y` / `--yes` to skip the
prompt.

Plugins are installed at the **user** level and are available across all your
projects.

***

## Managing plugins

```bash theme={null}
# List installed plugins, their versions, and whether any are blocked by policy
devin plugins list

# Show a plugin's skills and its required/optional/forbidden lists
devin plugins info review-tools

# Re-fetch a plugin (or all plugins) at the latest version
devin plugins update review-tools
devin plugins update

# Remove a plugin (auto-installed required plugins are left in place)
devin plugins remove review-tools
```

Local plugins are linked directly to their source folder, so edits are live:
`devin plugins install ./my-plugin` → edit `skills/<name>/SKILL.md` → changes
apply on the next session, no `update` needed.

***

## The manifest

`.devin-plugin/plugin.json` describes the plugin. Only `name` is required, and
it must be unique among installed plugins (it is the `/<name>:…` namespace).

```jsonc theme={null}
{
  "name": "review-tools",
  "version": "1.0.0",
  "description": "Code-review skills for our team",
  "requiredPlugins": [
    "acme/secure-base",
    { "source": "github", "repo": "acme/audit-logging" }
  ],
  "optionalPlugins": [
    "acme/deploy-tools",
    { "source": "url", "url": "https://gitlab.com/acme/extra.git" }
  ],
  "forbiddenPlugins": ["sketchy-org/bad-plugin", "acme/*", "*"]
}
```

Supported metadata fields: `name`, `version`, `description`, `author`
(`{ name, email }`), `homepage`, `repository`, `license`, and `keywords`.

A dependency entry is a **source** — either a string shorthand or an object:

* `"owner/repo"` → GitHub
* `"https://…"`, `"git@…"`, `"ssh://…"` → git URL
* `{ "source": "github", "repo": "owner/repo" }`
* `{ "source": "url", "url": "https://gitlab.com/team/plugin.git" }`

All GitHub forms for the same repo (`owner/repo`, the HTTPS URL, the `.git`
URL, the SSH form) refer to the same plugin identity.

***

## Dependencies and governance

A plugin can declare three lists, which let a single plugin act as a curated,
governed collection of other plugins.

### `requiredPlugins`

Auto-installed (recursively) when the plugin is installed. If a required plugin
is blocked by policy, the whole install fails — there is no partial install.

### `optionalPlugins`

An **allow-list** of plugins this plugin endorses. They are **not**
auto-installed; the list only matters as a carve-out against a forbidden entry
(see below).

### `forbiddenPlugins`

A **deny-list**. Each entry is one of:

* An exact plugin identity, written as `owner/repo`, a git URL, or a local path.
* A **glob pattern** — any entry containing `*`. The `*` matches any sequence of
  characters, including `/`. Patterns are normalized into canonical-identity
  space first, so `acme/*` becomes `https://github.com/acme/*` (all of `acme`'s
  GitHub repos), `*/secrets` matches a repo named `secrets` under any owner, and
  `https://gitlab.com/acme/*` matches any repo under that path.
* The lone `"*"`, which matches every other plugin (an un-defeatable lockdown).

The policy rules are:

* **Deny wins.** A plugin is blocked if any installed plugin forbids it (via its
  exact identity, a matching glob, or `"*"`).
* **Self-override.** A plugin's own `requiredPlugins`, `optionalPlugins`, and
  itself are exempt from its **own** forbidden list. So
  `forbiddenPlugins: ["*"]` together with `optionalPlugins: [B, C]` means "allow
  myself, B, and C; forbid everything else."
* **No cross-plugin re-permitting.** One plugin's allow-lists cannot re-permit
  what **another** plugin forbids. An installed plugin with
  `forbiddenPlugins: ["*"]` is an un-defeatable lockdown.
* **Default open.** If no installed plugin forbids anything, nothing is blocked.

Policy is enforced at two points:

* **Install time** — installing a blocked plugin (or one whose required plugins
  can't be satisfied, or whose name collides with an installed plugin) is
  refused.
* **Load time** — if a plugin becomes blocked after install (for example, a
  forbidding plugin is installed later), it stays on disk but its skills are
  skipped at session start, with a warning naming the plugin that forbids it.
