@every-env/compound-plugin 0.5.2 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.cursor-plugin/marketplace.json +25 -0
  3. package/CHANGELOG.md +47 -0
  4. package/README.md +29 -6
  5. package/bun.lock +1 -0
  6. package/docs/brainstorms/2026-02-14-copilot-converter-target-brainstorm.md +117 -0
  7. package/docs/brainstorms/2026-02-17-copilot-skill-naming-brainstorm.md +30 -0
  8. package/docs/plans/2026-02-14-feat-add-copilot-converter-target-plan.md +328 -0
  9. package/docs/plans/2026-02-14-feat-add-gemini-cli-target-provider-plan.md +370 -0
  10. package/docs/specs/copilot.md +122 -0
  11. package/docs/specs/gemini.md +122 -0
  12. package/package.json +1 -1
  13. package/plugins/coding-tutor/.cursor-plugin/plugin.json +21 -0
  14. package/plugins/compound-engineering/.claude-plugin/plugin.json +1 -1
  15. package/plugins/compound-engineering/.cursor-plugin/plugin.json +31 -0
  16. package/plugins/compound-engineering/.mcp.json +8 -0
  17. package/plugins/compound-engineering/CHANGELOG.md +27 -0
  18. package/plugins/compound-engineering/commands/lfg.md +3 -3
  19. package/plugins/compound-engineering/commands/slfg.md +2 -2
  20. package/plugins/compound-engineering/commands/workflows/plan.md +18 -1
  21. package/plugins/compound-engineering/commands/workflows/work.md +8 -1
  22. package/src/commands/convert.ts +14 -25
  23. package/src/commands/install.ts +27 -25
  24. package/src/commands/sync.ts +44 -21
  25. package/src/converters/{claude-to-cursor.ts → claude-to-copilot.ts} +93 -49
  26. package/src/converters/claude-to-gemini.ts +193 -0
  27. package/src/converters/claude-to-opencode.ts +16 -0
  28. package/src/converters/claude-to-pi.ts +205 -0
  29. package/src/sync/copilot.ts +100 -0
  30. package/src/sync/droid.ts +21 -0
  31. package/src/sync/pi.ts +88 -0
  32. package/src/targets/copilot.ts +48 -0
  33. package/src/targets/gemini.ts +68 -0
  34. package/src/targets/index.ts +25 -7
  35. package/src/targets/pi.ts +131 -0
  36. package/src/templates/pi/compat-extension.ts +452 -0
  37. package/src/types/copilot.ts +31 -0
  38. package/src/types/gemini.ts +29 -0
  39. package/src/types/pi.ts +40 -0
  40. package/src/utils/frontmatter.ts +1 -1
  41. package/src/utils/resolve-home.ts +17 -0
  42. package/tests/cli.test.ts +76 -0
  43. package/tests/converter.test.ts +29 -0
  44. package/tests/copilot-converter.test.ts +467 -0
  45. package/tests/copilot-writer.test.ts +189 -0
  46. package/tests/gemini-converter.test.ts +373 -0
  47. package/tests/gemini-writer.test.ts +181 -0
  48. package/tests/pi-converter.test.ts +116 -0
  49. package/tests/pi-writer.test.ts +99 -0
  50. package/tests/sync-copilot.test.ts +148 -0
  51. package/tests/sync-droid.test.ts +57 -0
  52. package/tests/sync-pi.test.ts +68 -0
  53. package/src/targets/cursor.ts +0 -48
  54. package/src/types/cursor.ts +0 -29
  55. package/tests/cursor-converter.test.ts +0 -347
  56. package/tests/cursor-writer.test.ts +0 -137
@@ -12,7 +12,7 @@
12
12
  {
13
13
  "name": "compound-engineering",
14
14
  "description": "AI-powered development tools that get smarter with every use. Make each unit of engineering work easier than the last. Includes 29 specialized agents, 22 commands, and 19 skills.",
15
- "version": "2.33.0",
15
+ "version": "2.34.0",
16
16
  "author": {
17
17
  "name": "Kieran Klaassen",
18
18
  "url": "https://github.com/kieranklaassen",
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "compound-engineering",
3
+ "owner": {
4
+ "name": "Kieran Klaassen",
5
+ "email": "kieran@every.to",
6
+ "url": "https://github.com/kieranklaassen"
7
+ },
8
+ "metadata": {
9
+ "description": "Cursor plugin marketplace for Every Inc plugins",
10
+ "version": "1.0.0",
11
+ "pluginRoot": "plugins"
12
+ },
13
+ "plugins": [
14
+ {
15
+ "name": "compound-engineering",
16
+ "source": "compound-engineering",
17
+ "description": "AI-powered development tools that get smarter with every use. Includes specialized agents, commands, skills, and Context7 MCP."
18
+ },
19
+ {
20
+ "name": "coding-tutor",
21
+ "source": "coding-tutor",
22
+ "description": "Personalized coding tutorials with spaced repetition quizzes using your real codebase."
23
+ }
24
+ ]
25
+ }
package/CHANGELOG.md ADDED
@@ -0,0 +1,47 @@
1
+ # Changelog
2
+
3
+ All notable changes to the `@every-env/compound-plugin` CLI tool will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.8.0] - 2026-02-17
9
+
10
+ ### Added
11
+
12
+ - **GitHub Copilot target** — `--to copilot` converts plugins to `.github/` format with `.agent.md` files, `SKILL.md` skills, and `copilot-mcp-config.json`. Also supports `sync --target copilot` ([#192](https://github.com/EveryInc/compound-engineering-plugin/pull/192)) — thanks [@brayanjuls](https://github.com/brayanjuls)!
13
+ - **Native Cursor plugin support** — Cursor now installs via `/add-plugin compound-engineering` using Cursor's native plugin system instead of CLI conversion ([#184](https://github.com/EveryInc/compound-engineering-plugin/pull/184)) — thanks [@ericzakariasson](https://github.com/ericzakariasson)!
14
+
15
+ ### Removed
16
+
17
+ - Cursor CLI conversion target (`--to cursor`) — replaced by native Cursor plugin install
18
+
19
+ ---
20
+
21
+ ## [0.6.0] - 2026-02-12
22
+
23
+ ### Added
24
+
25
+ - **Droid sync target** — `sync --target droid` symlinks personal skills to `~/.factory/skills/`
26
+ - **Cursor sync target** — `sync --target cursor` symlinks skills to `.cursor/skills/` and merges MCP servers into `.cursor/mcp.json`
27
+ - **Pi target** — First-class `--to pi` converter with MCPorter config and subagent compatibility ([#181](https://github.com/EveryInc/compound-engineering-plugin/pull/181)) — thanks [@gvkhosla](https://github.com/gvkhosla)!
28
+
29
+ ### Fixed
30
+
31
+ - **Bare Claude model alias resolution** — Fixed OpenCode converter not resolving bare model aliases like `claude-sonnet-4-5-20250514` ([#182](https://github.com/EveryInc/compound-engineering-plugin/pull/182)) — thanks [@waltbeaman](https://github.com/waltbeaman)!
32
+
33
+ ### Changed
34
+
35
+ - Extracted shared `expandHome` / `resolveTargetHome` helpers to `src/utils/resolve-home.ts`, removing duplication across `convert.ts`, `install.ts`, and `sync.ts`
36
+
37
+ ---
38
+
39
+ ## [0.5.2] - 2026-02-09
40
+
41
+ ### Fixed
42
+
43
+ - Fix cursor install defaulting to cwd instead of opencode config dir
44
+
45
+ ## [0.5.1] - 2026-02-08
46
+
47
+ - Initial npm publish
package/README.md CHANGED
@@ -12,9 +12,15 @@ A Claude Code plugin marketplace featuring the **Compound Engineering Plugin**
12
12
  /plugin install compound-engineering
13
13
  ```
14
14
 
15
- ## OpenCode, Codex, Droid & Cursor (experimental) Install
15
+ ## Cursor Install
16
16
 
17
- This repo includes a Bun/TypeScript CLI that converts Claude Code plugins to OpenCode, Codex, Factory Droid, and Cursor.
17
+ ```text
18
+ /add-plugin compound-engineering
19
+ ```
20
+
21
+ ## OpenCode, Codex, Droid, Pi, Gemini & GitHub Copilot (experimental) Install
22
+
23
+ This repo includes a Bun/TypeScript CLI that converts Claude Code plugins to OpenCode, Codex, Factory Droid, Pi, Gemini CLI and GitHub Copilot.
18
24
 
19
25
  ```bash
20
26
  # convert the compound-engineering plugin into OpenCode format
@@ -26,8 +32,14 @@ bunx @every-env/compound-plugin install compound-engineering --to codex
26
32
  # convert to Factory Droid format
27
33
  bunx @every-env/compound-plugin install compound-engineering --to droid
28
34
 
29
- # convert to Cursor format
30
- bunx @every-env/compound-plugin install compound-engineering --to cursor
35
+ # convert to Pi format
36
+ bunx @every-env/compound-plugin install compound-engineering --to pi
37
+
38
+ # convert to Gemini CLI format
39
+ bunx @every-env/compound-plugin install compound-engineering --to gemini
40
+
41
+ # convert to GitHub Copilot format
42
+ bunx @every-env/compound-plugin install compound-engineering --to copilot
31
43
  ```
32
44
 
33
45
  Local dev:
@@ -39,13 +51,15 @@ bun run src/index.ts install ./plugins/compound-engineering --to opencode
39
51
  OpenCode output is written to `~/.config/opencode` by default, with `opencode.json` at the root and `agents/`, `skills/`, and `plugins/` alongside it.
40
52
  Codex output is written to `~/.codex/prompts` and `~/.codex/skills`, with each Claude command converted into both a prompt and a skill (the prompt instructs Codex to load the corresponding skill). Generated Codex skill descriptions are truncated to 1024 characters (Codex limit).
41
53
  Droid output is written to `~/.factory/` with commands, droids (agents), and skills. Claude tool names are mapped to Factory equivalents (`Bash` → `Execute`, `Write` → `Create`, etc.) and namespace prefixes are stripped from commands.
42
- Cursor output is written to `.cursor/` with rules (`.mdc`), commands, skills, and `mcp.json`. Agents become "Agent Requested" rules (`alwaysApply: false`) so Cursor's AI activates them on demand. Works with both the Cursor IDE and Cursor CLI (`cursor-agent`) — they share the same `.cursor/` config directory.
54
+ Pi output is written to `~/.pi/agent/` by default with prompts, skills, extensions, and `compound-engineering/mcporter.json` for MCPorter interoperability.
55
+ Gemini output is written to `.gemini/` with skills (from agents), commands (`.toml`), and `settings.json` (MCP servers). Namespaced commands create directory structure (`workflows:plan` → `commands/workflows/plan.toml`). Skills use the identical SKILL.md standard and pass through unchanged.
56
+ Copilot output is written to `.github/` with agents (`.agent.md`), skills (`SKILL.md`), and `copilot-mcp-config.json`. Agents get Copilot frontmatter (`description`, `tools: ["*"]`, `infer: true`), commands are converted to agent skills, and MCP server env vars are prefixed with `COPILOT_MCP_`.
43
57
 
44
58
  All provider targets are experimental and may change as the formats evolve.
45
59
 
46
60
  ## Sync Personal Config
47
61
 
48
- Sync your personal Claude Code config (`~/.claude/`) to OpenCode or Codex:
62
+ Sync your personal Claude Code config (`~/.claude/`) to other AI coding tools:
49
63
 
50
64
  ```bash
51
65
  # Sync skills and MCP servers to OpenCode
@@ -53,6 +67,15 @@ bunx @every-env/compound-plugin sync --target opencode
53
67
 
54
68
  # Sync to Codex
55
69
  bunx @every-env/compound-plugin sync --target codex
70
+
71
+ # Sync to Pi
72
+ bunx @every-env/compound-plugin sync --target pi
73
+
74
+ # Sync to Droid (skills only)
75
+ bunx @every-env/compound-plugin sync --target droid
76
+
77
+ # Sync to GitHub Copilot (skills + MCP servers)
78
+ bunx @every-env/compound-plugin sync --target copilot
56
79
  ```
57
80
 
58
81
  This syncs:
package/bun.lock CHANGED
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "lockfileVersion": 1,
3
+ "configVersion": 0,
3
4
  "workspaces": {
4
5
  "": {
5
6
  "name": "compound-plugin",
@@ -0,0 +1,117 @@
1
+ ---
2
+ date: 2026-02-14
3
+ topic: copilot-converter-target
4
+ ---
5
+
6
+ # Add GitHub Copilot Converter Target
7
+
8
+ ## What We're Building
9
+
10
+ A new converter target that transforms the compound-engineering Claude Code plugin into GitHub Copilot's native format. This follows the same established pattern as the existing converters (Cursor, Codex, OpenCode, Droid, Pi) and outputs files that Copilot can consume directly from `.github/` (repo-level) or `~/.copilot/` (user-wide).
11
+
12
+ Copilot's customization system (as of early 2026) supports: custom agents (`.agent.md`), agent skills (`SKILL.md`), prompt files (`.prompt.md`), custom instructions (`copilot-instructions.md`), and MCP servers (via repo settings).
13
+
14
+ ## Why This Approach
15
+
16
+ The repository already has a robust multi-target converter infrastructure with a consistent `TargetHandler` pattern. Adding Copilot as a new target follows this proven pattern rather than inventing something new. Copilot's format is close enough to Claude Code's that the conversion is straightforward, and the SKILL.md format is already cross-compatible.
17
+
18
+ ### Approaches Considered
19
+
20
+ 1. **Full converter target (chosen)** — Follow the existing pattern with types, converter, writer, and target registration. Most consistent with codebase conventions.
21
+ 2. **Minimal agent-only converter** — Only convert agents, skip commands/skills. Too limited; users would lose most of the plugin's value.
22
+ 3. **Documentation-only approach** — Just document how to manually set up Copilot. Doesn't compound — every user would repeat the work.
23
+
24
+ ## Key Decisions
25
+
26
+ ### Component Mapping
27
+
28
+ | Claude Code Component | Copilot Equivalent | Notes |
29
+ |----------------------|-------------------|-------|
30
+ | **Agents** (`.md`) | **Custom Agents** (`.agent.md`) | Full frontmatter mapping: description, tools, target, infer |
31
+ | **Commands** (`.md`) | **Agent Skills** (`SKILL.md`) | Commands become skills since Copilot has no direct command equivalent. `allowed-tools` dropped silently. |
32
+ | **Skills** (`SKILL.md`) | **Agent Skills** (`SKILL.md`) | Copy as-is — format is already cross-compatible |
33
+ | **MCP Servers** | **Repo settings JSON** | Generate a `copilot-mcp-config.json` users paste into GitHub repo settings |
34
+ | **Hooks** | **Skipped with warning** | Copilot doesn't have a hooks equivalent |
35
+
36
+ ### Agent Frontmatter Mapping
37
+
38
+ | Claude Field | Copilot Field | Mapping |
39
+ |-------------|--------------|---------|
40
+ | `name` | `name` | Direct pass-through |
41
+ | `description` | `description` (required) | Direct pass-through, generate fallback if missing |
42
+ | `capabilities` | Body text | Fold into body as "## Capabilities" section (like Cursor) |
43
+ | `model` | `model` | Pass through (works in IDE, may be ignored on github.com) |
44
+ | — | `tools` | Default to `["*"]` (all tools). Claude agents have unrestricted tool access, so Copilot agents should too. |
45
+ | — | `target` | Omit (defaults to `both` — IDE + github.com) |
46
+ | — | `infer` | Set to `true` (auto-selection enabled) |
47
+
48
+ ### Output Directories
49
+
50
+ - **Repository-level (default):** `.github/agents/`, `.github/skills/`
51
+ - **User-wide (with --personal flag):** `~/.copilot/skills/` (only skills supported at this level)
52
+
53
+ ### Content Transformation
54
+
55
+ Apply transformations similar to Cursor converter:
56
+
57
+ 1. **Task agent calls:** `Task agent-name(args)` → `Use the agent-name skill to: args`
58
+ 2. **Slash commands:** `/workflows:plan` → `/plan` (flatten namespace)
59
+ 3. **Path rewriting:** `.claude/` → `.github/` (Copilot's repo-level config path)
60
+ 4. **Agent references:** `@agent-name` → `the agent-name agent`
61
+
62
+ ### MCP Server Handling
63
+
64
+ Generate a `copilot-mcp-config.json` file with the structure Copilot expects:
65
+
66
+ ```json
67
+ {
68
+ "mcpServers": {
69
+ "server-name": {
70
+ "type": "local",
71
+ "command": "npx",
72
+ "args": ["package"],
73
+ "tools": ["*"],
74
+ "env": {
75
+ "KEY": "COPILOT_MCP_KEY"
76
+ }
77
+ }
78
+ }
79
+ }
80
+ ```
81
+
82
+ Note: Copilot requires env vars to use the `COPILOT_MCP_` prefix. The converter should transform env var names accordingly and include a comment/note about this.
83
+
84
+ ## Files to Create/Modify
85
+
86
+ ### New Files
87
+
88
+ - `src/types/copilot.ts` — Type definitions (CopilotAgent, CopilotSkill, CopilotBundle, etc.)
89
+ - `src/converters/claude-to-copilot.ts` — Converter with `transformContentForCopilot()`
90
+ - `src/targets/copilot.ts` — Writer with `writeCopilotBundle()`
91
+ - `docs/specs/copilot.md` — Format specification document
92
+
93
+ ### Modified Files
94
+
95
+ - `src/targets/index.ts` — Register copilot target handler
96
+ - `src/commands/sync.ts` — Add "copilot" to valid sync targets
97
+
98
+ ### Test Files
99
+
100
+ - `tests/copilot-converter.test.ts` — Converter tests following existing patterns
101
+
102
+ ### Character Limit
103
+
104
+ Copilot imposes a 30,000 character limit on agent body content. If an agent body exceeds this after folding in capabilities, the converter should truncate with a warning to stderr.
105
+
106
+ ### Agent File Extension
107
+
108
+ Use `.agent.md` (not plain `.md`). This is the canonical Copilot convention and makes agent files immediately identifiable.
109
+
110
+ ## Open Questions
111
+
112
+ - Should the converter generate a `copilot-setup-steps.yml` workflow file for MCP servers that need special dependencies (e.g., `uv`, `pipx`)?
113
+ - Should `.github/copilot-instructions.md` be generated with any base instructions from the plugin?
114
+
115
+ ## Next Steps
116
+
117
+ → `/workflows:plan` for implementation details
@@ -0,0 +1,30 @@
1
+ ---
2
+ date: 2026-02-17
3
+ topic: copilot-skill-naming
4
+ ---
5
+
6
+ # Copilot Skill Naming: Preserve Namespace
7
+
8
+ ## What We're Building
9
+
10
+ Change the Copilot converter to preserve command namespaces when converting commands to skills. Currently `workflows:plan` flattens to `plan`, which is too generic and clashes with Copilot's own features in the chat suggestion UI.
11
+
12
+ ## Why This Approach
13
+
14
+ The `flattenCommandName` function strips everything before the last colon, producing names like `plan`, `review`, `work` that are too generic for Copilot's skill discovery UI. Replacing colons with hyphens (`workflows:plan` -> `workflows-plan`) preserves context while staying within valid filename characters.
15
+
16
+ ## Key Decisions
17
+
18
+ - **Replace colons with hyphens** instead of stripping the prefix: `workflows:plan` -> `workflows-plan`
19
+ - **Copilot only** — other converters (Cursor, Droid, etc.) keep their current flattening behavior
20
+ - **Content transformation too** — slash command references in body text also use hyphens: `/workflows:plan` -> `/workflows-plan`
21
+
22
+ ## Changes Required
23
+
24
+ 1. `src/converters/claude-to-copilot.ts` — change `flattenCommandName` to replace colons with hyphens
25
+ 2. `src/converters/claude-to-copilot.ts` — update `transformContentForCopilot` slash command rewriting
26
+ 3. `tests/copilot-converter.test.ts` — update affected tests
27
+
28
+ ## Next Steps
29
+
30
+ -> Implement directly (small, well-scoped change)
@@ -0,0 +1,328 @@
1
+ ---
2
+ title: "feat: Add GitHub Copilot converter target"
3
+ type: feat
4
+ date: 2026-02-14
5
+ status: complete
6
+ ---
7
+
8
+ # feat: Add GitHub Copilot Converter Target
9
+
10
+ ## Overview
11
+
12
+ Add GitHub Copilot as a converter target following the established `TargetHandler` pattern. This converts the compound-engineering Claude Code plugin into Copilot's native format: custom agents (`.agent.md`), agent skills (`SKILL.md`), and MCP server configuration JSON.
13
+
14
+ **Brainstorm:** `docs/brainstorms/2026-02-14-copilot-converter-target-brainstorm.md`
15
+
16
+ ## Problem Statement
17
+
18
+ The CLI tool (`compound`) already supports converting Claude Code plugins to 5 target formats (OpenCode, Codex, Droid, Cursor, Pi). GitHub Copilot is a widely-used AI coding assistant that now supports custom agents, skills, and MCP servers — but there's no converter target for it.
19
+
20
+ ## Proposed Solution
21
+
22
+ Follow the existing converter pattern exactly:
23
+
24
+ 1. Define types (`src/types/copilot.ts`)
25
+ 2. Implement converter (`src/converters/claude-to-copilot.ts`)
26
+ 3. Implement writer (`src/targets/copilot.ts`)
27
+ 4. Register target (`src/targets/index.ts`)
28
+ 5. Add sync support (`src/sync/copilot.ts`, `src/commands/sync.ts`)
29
+ 6. Write tests and documentation
30
+
31
+ ### Component Mapping
32
+
33
+ | Claude Code | Copilot | Output Path |
34
+ |-------------|---------|-------------|
35
+ | Agents (`.md`) | Custom Agents (`.agent.md`) | `.github/agents/{name}.agent.md` |
36
+ | Commands (`.md`) | Agent Skills (`SKILL.md`) | `.github/skills/{name}/SKILL.md` |
37
+ | Skills (`SKILL.md`) | Agent Skills (`SKILL.md`) | `.github/skills/{name}/SKILL.md` |
38
+ | MCP Servers | Config JSON | `.github/copilot-mcp-config.json` |
39
+ | Hooks | Skipped | Warning to stderr |
40
+
41
+ ## Technical Approach
42
+
43
+ ### Phase 1: Types
44
+
45
+ **File:** `src/types/copilot.ts`
46
+
47
+ ```typescript
48
+ export type CopilotAgent = {
49
+ name: string
50
+ content: string // Full .agent.md content with frontmatter
51
+ }
52
+
53
+ export type CopilotGeneratedSkill = {
54
+ name: string
55
+ content: string // SKILL.md content with frontmatter
56
+ }
57
+
58
+ export type CopilotSkillDir = {
59
+ name: string
60
+ sourceDir: string
61
+ }
62
+
63
+ export type CopilotMcpServer = {
64
+ type: string
65
+ command?: string
66
+ args?: string[]
67
+ url?: string
68
+ tools: string[]
69
+ env?: Record<string, string>
70
+ headers?: Record<string, string>
71
+ }
72
+
73
+ export type CopilotBundle = {
74
+ agents: CopilotAgent[]
75
+ generatedSkills: CopilotGeneratedSkill[]
76
+ skillDirs: CopilotSkillDir[]
77
+ mcpConfig?: Record<string, CopilotMcpServer>
78
+ }
79
+ ```
80
+
81
+ ### Phase 2: Converter
82
+
83
+ **File:** `src/converters/claude-to-copilot.ts`
84
+
85
+ **Agent conversion:**
86
+ - Frontmatter: `description` (required, fallback to `"Converted from Claude agent {name}"`), `tools: ["*"]`, `infer: true`
87
+ - Pass through `model` if present
88
+ - Fold `capabilities` into body as `## Capabilities` section (same as Cursor)
89
+ - Use `formatFrontmatter()` utility
90
+ - Warn if body exceeds 30,000 characters (`.length`)
91
+
92
+ **Command → Skill conversion:**
93
+ - Convert to SKILL.md format with frontmatter: `name`, `description`
94
+ - Flatten namespaced names: `workflows:plan` → `plan`
95
+ - Drop `allowed-tools`, `model`, `disable-model-invocation` silently
96
+ - Include `argument-hint` as `## Arguments` section in body
97
+
98
+ **Skill pass-through:**
99
+ - Map to `CopilotSkillDir` as-is (same as Cursor)
100
+
101
+ **MCP server conversion:**
102
+ - Transform env var names: `API_KEY` → `COPILOT_MCP_API_KEY`
103
+ - Skip vars already prefixed with `COPILOT_MCP_`
104
+ - Add `type: "local"` for command-based servers, `type: "sse"` for URL-based
105
+ - Set `tools: ["*"]` for all servers
106
+
107
+ **Content transformation (`transformContentForCopilot`):**
108
+
109
+ | Pattern | Input | Output |
110
+ |---------|-------|--------|
111
+ | Task calls | `Task repo-research-analyst(desc)` | `Use the repo-research-analyst skill to: desc` |
112
+ | Slash commands | `/workflows:plan` | `/plan` |
113
+ | Path rewriting | `.claude/` | `.github/` |
114
+ | Home path rewriting | `~/.claude/` | `~/.copilot/` |
115
+ | Agent references | `@security-sentinel` | `the security-sentinel agent` |
116
+
117
+ **Hooks:** Warn to stderr if present, skip.
118
+
119
+ ### Phase 3: Writer
120
+
121
+ **File:** `src/targets/copilot.ts`
122
+
123
+ **Path resolution:**
124
+ - If `outputRoot` basename is `.github`, write directly into it (avoid `.github/.github/` double-nesting)
125
+ - Otherwise, nest under `.github/`
126
+
127
+ **Write operations:**
128
+ - Agents → `.github/agents/{name}.agent.md` (note: `.agent.md` extension)
129
+ - Generated skills (from commands) → `.github/skills/{name}/SKILL.md`
130
+ - Skill dirs → `.github/skills/{name}/` (copy via `copyDir`)
131
+ - MCP config → `.github/copilot-mcp-config.json` (backup existing with `backupFile`)
132
+
133
+ ### Phase 4: Target Registration
134
+
135
+ **File:** `src/targets/index.ts`
136
+
137
+ Add import and register:
138
+
139
+ ```typescript
140
+ import { convertClaudeToCopilot } from "../converters/claude-to-copilot"
141
+ import { writeCopilotBundle } from "./copilot"
142
+
143
+ // In targets record:
144
+ copilot: {
145
+ name: "copilot",
146
+ implemented: true,
147
+ convert: convertClaudeToCopilot as TargetHandler<CopilotBundle>["convert"],
148
+ write: writeCopilotBundle as TargetHandler<CopilotBundle>["write"],
149
+ },
150
+ ```
151
+
152
+ ### Phase 5: Sync Support
153
+
154
+ **File:** `src/sync/copilot.ts`
155
+
156
+ Follow the Cursor sync pattern (`src/sync/cursor.ts`):
157
+ - Symlink skills to `.github/skills/` using `forceSymlink`
158
+ - Validate skill names with `isValidSkillName`
159
+ - Convert MCP servers with `COPILOT_MCP_` prefix transformation
160
+ - Merge MCP config into existing `.github/copilot-mcp-config.json`
161
+
162
+ **File:** `src/commands/sync.ts`
163
+
164
+ - Add `"copilot"` to `validTargets` array
165
+ - Add case in `resolveOutputRoot()`: `case "copilot": return path.join(process.cwd(), ".github")`
166
+ - Add import and switch case for `syncToCopilot`
167
+ - Update meta description to include "Copilot"
168
+
169
+ ### Phase 6: Tests
170
+
171
+ **File:** `tests/copilot-converter.test.ts`
172
+
173
+ Test cases (following `tests/cursor-converter.test.ts` pattern):
174
+
175
+ ```
176
+ describe("convertClaudeToCopilot")
177
+ ✓ converts agents to .agent.md with Copilot frontmatter
178
+ ✓ agent description is required, fallback generated if missing
179
+ ✓ agent with empty body gets default body
180
+ ✓ agent capabilities are prepended to body
181
+ ✓ agent model field is passed through
182
+ ✓ agent tools defaults to ["*"]
183
+ ✓ agent infer defaults to true
184
+ ✓ warns when agent body exceeds 30k characters
185
+ ✓ converts commands to skills with SKILL.md format
186
+ ✓ flattens namespaced command names
187
+ ✓ command name collision after flattening is deduplicated
188
+ ✓ command allowedTools is silently dropped
189
+ ✓ command with argument-hint gets Arguments section
190
+ ✓ passes through skill directories
191
+ ✓ skill and generated skill name collision is deduplicated
192
+ ✓ converts MCP servers with COPILOT_MCP_ prefix
193
+ ✓ MCP env vars already prefixed are not double-prefixed
194
+ ✓ MCP servers get type field (local vs sse)
195
+ ✓ warns when hooks are present
196
+ ✓ no warning when hooks are absent
197
+ ✓ plugin with zero agents produces empty agents array
198
+ ✓ plugin with only skills works
199
+
200
+ describe("transformContentForCopilot")
201
+ ✓ rewrites .claude/ paths to .github/
202
+ ✓ rewrites ~/.claude/ paths to ~/.copilot/
203
+ ✓ transforms Task agent calls to skill references
204
+ ✓ flattens slash commands
205
+ ✓ transforms @agent references to agent references
206
+ ```
207
+
208
+ **File:** `tests/copilot-writer.test.ts`
209
+
210
+ Test cases (following `tests/cursor-writer.test.ts` pattern):
211
+
212
+ ```
213
+ describe("writeCopilotBundle")
214
+ ✓ writes agents, generated skills, copied skills, and MCP config
215
+ ✓ agents use .agent.md file extension
216
+ ✓ writes directly into .github output root without double-nesting
217
+ ✓ handles empty bundles gracefully
218
+ ✓ writes multiple agents as separate .agent.md files
219
+ ✓ backs up existing copilot-mcp-config.json before overwriting
220
+ ✓ creates skill directories with SKILL.md
221
+ ```
222
+
223
+ **File:** `tests/sync-copilot.test.ts`
224
+
225
+ Test cases (following `tests/sync-cursor.test.ts` pattern):
226
+
227
+ ```
228
+ describe("syncToCopilot")
229
+ ✓ symlinks skills to .github/skills/
230
+ ✓ skips skills with invalid names
231
+ ✓ merges MCP config with existing file
232
+ ✓ transforms MCP env var names to COPILOT_MCP_ prefix
233
+ ✓ writes MCP config with restricted permissions (0o600)
234
+ ```
235
+
236
+ ### Phase 7: Documentation
237
+
238
+ **File:** `docs/specs/copilot.md`
239
+
240
+ Follow `docs/specs/cursor.md` format:
241
+ - Last verified date
242
+ - Primary sources (GitHub Docs URLs)
243
+ - Config locations table
244
+ - Agents section (`.agent.md` format, frontmatter fields)
245
+ - Skills section (`SKILL.md` format)
246
+ - MCP section (config structure, env var prefix requirement)
247
+ - Character limits (30k agent body)
248
+
249
+ **File:** `README.md`
250
+
251
+ - Add "copilot" to the list of supported targets
252
+ - Add usage example: `compound convert --to copilot ./plugins/compound-engineering`
253
+ - Add sync example: `compound sync copilot`
254
+
255
+ ## Acceptance Criteria
256
+
257
+ ### Converter
258
+ - [x] Agents convert to `.agent.md` with `description`, `tools: ["*"]`, `infer: true`
259
+ - [x] Agent `model` passes through when present
260
+ - [x] Agent `capabilities` fold into body as `## Capabilities`
261
+ - [x] Missing description generates fallback
262
+ - [x] Empty body generates fallback
263
+ - [x] Body exceeding 30k chars triggers stderr warning
264
+ - [x] Commands convert to SKILL.md format
265
+ - [x] Command names flatten (`workflows:plan` → `plan`)
266
+ - [x] Name collisions deduplicated with `-2`, `-3` suffix
267
+ - [x] Command `allowed-tools` dropped silently
268
+ - [x] Skills pass through as `CopilotSkillDir`
269
+ - [x] MCP env vars prefixed with `COPILOT_MCP_`
270
+ - [x] Already-prefixed env vars not double-prefixed
271
+ - [x] MCP servers get `type` field (`local` or `sse`)
272
+ - [x] Hooks trigger warning, skip conversion
273
+ - [x] Content transformation: Task calls, slash commands, paths, @agent refs
274
+
275
+ ### Writer
276
+ - [x] Agents written to `.github/agents/{name}.agent.md`
277
+ - [x] Generated skills written to `.github/skills/{name}/SKILL.md`
278
+ - [x] Skill dirs copied to `.github/skills/{name}/`
279
+ - [x] MCP config written to `.github/copilot-mcp-config.json`
280
+ - [x] Existing MCP config backed up before overwrite
281
+ - [x] No double-nesting when outputRoot is `.github`
282
+ - [x] Empty bundles handled gracefully
283
+
284
+ ### CLI Integration
285
+ - [x] `compound convert --to copilot` works
286
+ - [x] `compound sync copilot` works
287
+ - [x] Copilot registered in `src/targets/index.ts`
288
+ - [x] Sync resolves output to `.github/` in current directory
289
+
290
+ ### Tests
291
+ - [x] `tests/copilot-converter.test.ts` — all converter tests pass
292
+ - [x] `tests/copilot-writer.test.ts` — all writer tests pass
293
+ - [x] `tests/sync-copilot.test.ts` — all sync tests pass
294
+
295
+ ### Documentation
296
+ - [x] `docs/specs/copilot.md` — format specification
297
+ - [x] `README.md` — updated with copilot target
298
+
299
+ ## Files to Create
300
+
301
+ | File | Purpose |
302
+ |------|---------|
303
+ | `src/types/copilot.ts` | Type definitions |
304
+ | `src/converters/claude-to-copilot.ts` | Converter logic |
305
+ | `src/targets/copilot.ts` | Writer logic |
306
+ | `src/sync/copilot.ts` | Sync handler |
307
+ | `tests/copilot-converter.test.ts` | Converter tests |
308
+ | `tests/copilot-writer.test.ts` | Writer tests |
309
+ | `tests/sync-copilot.test.ts` | Sync tests |
310
+ | `docs/specs/copilot.md` | Format specification |
311
+
312
+ ## Files to Modify
313
+
314
+ | File | Change |
315
+ |------|--------|
316
+ | `src/targets/index.ts` | Register copilot target |
317
+ | `src/commands/sync.ts` | Add copilot to valid targets, output root, switch case |
318
+ | `README.md` | Add copilot to supported targets |
319
+
320
+ ## References
321
+
322
+ - [Custom agents configuration - GitHub Docs](https://docs.github.com/en/copilot/reference/custom-agents-configuration)
323
+ - [About Agent Skills - GitHub Docs](https://docs.github.com/en/copilot/concepts/agents/about-agent-skills)
324
+ - [MCP and coding agent - GitHub Docs](https://docs.github.com/en/copilot/concepts/agents/coding-agent/mcp-and-coding-agent)
325
+ - Existing converter: `src/converters/claude-to-cursor.ts`
326
+ - Existing writer: `src/targets/cursor.ts`
327
+ - Existing sync: `src/sync/cursor.ts`
328
+ - Existing tests: `tests/cursor-converter.test.ts`, `tests/cursor-writer.test.ts`