Portable Agent Plugin Template
A template for packaging skills and MCP servers into a plugin that can be
version-controlled in its own repo and pulled into any project as a git
submodule (or installed from a marketplace).
The problem
You have skills and MCP servers that you want to reuse across multiple repos.
Dropping them directly into each project's .claude/ or equivalent folder
means duplicated files, no single source of truth, and no clean way to version
or update them. You cannot add a local skills folder from another repo as a
submodule because the expected directory structure does not allow it.
The solution
Wrap your skills and MCP servers in the plugin format. Plugins are the
packaging unit that Claude Code, Copilot CLI, and GitHub Copilot in VS Code
all understand,
and they have a directory structure that works as a standalone repo. This
means you can store your plugins in a dedicated repo and pull them into
projects as a git submodule, with versioning tied to the submodule commit.
The plugin format also supports marketplace-style installation from a repo
URL, so the same repo works for all three tools and both distribution
methods without changes.
What is included
This template contains one example plugin with:
- A
greeting skill -- responds when you say hello (verifies skill loading).
- A
time MCP server -- exposes get_current_time and convert_time tools
(verifies MCP loading). Uses mcp-server-time via uvx.
Both exist only to confirm the install worked. Replace them with your own.
Repository structure
.claude-plugin/
marketplace.json # Registers repo as a marketplace (Claude Code)
.github/
plugin/
plugin.json # Direct plugin entry point (Copilot CLI / VS Code)
# MCP servers are inlined here
plugins/
example-plugin/
.claude-plugin/
plugin.json # Plugin manifest (Claude Code, via marketplace)
skills/
greeting/
SKILL.md
.mcp.json # MCP server definitions (Claude Code)
README.md
Why three manifests
Claude Code, Copilot CLI, and GitHub Copilot in VS Code discover plugins
differently. Three files cover all three tools:
| File | Read by | Purpose |
|---|
.claude-plugin/marketplace.json | Claude Code, VS Code | Registers the repo as a marketplace; points to ./plugins/example-plugin |
.github/plugin/plugin.json | Copilot CLI, VS Code | Direct plugin entry point with MCP servers inlined |
plugins/example-plugin/.claude-plugin/plugin.json | Claude Code (via marketplace) | The plugin manifest CC loads after resolving the marketplace path |
VS Code reads both .github/plugin/ and .claude-plugin/ locations, so
our layout with both is already covered.
Claude Code auto-discovers .mcp.json next to the plugin manifest, so MCP
servers are not inlined there. Copilot CLI and VS Code do not do this, so
the root-level .github/plugin/plugin.json inlines them.
This is the cost of triple compatibility. If you only target one tool, you
can drop the manifests for the others.
Installation
Git submodule (recommended)
Version-locked to a specific commit, reviewable in PRs, available to anyone
who clones the repo.
git submodule add https://github.com/DavidEncrypted/portable-agent-plugin-template.git .agent-plugins/portable-agent-plugin-template
git commit -m "add agent plugin submodule"
Claude Code -- add to your project's .claude/settings.json and commit it:
{
"pluginMarketplaces": ["./.agent-plugins/portable-agent-plugin-template"],
"enabledPlugins": {
"example-plugin@portable-agent-plugin-template": true
}
}
Anyone who clones with --recurse-submodules gets prompted to enable the
plugin. Updates arrive via git submodule update.
Copilot CLI -- after cloning:
copilot plugin install ./.agent-plugins/portable-agent-plugin-template/plugins/example-plugin
After a submodule update, re-run the install. Alternatively, use
--plugin-dir for direct loading (must be passed every launch):
copilot --plugin-dir ./.agent-plugins/portable-agent-plugin-template/plugins/example-plugin
GitHub Copilot in VS Code -- the submodule method is not recommended.
Plugin settings are all user-level, so a workspace-committed config won't
actually enable the plugin for other users. And because the path is relative
to a specific workspace, it breaks when you open a different folder. Use
the marketplace install instead (see below).
Marketplace install (alternative)
Better when you want the plugin available across all projects without adding
a submodule to each.
Claude Code:
claude plugin marketplace add DavidEncrypted/portable-agent-plugin-template
claude plugin install example-plugin@portable-agent-plugin-template
Copilot CLI: