@every-env/compound-plugin 0.7.0 → 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.
- package/.cursor-plugin/marketplace.json +25 -0
- package/CHANGELOG.md +13 -0
- package/README.md +14 -8
- package/bun.lock +1 -0
- package/docs/brainstorms/2026-02-14-copilot-converter-target-brainstorm.md +117 -0
- package/docs/brainstorms/2026-02-17-copilot-skill-naming-brainstorm.md +30 -0
- package/docs/plans/2026-02-14-feat-add-copilot-converter-target-plan.md +328 -0
- package/docs/specs/copilot.md +122 -0
- package/package.json +1 -1
- package/plugins/coding-tutor/.cursor-plugin/plugin.json +21 -0
- package/plugins/compound-engineering/.claude-plugin/plugin.json +1 -1
- package/plugins/compound-engineering/.cursor-plugin/plugin.json +31 -0
- package/plugins/compound-engineering/.mcp.json +8 -0
- package/plugins/compound-engineering/CHANGELOG.md +10 -0
- package/plugins/compound-engineering/commands/lfg.md +3 -3
- package/plugins/compound-engineering/commands/slfg.md +2 -2
- package/plugins/compound-engineering/commands/workflows/plan.md +15 -1
- package/src/commands/install.ts +5 -1
- package/src/commands/sync.ts +8 -8
- package/src/converters/{claude-to-cursor.ts → claude-to-copilot.ts} +93 -49
- package/src/sync/{cursor.ts → copilot.ts} +36 -14
- package/src/targets/copilot.ts +48 -0
- package/src/targets/index.ts +9 -9
- package/src/types/copilot.ts +31 -0
- package/src/utils/frontmatter.ts +1 -1
- package/tests/copilot-converter.test.ts +467 -0
- package/tests/copilot-writer.test.ts +189 -0
- package/tests/sync-copilot.test.ts +148 -0
- package/src/targets/cursor.ts +0 -48
- package/src/types/cursor.ts +0 -29
- package/tests/cursor-converter.test.ts +0 -347
- package/tests/cursor-writer.test.ts +0 -137
- package/tests/sync-cursor.test.ts +0 -92
|
@@ -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
CHANGED
|
@@ -5,6 +5,19 @@ All notable changes to the `@every-env/compound-plugin` CLI tool will be documen
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
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
|
+
|
|
8
21
|
## [0.6.0] - 2026-02-12
|
|
9
22
|
|
|
10
23
|
### Added
|
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
|
-
##
|
|
15
|
+
## Cursor Install
|
|
16
16
|
|
|
17
|
-
|
|
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,14 +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
|
|
31
|
-
|
|
32
35
|
# convert to Pi format
|
|
33
36
|
bunx @every-env/compound-plugin install compound-engineering --to pi
|
|
34
37
|
|
|
35
38
|
# convert to Gemini CLI format
|
|
36
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
|
|
37
43
|
```
|
|
38
44
|
|
|
39
45
|
Local dev:
|
|
@@ -45,9 +51,9 @@ bun run src/index.ts install ./plugins/compound-engineering --to opencode
|
|
|
45
51
|
OpenCode output is written to `~/.config/opencode` by default, with `opencode.json` at the root and `agents/`, `skills/`, and `plugins/` alongside it.
|
|
46
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).
|
|
47
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.
|
|
48
|
-
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.
|
|
49
54
|
Pi output is written to `~/.pi/agent/` by default with prompts, skills, extensions, and `compound-engineering/mcporter.json` for MCPorter interoperability.
|
|
50
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_`.
|
|
51
57
|
|
|
52
58
|
All provider targets are experimental and may change as the formats evolve.
|
|
53
59
|
|
|
@@ -68,8 +74,8 @@ bunx @every-env/compound-plugin sync --target pi
|
|
|
68
74
|
# Sync to Droid (skills only)
|
|
69
75
|
bunx @every-env/compound-plugin sync --target droid
|
|
70
76
|
|
|
71
|
-
# Sync to
|
|
72
|
-
bunx @every-env/compound-plugin sync --target
|
|
77
|
+
# Sync to GitHub Copilot (skills + MCP servers)
|
|
78
|
+
bunx @every-env/compound-plugin sync --target copilot
|
|
73
79
|
```
|
|
74
80
|
|
|
75
81
|
This syncs:
|
package/bun.lock
CHANGED
|
@@ -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`
|