Making Claude Code Plugins Work with Copilot CLI
Making Claude Code Plugins Work with Copilot CLI
GitHub’s Copilot CLI went GA in February 2026 with a plugin system that closely mirrors Claude Code’s. If you maintain a Claude Code plugin, you can make it work with both tools with minimal effort.
This guide covers what’s compatible, what’s not, and the concrete steps to make one repo serve both ecosystems.
TL;DR
Copilot CLI reads .claude-plugin/plugin.json natively. Most Claude Code plugins work with zero changes.
Fully portable — works on both, no changes needed
- Plugin manifest —
.claude-plugin/plugin.jsonread by both tools - Skills —
skills/<name>/SKILL.mdidentical format and paths - MCP servers —
.mcp.jsonsame schema
Portable with graceful degradation
- Agents — extra frontmatter (
model,permissionMode, etc.) ignored by Copilot CLI; declare paths explicitly inplugin.jsonand.mdfiles work for both - Hooks —
PreToolUse/PostToolUsecommand hooks work in both (watch PascalCase vs camelCase); 12 Claude Code-only events and prompt/agent handler types degrade silently
Not portable — Claude Code only
- Commands (
commands/) — use skills instead - Styles (
styles/) — no Copilot CLI equivalent - Advanced hooks —
PermissionRequest,SubagentStart,InstructionsLoaded, etc. - LLM-based hook handlers —
promptandagenttypes - Context hierarchy — layered CLAUDE.md (user, project, per-directory)
Why Portability Matters
The feature sets have converged significantly. Both tools now support plugins, skills, agents, hooks, and MCP servers – and both use markdown files with YAML frontmatter as the primary authoring format. Users are already running both tools depending on the task. A portable plugin doubles your audience without doubling your maintenance.
Format Comparison
Plugin Manifest
The manifest tells each tool where to find your plugin’s components.
| Claude Code | Copilot CLI | |
|---|---|---|
| Location | .claude-plugin/plugin.json | Root plugin.json, .claude-plugin/plugin.json, or .github/plugin/plugin.json |
| Required fields | name, description, version, author | name, description, version, author |
| Optional fields | agents, skills, hooks, commands, styles | agents, skills, hooks, mcpServers |
The schema is nearly identical. Copilot CLI accepts plugin.json in multiple locations – including .claude-plugin/plugin.json, the repo root, and .github/plugin/. This means Claude Code’s standard layout works with Copilot CLI out of the box – no symlinks or extra files needed.
Claude Code plugin.json:
{
"name": "my-plugin",
"description": "My plugin",
"version": "1.0.0",
"author": { "name": "Jane Doe" },
"skills": "skills/",
"agents": [
"agents/reviewer.md"
],
"hooks": "hooks/hooks.json"
}
Copilot CLI plugin.json:
{
"name": "my-plugin",
"description": "My plugin",
"version": "1.0.0",
"author": { "name": "Jane Doe" },
"skills": "skills/",
"agents": "agents/",
"hooks": "hooks.json",
"mcpServers": ".mcp.json"
}
Claimed differences vs tested reality:
- Location: Copilot CLI reads
.claude-plugin/plugin.jsonnatively. No symlink needed. ✅ Tested - Agents: Claude Code uses an array of file paths; Copilot CLI accepts a directory path. Both accept
.mdfiles. ✅ Tested — Copilot installs.mdagents from Claude Code layout - Hooks: Claude Code expects
hooks/hooks.json(subdirectory). Copilot CLI follows the path declared in plugin.json, so"hooks": "hooks/hooks.json"works. ✅ Tested - MCP: Copilot CLI references MCP config via
mcpServersin plugin.json; Claude Code uses.mcp.jsonat the plugin root (auto-discovered, not declared in plugin.json). - LSP: Claude Code supports
.lsp.jsonfor language servers; Copilot CLI useslspServersin plugin.json. - Commands/Styles: Claude Code supports
commands/andstyles/directories; Copilot CLI does not have these concepts.
Skills
Skills are the most portable component. Both tools use the same format.
| Claude Code | Copilot CLI | |
|---|---|---|
| File name | SKILL.md | SKILL.md |
| Directory | skills/<name>/SKILL.md | skills/<name>/SKILL.md |
| User-level | ~/.claude/skills/ | ~/.copilot/skills/ or ~/.claude/skills/ |
| Project-level | .claude/skills/ | .github/skills/ or .claude/skills/ |
| Frontmatter | name, description (required) | name, description (required), license (optional) |
| Invocation | /skill-name | /skill-name |
Copilot CLI explicitly supports .claude/skills/ as a lookup path, so your existing skills work without changes.
Agents
Agent files are the biggest format difference between the two tools.
| Claude Code | Copilot CLI | |
|---|---|---|
| File extension | .md | .agent.md |
| Directory | agents/ | agents/ |
| User-level | ~/.claude/agents/ | ~/.copilot/agents/ |
| Project-level | .claude/agents/ | .github/agents/ |
| Frontmatter fields | name, description, tools, model, color, permissionMode, maxTurns, skills, mcpServers, hooks, memory | name, description, tools |
Claude Code agents have significantly richer frontmatter (model selection, color, permission modes, hooks, memory, skills injection). Copilot CLI agents are simpler – name, description, tools, and the markdown body.
Making agents work for both: You can include Claude Code-specific frontmatter fields; Copilot CLI ignores fields it doesn’t recognize. Despite the documented preference for .agent.md, testing shows Copilot CLI installs .md agent files from the Claude Code layout without issues. Runtime discovery of .md agents needs further testing.
Hooks
Hooks have the largest gap in capability between the two tools.
| Claude Code | Copilot CLI | |
|---|---|---|
| Config file | hooks/hooks.json (plugin) or .claude/settings.json | hooks.json |
| Hook events | 18 events | 6 events |
| Handler types | command, prompt, agent | command only |
| Matchers | Regex on tool name, agent type, etc. | Supported |
Claude Code events (18): SessionStart, UserPromptSubmit, PreToolUse, PermissionRequest, PostToolUse, PostToolUseFailure, Notification, SubagentStart, SubagentStop, Stop, TeammateIdle, TaskCompleted, InstructionsLoaded, ConfigChange, WorktreeCreate, WorktreeRemove, PreCompact, SessionEnd
Copilot CLI events (6): sessionStart, sessionEnd, userPromptSubmitted, preToolUse, postToolUse, errorOccurred
The six Copilot CLI events roughly map to a subset of Claude Code’s events. If your hooks only use PreToolUse and PostToolUse, they’re portable. LLM-based hooks (prompt and agent types) are Claude Code-only.
Both tools use a versioned JSON wrapper:
{
"version": 1,
"hooks": {
"preToolUse": [...]
}
}
Note the casing difference: Claude Code uses PascalCase (PreToolUse), Copilot CLI uses camelCase (preToolUse).
MCP Servers
MCP configuration is portable – both tools use .mcp.json at the project or plugin root with the same schema.
| Claude Code | Copilot CLI | |
|---|---|---|
| Config file | .mcp.json (auto-discovered) | .mcp.json (referenced in plugin.json as mcpServers) |
| Schema | Standard MCP config | Standard MCP config |
LSP Servers
| Claude Code | Copilot CLI | |
|---|---|---|
| Config | .lsp.json at plugin root | lspServers field in plugin.json |
Both support language server integration but configure it differently.
Zero-Change Compatibility
The good news: Copilot CLI reads .claude-plugin/plugin.json natively. No symlinks, no extra files, no changes needed. Your existing Claude Code plugin layout works as-is.
my-plugin/
├── .claude-plugin/
│ ├── plugin.json # Works for BOTH Claude Code and Copilot CLI
│ └── marketplace.json # Claude Code marketplace listing (ignored by Copilot)
├── skills/
│ └── my-skill/
│ └── SKILL.md # Works for both tools
├── hooks/
│ └── hooks.json # Works for both (if declared in plugin.json)
├── .mcp.json # Works for both tools
└── README.md
Working Example: show-me
The show-me plugin required zero changes to work with Copilot CLI:
show-me/
├── .claude-plugin/
│ └── plugin.json # Manifest — works for both tools
├── skills/
│ └── show-me/
│ ├── SKILL.md # Skill — works for both tools
│ └── docs/
├── bin/
│ ├── show
│ └── look
└── README.md
Install from either tool:
claude plugin install mbailey/show-me # Claude Code
copilot plugin install mbailey/show-me # Copilot CLI
Installation
Users install from each tool using similar commands:
| Claude Code | Copilot CLI | |
|---|---|---|
| From repo | claude plugin install mbailey/show-me | copilot plugin install mbailey/show-me |
| From marketplace | /plugin marketplace add user/repo then /plugin install name | copilot plugin install name@marketplace |
| Local | claude --plugin-dir ./my-plugin | copilot plugin install ./my-plugin |
| Installed to | ~/.claude/plugins/cache/ | ~/.copilot/state/installed-plugins/ |
Both tools support installing directly from a GitHub owner/repo path, making distribution straightforward.
What’s NOT Portable
Hook Events and Handler Types
Claude Code has 18 hook events with three handler types (command, prompt, agent). Copilot CLI has 6 events with command handlers only. If your plugin relies on PermissionRequest, SubagentStart, InstructionsLoaded, or other Claude Code-specific events, those hooks won’t fire in Copilot CLI. LLM-evaluated hooks (prompt and agent types) are Claude Code-only.
Agent Frontmatter
Claude Code agents support model, color, permissionMode, maxTurns, skills, mcpServers, hooks, and memory in frontmatter. Copilot CLI agents support name, description, and tools. The extra fields are ignored by Copilot CLI but don’t cause errors – your agents just won’t have those capabilities.
Agent File Extension
Claude Code uses *.md; Copilot CLI conventionally uses *.agent.md. However, when agent paths are declared explicitly in plugin.json (e.g., "agents": ["agents/greeter.md"]), Copilot CLI installs and uses .md files without issues. The extension convention only matters for auto-discovery in the agents/ directory — explicit paths work regardless of extension.
Progressive Plugin Pattern
Claude Code’s .claude/ subdirectory pattern (for projects that are both standalone tools and plugins) has no Copilot CLI equivalent. Copilot CLI looks for components at the paths declared in plugin.json, so you can point to .claude/ paths, but the convention is different.
Marketplace and Discovery
Claude Code uses marketplace.json in .claude-plugin/ for marketplace distribution. Copilot CLI has its own marketplace system. You’ll need separate marketplace listings for each ecosystem.
Commands and Styles
Claude Code supports commands/ (slash commands) and styles/ (output formatting). Copilot CLI doesn’t have these concepts. Commands are being merged into skills in Claude Code anyway, so prefer skills for new work.
Hook Casing Convention
Claude Code uses PascalCase for event names (PreToolUse); Copilot CLI uses camelCase (preToolUse). If you maintain separate hooks configs, watch the casing.
Context Hierarchy
Claude Code’s layered CLAUDE.md system (user, project, per-directory) is richer than Copilot CLI’s single .github/copilot-instructions.md per repo.
Portability Checklist
Use this checklist when adapting a Claude Code plugin for Copilot CLI compatibility:
- No manifest changes needed — Copilot CLI reads
.claude-plugin/plugin.jsonnatively - Skills: No changes needed —
skills/<name>/SKILL.mdworks for both - MCP config:
.mcp.jsonworks for both; add"mcpServers": ".mcp.json"to plugin.json for explicit Copilot CLI discovery - Agents:
.mdfiles install fine; runtime discovery of.mdvs.agent.mdmay vary - Hooks: If using only
PreToolUse/PostToolUsewith command handlers, they work in both. Watch PascalCase vs camelCase. Advanced hook types are Claude Code-only. - Test both: Install with
claude --plugin-dir ./andcopilot plugin install ./to verify - README: Document that the plugin works with both tools and any feature differences
- Avoid Claude Code-only features in shared components: prompt/agent hooks, commands, styles, advanced agent frontmatter
Summary
| Component | Portability | Notes |
|---|---|---|
| Skills | Fully portable | Same format, same paths |
| MCP servers | Fully portable | Same .mcp.json format |
| Plugin manifest | Fully portable | Copilot CLI reads .claude-plugin/plugin.json natively |
| Hooks (basic) | Adaptable | PreToolUse/PostToolUse command hooks work; watch casing |
| Hooks (advanced) | Not portable | 12 Claude Code-only events; prompt/agent handlers |
| Agents | Adaptable | Extra frontmatter ignored; file extension differs |
| Commands | Not portable | Claude Code-only (use skills instead) |
| Styles | Not portable | Claude Code-only |
The convergence between these tools is good news for plugin authors. Skills, MCP servers, and plugin manifests are fully portable today — Copilot CLI reads .claude-plugin/plugin.json natively, so Claude Code plugins work with zero changes. As the tools continue to evolve, expect the remaining gaps to narrow.
Last updated: March 2026
Resources
- Copilot CLI vs Claude Code comparison
- Claude Code Plugin Structure
- Claude Code Plugins Reference
- Copilot CLI Plugin Docs
- Copilot CLI Custom Agents
- Copilot CLI Hooks
- show-me plugin (working example — zero changes needed for Copilot CLI)