Repository navigation
Description
Scope and evidence
P2 feature expansion, researched 2026-09-06. Agent Bundle baseline 5fc8de37c9695b816d55bdcf18a6bcb1dfee69f5. Official GitHub documentation was read; no Copilot CLI installation or native execution was performed. This issue covers the standalone CLI. VS Code/other editor Copilot support has a separate host issue and must not inherit CLI capabilities automatically.
Primary reference URLs
- Complete CLI plugin manifest, management, precedence and locations
- Authoring and testing a CLI plugin
- Hook JSON schema, input/output semantics, exit codes and timeout behavior
- Hook concepts and surface differences
- Official hook walkthrough
- Agent Plugins / Open Plugin Spec
Pin a supported CLI version and immutable schema/spec revision. Documentation is evolving; this research is not a conformance certificate.
Verified model
Copilot CLI supports native plugin packages containing skills, agents, commands, hooks and MCP configuration. It also opts into Agent Plugins v1 semantics through a canonical $schema. Manifest lookup is ordered: .plugin/plugin.json, root plugin.json, .github/plugin/plugin.json, then .claude-plugin/plugin.json. Marketplace lookup has its own order. This matters because Agent Bundle already emits portable and Claude manifests.
Component fields include skills, agents, commands, hooks and mcpServers. Native extensions has runtime meaning that differs from the same field in Open Plugin Spec mode; do not copy it between formats indiscriminately. Agents/skills and MCP have different collision/precedence rules. The host's parser—not whichever file the build happened to emit first—determines the effective plugin.
Proposed artifact and local validation
composite-root/
plugin.json # reuse portable mode if it covers selected capabilities
skills/review/SKILL.md
agents/reviewer.agent.md
hooks/copilot-cli.json
mcp/example.mjs
.github/plugin/marketplace.json # only when marketplace delivery is declared
An illustrative native manifest, where native mode is deliberately selected:
{
"name": "example-plugin",
"version": "1.0.0",
"skills": ["skills/"],
"hooks": "hooks/copilot-cli.json",
"mcpServers": ".mcp.json"
}Do not emit a conflicting root native manifest alongside the portable one. Prefer reusing the portable representation and proving the supported subset, or produce a precise incompatible-selection diagnostic.
Documented operator commands:
copilot plugin install ./composite-root
copilot plugin list
copilot plugin marketplace add example/repository
copilot plugin install example-plugin@example-marketplace
copilot plugin uninstall example-pluginDirect local installs are cached and may require reinstall; a path-sourced plugin in a local marketplace can load live on restart. These are distinct delivery modes, not a universal HMR promise. Uninstall takes native plugin identity. Preserve native policy and user configuration; never force marketplace removal that also deletes other plugins.
Hook codec requirements
The current hook reference supports version-1 documents and camelCase events, with PascalCase compatibility payloads using different field names. CLI direct exec plus args avoids shell interpolation. A minimal configuration shape is:
{
"version": 1,
"hooks": {
"preToolUse": [
{ "type": "command", "exec": "node", "args": ["/installed/example/hooks/before.mjs"], "timeoutSec": 30 }
]
}
}Replace the illustrative absolute path with a documented plugin-root anchor or installation binding, not a source-checkout path. Pin the selected payload dialect and event mapping. Current docs explicitly distinguish command failures from timeouts: before-tool command errors can deny, while timeouts fall through to normal permissions. Do not advertise a stronger fail-closed deadline than the host guarantees. SDK-only prompt transformations are not available merely because a command-hook field has the same name.
A portable hook or Claude-compatible event must have tests for the actual Copilot wire behavior. Cloud agent is another execution environment with a subset of events; it is not covered by this CLI adapter.
MCP, trust, state and scope
Bundle only declared MCP servers. Use canonical launch descriptors for argv/environment and host-managed secret authorization. The plugin data anchor is separate from the installation cache; generated state must not be written into cached code. Enterprise policy may disallow a marketplace, tool, hook or endpoint; report that honestly instead of editing policy.
Skill and agent name conflicts must be visible in inspection. An installed plugin can be valid yet have a skill shadowed by project/personal content. Conversely a later MCP definition can change the effective server. Never silently claim all declared components are active.
Implementation and acceptance
- Select and pin native versus spec-mode semantics; validate manifests without importing application code.
- Test effective lookup with root portable,
.github/plugin, and Claude manifests present together; no foreign hook/skill discovery. - Preserve identity, version, source and component references in the canonical artifact manifest, not a parallel catalog.
- Exercise static skills and commands without MCP/Flight processes.
- Execute a generated MCP tool successfully from an installed source-free package with correct argv/cwd/env and cancellation.
- Verify before/after tool payloads, denial, failure, timeout, context and unsupported transform behavior.
- Test native name precedence, disabled plugins, local-cache versus live-marketplace update, and uninstall ownership.
- Test Windows direct-exec behavior separately from POSIX shell hooks.
- Record real-host discovery and completed invocation; a listed plugin or emitted outgoing request alone is insufficient.
- Update English/Chinese docs and Composite conformance: test cross-host auto-discovery and precedence, not only file collisions #651 composite tests. Do not relax AB4106 globally just to add the adapter.
Non-goals
No cloud-agent rollout, new LSP subsystem, policy override, credential storage, independent compiler, agent loop, or duplicate MCP/native registration of the same operation. Extend existing portable/adapters/manifest/installation machinery and keep native host permissions intact.
Activity
ScriptedAlchemy commentedon Sep 7, 2026
Resolved by #723 (
4dc11a4a06).GitHub Copilot CLI — observed @github/copilot 1.0.83, installed and exercised 2026-09-06. Supported: the emitted package installs as one plugin.
manifestprobe-plugin (v1.0.0)) with no host-specific manifest present.skillscopilot plugins liston 1.0.83 reported "Skills: Plugin-contributed: review -- Review a change", read from skills/review/SKILL.md in the installed package.mcpcopilot plugins listreported "MCP servers: Plugin-contributed: probe -- stdio transport" andcopilot mcp get probereported Source: Plugin, Source plugin: probe-plugin (1.0.0) — the emitted mcp.json, read without a .mcp.json present.placeholderscopilot mcp getprints static configuration, and spawning the server requires a GitHub Copilot login that was not performed.hooksPaths it reads:
mcp.json,plugin.json,skills.Install:
copilot plugin install <plugin directory>.Every row above is pinned to that client's own documentation on the date shown, is validated on every build, and renders in
INSTALL.mdand the generated hosts reference. A surface recordedunavailableordegradednames exactly what the client would need; no unsupported feature is projected silently.ScriptedAlchemy commentedon Sep 7, 2026
Current-main reconciliation
At
b5cf7575e0bcfa6da23e12d2c5628146bdbe5cb1, #723'scopilot-clicompatibility record is delivered. This records how Copilot consumes the existing portable artifact; it is not delivery of a new native hook adapter or proof of authenticated tool execution.The two corrections explicitly deferred by #723 are now tracked in #728 instead of reopening this broad research ticket:
clients.copilot-cli.discovery.shadowedByis still empty, although the official manifest lookup order checks.plugin/plugin.jsonbefore the root manifest. Add the affected-surface record and composite regression.The existing deprecation and unverified-placeholder notes must survive rendering. #728 owns the focused record/tests change; no second compatibility table, new host permissions, or blanket reopening of the original native scope is requested.