This repository builds GitHub Copilot CLI plugins for marketplace distribution. Read this before writing any code. These rules are non-negotiable.
Every artifact in this repo is a GitHub Copilot CLI plugin — installable via
copilot plugin marketplace add <repo> and shareable across teams.
A plugin bundles any combination of: agents, skills, MCP servers, LSP servers, and hooks.
.
├── .github/
│ └── plugin/
│ └── marketplace.json # Marketplace manifest — REQUIRED
├── plugins/
│ └── <plugin-name>/
│ ├── .github/
│ │ └── plugin/
│ │ └── plugin.json # Plugin manifest — REQUIRED
│ ├── .mcp.json # MCP servers config (optional)
│ ├── agents/
│ │ └── *.agent.md # Agent definitions
│ ├── skills/
│ │ └── <skill-name>/
│ │ └── SKILL.md # Skill definitions
│ └── README.md # Required
└── AGENTS.md # This file
These rules apply to all work in this monorepo. No exceptions.
- Work on one plugin at a time — never edit multiple plugins in a single change unless explicitly requested
- Never add secrets — no tokens, credentials, or private endpoints in any file
- Prefer minimal changes — improve correctness, security, and clarity with smallest viable surface area
- Keep instructions stable — avoid time-dependent guidance (e.g., "before August 2025")
- Use forward slashes — always use forward slashes in all file paths, never backslashes
Use these commands to manage plugins:
| Command | Description |
|---|---|
copilot plugin install SPECIFICATION |
Install a plugin from marketplace, GitHub repo, Git URL, or local path |
copilot plugin uninstall NAME |
Remove a plugin |
copilot plugin list |
List installed plugins |
copilot plugin update NAME |
Update a specific plugin |
copilot plugin update --all |
Update all installed plugins |
copilot plugin disable NAME |
Temporarily disable a plugin without uninstalling it |
copilot plugin enable NAME |
Re-enable a disabled plugin |
copilot plugin marketplace add SPECIFICATION |
Register a marketplace |
copilot plugin marketplace list |
List registered marketplaces |
copilot plugin marketplace browse NAME |
Browse marketplace plugins |
copilot plugin marketplace remove NAME |
Unregister a marketplace |
| Format | Example | Description |
|---|---|---|
| Marketplace | plugin@marketplace |
Plugin from a registered marketplace |
| GitHub | OWNER/REPO |
Root of a GitHub repository |
| GitHub subdir | OWNER/REPO:PATH/TO/PLUGIN |
Subdirectory in a repository |
| Git URL | https://github.com/o/r.git |
Any Git URL |
| Local path | ./my-plugin or /abs/path |
Local directory |
Required at .github/plugin/marketplace.json. Copilot CLI also recognizes this file in .claude-plugin/.
{
"name": "my-marketplace",
"owner": {
"name": "Your Organization",
"email": "plugins@example.com"
},
"metadata": {
"description": "Curated plugins for our team",
"version": "1.0.0"
},
"plugins": [
{
"name": "frontend-design",
"description": "Create a professional-looking GUI ...",
"version": "2.1.0",
"source": "./plugins/frontend-design"
},
{
"name": "security-checks",
"description": "Check for potential security vulnerabilities ...",
"version": "1.3.0",
"source": "./plugins/security-checks"
}
]
}| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Kebab-case marketplace name. Max 64 chars. |
owner |
object | Yes | { name, email? } — marketplace owner info. |
plugins |
array | Yes | List of plugin entries. |
metadata |
object | No | { description?, version?, pluginRoot? } |
| Field | Type | Required | Description |
|---|---|---|---|
name |
string | Yes | Kebab-case plugin name. Max 64 chars. |
source |
string | object | Yes |
description |
string | No | Plugin description. Max 1024 chars. |
version |
string | No | Plugin version. |
author |
object | No | { name, email?, url? } |
homepage |
string | No | Plugin homepage URL. |
repository |
string | No | Source repository URL. |
license |
string | No | License identifier. |
keywords |
string[] | No | Search keywords. |
category |
string | No | Plugin category. |
tags |
string[] | No | Additional tags. |
commands |
string | string[] | No |
agents |
string | string[] | No |
skills |
string | string[] | No |
hooks |
string | object | No |
mcpServers |
string | object | No |
lspServers |
string | object | No |
strict |
boolean | No | When true (the default), plugins must conform to the full schema and validation rules. When false, relaxed validation is used. |
Rules:
nameis the marketplace identifier — use lowercase letters, numbers, and hyphensowner.nameandowner.emailidentify the marketplace maintainermetadata.descriptionprovides marketplace-level descriptionmetadata.versionfollows semantic versioning:major.minor.patchpluginsarray lists all available plugins in this marketplacesourceis the path to the plugin directory, relative to repository root- Source paths can use
./plugins/plugin-nameorplugins/plugin-name(both resolve the same)
Required at plugins/<plugin-name>/.github/plugin/plugin.json. Copilot CLI also recognizes this file at the plugin root.
| Field | Type | Description |
|---|---|---|
name |
string | Kebab-case plugin name (letters, numbers, hyphens only). Max 64 chars. |
| Field | Type | Description |
|---|---|---|
description |
string | Brief description. Max 1024 chars. |
version |
string | Semantic version (e.g., 1.0.0). |
author |
object | name (required), email (optional), url (optional). |
homepage |
string | Plugin homepage URL. |
repository |
string | Source repository URL. |
license |
string | License identifier (e.g., MIT). |
keywords |
string[] | Search keywords. |
category |
string | Plugin category. |
tags |
string[] | Additional tags. |
These tell the CLI where to find your plugin's components. All are optional. The CLI uses default conventions if omitted.
| Field | Type | Default | Description |
|---|---|---|---|
agents |
string | string[] | agents/ |
skills |
string | string[] | skills/ |
commands |
string | string[] | — |
hooks |
string | object | — |
mcpServers |
string | object | — |
lspServers |
string | object | — |
{
"name": "my-dev-tools",
"description": "React development utilities",
"version": "1.2.0",
"author": {
"name": "Jane Doe",
"email": "jane@example.com"
},
"license": "MIT",
"keywords": ["react", "frontend"],
"agents": "agents/",
"skills": ["skills/", "extra-skills/"],
"hooks": "hooks.json",
"mcpServers": ".mcp.json"
}Rules:
namebecomes the plugin identifier- Lowercase letters, numbers, hyphens only
- Never use "github" or "copilot" as part of the name
- Follow semantic versioning:
major.minor.patch - Component paths can be strings or arrays of strings
- All paths are relative to the plugin root
| Item | Path |
|---|---|
| Installed plugins | ~/.copilot/state/installed-plugins/MARKETPLACE/PLUGIN-NAME (installed via a marketplace) and ~/.copilot/state/installed-plugins/PLUGIN-NAME (installed directly) |
| Marketplace cache | ~/.copilot/state/marketplace-cache/ |
| Plugin manifest | plugin.json, .github/plugin/plugin.json, or .claude-plugin/plugin.json |
| Marketplace manifest | .github/plugin/marketplace.json or .claude-plugin/marketplace.json |
| Agents | agents/ (default, overridable in manifest) |
| Skills | skills/ (default, overridable in manifest) |
| Hooks config | hooks.json or hooks/hooks.json |
| MCP config | .mcp.json or .github/mcp.json |
| LSP config | lsp.json or .github/lsp.json |
If you install multiple plugins it's possible that some custom agents, skills, MCP servers, or tools supplied via MCP servers have duplicate names. In this situation, the CLI determines which component to use based on a precedence order.
If you have a project-level custom agent or skill with the same name or ID as one in a plugin you install, the agent or skill in the plugin is silently ignored. The plugin cannot override project-level or personal configurations. Custom agents are deduplicated using their ID, which is derived from its file name (for example, if the file is named reviewer.agent.md, the agent ID is reviewer). Skills are deduplicated by their name field inside the SKILL.md file.
Loading order for agents:
~/.copilot/agents/(user, .github convention)<project>/.github/agents/(project)<parents>/.github/agents/(inherited, monorepo)~/.claude/agents/(user, .claude convention)<project>/.claude/agents/(project)<parents>/.claude/agents/(inherited, monorepo)PLUGIN: agents/dirs (plugin, by install order)- Remote org/enterprise agents (remote, via API)
Loading order for skills:
<project>/.github/skills/(project)<project>/.agents/skills/(project)<project>/.claude/skills/(project)<parents>/.github/skills/etc. (inherited)~/.copilot/skills/(personal-copilot)~/.claude/skills/(personal-claude)PLUGIN: skills/dirs (plugin)COPILOT_SKILLS_DIRSenv + config (custom)
Then commands (.claude/commands/) are loaded, and skills override commands.
If you install a plugin that defines an MCP server with the same server name as an MCP server you have already installed, the plugin's definition takes precedence. You can use the --additional-mcp-config command-line option to override an MCP server configuration with the same name, installed using a plugin.
Loading order for MCP servers:
~/.copilot/mcp-config.json(lowest priority).vscode/mcp.json(workspace)PLUGIN: MCP configs(plugins)--additional-mcp-configflag (highest priority)
Built-in tools and agents are always present and cannot be overridden by user-defined components:
- tools: bash, view, apply_patch, glob, rg, task, ...
- agents: explore, task, code-review, general-purpose, research
Agents live in plugins/<plugin-name>/agents/<agent-name>.agent.md.
Agent ID is derived from the filename (without .agent.md extension). For example, reviewer.agent.md has agent ID reviewer.
# Agent Name
> Brief description of what this agent does.
## When to Use
Describe when to invoke this agent.
## Capabilities
List the agent's capabilities.
## Instructions
Detailed instructions for the agent.Skills live in plugins/<plugin-name>/skills/<skill-name>/SKILL.md.
Skill name is defined by the name field inside the SKILL.md file. Skills are deduplicated by name, so ensure unique names across all skills.
# Skill Name
> Brief description of what this skill does.
## Available Tools
List the tools this skill has access to.
## Instructions
Detailed instructions for the skill.
## Examples
Provide usage examples.MCP server configs can be defined at the plugin root or in a dedicated .mcp.json file referenced in plugin.json.
{
"mcpServers": {
"server-name": {
"command": "node",
"args": ["path/to/server.js"],
"env": {
"API_KEY": "${API_KEY}"
}
}
}
}- Never hardcode credentials — use
${ENV_VAR}in configs,process.env.Xin code - Validate all inputs before processing
- Use structured errors — never raw exception messages to users
- No
eval()or dynamicexec()— reject any generated code execution - Always use forward slashes in all file paths to prevent cross-platform issues
- Sanitize all file paths — prevent path traversal
- Validate before processing, not after
Test plugins locally before publishing:
# Add local marketplace
copilot plugin marketplace add ./github-copilot-authstack
# List available plugins
copilot plugin list
# Install a specific plugin
copilot plugin install mcp-auth
# Test the plugin
copilot <agent-name> "Your prompt"Test with real workflow scenarios to ensure agents and skills work as expected.
Required for every plugin — Every plugin README must include these 7 sections.
- Purpose — what problem this solves (2–3 sentences)
- Installation —
copilot plugin marketplace add <repo> - Components reference — every agent, skill, and MCP server
- Configuration — required env vars + config examples
- Usage examples — at least one end-to-end walkthrough
- Troubleshooting — the 3 most common failure modes
- Security — what credentials are needed and how to store them
Important: If behavior changes, update the plugin README in the same PR.
Marketplace
- [ ] marketplace.json has name, owner, metadata, plugins array
- [ ] All plugin source paths are correct relative to repo root
- [ ] Marketplace name is lowercase, hyphens only
Plugin
- [ ] plugin.json has name, description, version, homepage, license
- [ ] name is lowercase, hyphens only, no reserved words
- [ ] Component paths are correct (agents, skills, mcpServers, etc.)
- [ ] plugin.json exists at .github/plugin/plugin.json or plugin root
Agents
- [ ] All agent IDs are unique (derived from filename)
- [ ] All .agent.md files are valid markdown
- [ ] Forward slashes in all file paths
Skills
- [ ] All skill names are unique (defined in SKILL.md)
- [ ] All SKILL.md files are valid markdown
- [ ] Forward slashes in all file paths
MCP Servers
- [ ] All server names are unique
- [ ] No hardcoded credentials
- [ ] Environment variables use ${ENV_VAR} format
Security
- [ ] Zero hardcoded credentials anywhere in the repo
- [ ] All inputs are validated
- [ ] Error messages are user-friendly and actionable
Testing
- [ ] Plugin loaded locally and confirmed working
- [ ] All agents tested with real scenarios
- [ ] All skills tested with real scenarios
- [ ] Integration tested with copilot CLI
Documentation
- [ ] README covers all 7 required sections
| Artifact | Convention | Example |
|---|---|---|
| Marketplace name | kebab-case |
team-plugins |
| Plugin name | kebab-case |
mcp-auth |
| Agent filename | <name>.agent.md |
scalekit-mcp-auth-troubleshooter.agent.md |
| Agent ID | derived from filename | scalekit-mcp-auth-troubleshooter |
| Skill directory | kebab-case |
mcp-auth |
| Skill name | defined in SKILL.md | MCP Auth |
| MCP server name | kebab-case |
scalekit-auth-server |
Note: All file paths must use forward slashes (/) regardless of operating system.
- Create feature branch:
git checkout -b feature/plugin-name - Update marketplace.json: Add or update plugin entry
- Implement plugin: Create plugin directory with all required files
- Test locally: Add marketplace and test all components
- Commit changes: Use conventional commit format
- Push to GitHub:
git push origin feature/plugin-name - Create PR: Request review and merge to main
- Tag release:
git tag v1.0.0 && git push --tags
Provide these instructions to users:
# Add the marketplace
copilot plugin marketplace add octo-org/octo-repo
# List available plugins
copilot plugin list
# Install a specific plugin
copilot plugin install mcp-auth
# Use an agent from the plugin
copilot <agent-name> "Your prompt"- Incorrect source paths in marketplace.json (must be relative to repo root)
- Missing required fields in plugin.json
- Using reserved words in plugin names (github, copilot, etc.)
- Hardcoding credentials or API keys
- Not validating inputs
- Missing README documentation sections
- Not testing with copilot CLI before publishing
- Agent ID conflicts (duplicate agent IDs across plugins)
- Skill name conflicts (duplicate skill names across plugins)
- MCP server name conflicts (duplicate server names)
- Not understanding loading order and precedence rules