Plugins are in closed beta. To request access, contact support@cognition.ai. Behavior and configuration may change in future releases.
/<plugin>:<skill> slash commands, and it can pull in other plugins it depends
on automatically.
A plugin is just a source that contains:
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.mdat the plugin root is injected as an always-on rule in every session, alongside your project’s own rules. Markdown files in arules/folder are loaded too, with the sametriggerfrontmatter and activation types as Windsurf rules. - Custom subagents —
agents/<name>.mdoragents/<name>/AGENT.mdprofiles (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.jsonat the plugin root registers lifecycle hooks that run in every session where the plugin is installed. - MCP servers — an
mcp_config.jsonat the plugin root declares MCP servers ("mcpServers": { "<name>": { … } }) that start with the session. Claude plugins’ root.mcp.jsonand manifestmcpServersfield are also honored.
Installing a plugin
A plugin source can be a GitHubowner/repo, a git URL, or a local path:
-y / --yes to skip the
prompt.
Plugins are installed at the user level and are available across all your
projects.
Managing plugins
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).
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/repoor a git URL. All GitHub forms of the same repo (owner/repo, the HTTPS URL, the.gitURL, the SSH form) refer to the same identity. - A glob pattern — any entry containing
*. The*matches any sequence of characters, including/:acme/*matches all ofacme’s GitHub repos,*/secretsmatches a repo namedsecretsunder any owner, andhttps://gitlab.com/acme/*matches any repo under that path. - The lone
"*", which matches everything else (a full lockdown).
- 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
requiredPluginsandoptionalPlugins— 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.
- 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.
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:- Enterprise — the account-wide managed manifest, configured by an admin.
- 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.
- Repo — the
requiredPlugins/optionalPlugins/forbiddenPluginsin a checkout’s.devin/config.json, discovered by walking up from your working directory. - User — plugins you install yourself with
devin plugins install.
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.
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’sforbiddenPlugins
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:
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.

