This guide explains how to author a plugin directly in this repo (under
plugins/*), as opposed to porting one from Cursor (like thermos/). Use
plugins/example-agent/ as a working template.
plugins/<plugin-name>/
├── plugin.json # manifest (required)
├── README.md # what the plugin does and how to install it
├── LICENSE # license for the plugin
├── agents/
│ └── <agent>.agent.md # one or more custom review/automation agents
└── skills/
└── <skill>/
└── SKILL.md # one or more user/model-invocable skills
{
"name": "example-agent",
"description": "Short description shown to users.",
"version": "0.1.0",
"license": "MIT",
"agents": "agents/",
"skills": ["skills/"]
}Rules enforced by scripts/validate-copilot-plugin.mjs:
agentsmust be a non-empty string path pointing to an existing directory.skillsmust be a non-empty array of paths, each pointing to an existing directory.- Every file in the
agents/directory must be named*.agent.md. - Every skill subdirectory must contain a
SKILL.mdfile. - Text files (
.json,.md,.txt) must not contain Cursor-only terms (/add-plugin thermos,subagent_type,run_in_background).
Each agent file starts with YAML front matter and a Markdown body that is the agent's system prompt:
---
name: example-review
description: One-line description of what this agent reviews or does.
---
# Example Review Agent
You are a Copilot custom agent. ...Each skill is a directory with a SKILL.md:
---
name: example
description: When to invoke this skill and what it does.
user-invocable: true
---
# Example Skill
Step-by-step instructions the agent follows when this skill runs.npm run validate:allvalidate:all automatically discovers every directory containing a plugin.json
(top-level plugins like thermos/ and everything under plugins/*), so a new
plugin is covered as soon as it has a manifest.
copilot plugin install ./plugins/<plugin-name>