Skip to main content
Plugins are in closed beta. To request access, contact support@cognition.ai. Behavior and configuration may change in future releases.
A plugin is a bundle of skills 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:
The skills/ directory holds ordinary skills — plugins introduce no new skill format. See Creating Skills for the SKILL.md format. Beyond skills, a plugin can ship:
  • Rules — an AGENTS.md at the plugin root is injected as an always-on rule in every session, alongside your project’s own rules. Markdown files in a rules/ folder are loaded too, with the same trigger frontmatter and activation types as Windsurf rules.
  • Custom subagentsagents/<name>.md or agents/<name>/AGENT.md profiles (the same custom subagent format as project subagents), available as <plugin>:<name>. Plugin subagents currently load in local Devin agents only — the CLI and Devin Desktop — not in cloud Devin sessions.
  • Hooks — a hooks.json at the plugin root registers lifecycle hooks that run in every session where the plugin is installed.
  • MCP servers — an mcp_config.json at the plugin root declares MCP servers ("mcpServers": { "<name>": { … } }) that start with the session. Claude plugins’ root .mcp.json and manifest mcpServers field are also honored.

Installing a plugin

A plugin source can be a GitHub owner/repo, a git URL, or a local path:
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

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).
Supported metadata fields: name, version, description, author ({ name, email }), homepage, repository, license, and keywords. Two more optional fields control where assets load from: skills — a path or array of paths to skill directories, replacing the default skills/ — and mcpServers — MCP declaration file paths or an inline server map, read in addition to the root conventions. A dependency entry is a source — either a string shorthand or an object: 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 of plugin identities and glob patterns. forbiddenPlugins entries are matched against plugin identities:
  • An exact identity, written as owner/repo or a git URL. All GitHub forms of the same repo (owner/repo, the HTTPS URL, the .git URL, the SSH form) refer to the same identity.
  • A glob pattern — any entry containing *. The * matches any sequence of characters, including /: acme/* matches 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 everything else (a full lockdown).
The lists combine deny-wins:
  • Deny wins. A plugin is blocked if any active manifest or installed plugin forbids it. If nothing forbids anything, nothing is blocked.
  • Self-override. A manifest’s (or plugin’s) own requiredPlugins and optionalPlugins — and, for a plugin, the plugin itself — are exempt from its own forbidden list, so "forbiddenPlugins": ["*"] plus "optionalPlugins": ["acme/approved"] means “allow only what this manifest lists; forbid everything else.” The carve-out covers only those direct entries, not a required plugin’s transitive dependencies — list those explicitly under a lockdown.
  • No cross-scope re-permitting. One manifest’s or plugin’s allow-list cannot re-permit what another forbids. A "forbiddenPlugins": ["*"] lockdown can’t be defeated from a lower scope.
Enforcement happens 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 — a plugin blocked after it’s already installed stays on disk, but its skills are skipped at session start with a warning naming the forbidder.
A forbidden identity can also be a local path (for plugins installed from a local folder), in addition to the owner/repo and git-URL forms above.

Inheritance and levels

Plugins aren’t declared in one place. Beyond your own installs, plugins can be required, endorsed, or forbidden by your repo and by your organization’s admin. Each source is a level, and the levels are ranked by authority, highest first:
  1. Enterprise — the account-wide managed manifest, configured by an admin.
  2. Org — an org-level managed manifest, layered below its account (an org can add to what its account declares, but can’t overrule it). This applies only to cloud Devin sessions: the CLI authenticates at the account level and has no org context, so org-level requires and forbids don’t reach CLI users. Put anything you need enforced in the CLI in the enterprise/account manifest.
  3. Repo — the requiredPlugins / optionalPlugins / forbiddenPlugins in a checkout’s .devin/config.json, discovered by walking up from your working directory.
  4. User — plugins you install yourself with devin plugins install.
Every level declares the same three lists, and within a level they combine with the same deny-wins, self-override rules as a single manifest. What the levels add on top is one rule: higher authority wins.

Higher authority wins

  • A lower level can never re-permit what a higher level forbids.
  • A lower level can never forbid what a higher level requires — the forbid is ignored and the plugin still loads.
So an admin can mandate a plugin no repo or user can opt out of, and forbid a plugin no lower level can bring back.

A denylist is only overridden at its own level

Because allow-lists don’t cross levels, the only way to carve an exception out of a denylist is at the same level that declared it. A level’s forbiddenPlugins is overridden only by that same manifest’s own optionalPlugins (or requiredPlugins) — never by a list at a lower level. For example, an enterprise-level managed manifest can lock the account down to a single approved plugin:
This means “across the whole account, allow only acme/approved and forbid every other plugin.” No org, repo, or user can widen that allow-list — not by installing a plugin, and not by adding it to a lower level’s optionalPlugins. The carve-out also covers only the entries this manifest lists directly; a required plugin’s own transitive dependencies aren’t exempt, so list those explicitly under a lockdown.

Conflicts and dependencies

  • A require and a forbid for the same plugin at the same level but from different manifests (for example two separately installed user-level plugins) resolve to the forbid — an allow-list only exempts entries in its own manifest, so it can’t rescue a plugin another manifest forbids. (Within a single manifest, its own required/optional stay exempt from its own forbids, as above.)
  • A plugin blocked by governance soft-fails: at session start its skills are skipped with a warning naming the forbidder, rather than aborting the session.
  • Being depended upon grants no exemption. A plugin pulled in only as a transitive dependency is still subject to every forbid that applies to it, and it inherits the highest authority level of any plugin that requires it.