@every-env/compound-plugin 0.9.0 → 2.34.2

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 (121) hide show
  1. package/.claude-plugin/marketplace.json +3 -3
  2. package/.github/workflows/publish.yml +20 -10
  3. package/.releaserc.json +31 -0
  4. package/AGENTS.md +6 -1
  5. package/CHANGELOG.md +76 -0
  6. package/CLAUDE.md +16 -3
  7. package/README.md +83 -16
  8. package/bun.lock +977 -0
  9. package/docs/plans/2026-02-14-feat-auto-detect-install-and-gemini-sync-plan.md +360 -0
  10. package/docs/plans/2026-02-25-feat-windsurf-global-scope-support-plan.md +627 -0
  11. package/docs/plans/2026-03-01-feat-ce-command-aliases-backwards-compatible-deprecation-plan.md +261 -0
  12. package/docs/plans/2026-03-01-fix-setup-skill-non-claude-llm-fallback-plan.md +140 -0
  13. package/docs/plans/2026-03-03-feat-sync-claude-mcp-all-supported-providers-plan.md +639 -0
  14. package/docs/plans/feature_opencode-commands-as-md-and-config-merge.md +574 -0
  15. package/docs/solutions/adding-converter-target-providers.md +693 -0
  16. package/docs/solutions/plugin-versioning-requirements.md +7 -3
  17. package/docs/specs/windsurf.md +477 -0
  18. package/package.json +10 -4
  19. package/plans/landing-page-launchkit-refresh.md +2 -2
  20. package/plugins/compound-engineering/.claude-plugin/plugin.json +2 -2
  21. package/plugins/compound-engineering/CHANGELOG.md +82 -1
  22. package/plugins/compound-engineering/CLAUDE.md +14 -7
  23. package/plugins/compound-engineering/README.md +10 -7
  24. package/plugins/compound-engineering/agents/research/git-history-analyzer.md +1 -1
  25. package/plugins/compound-engineering/agents/research/learnings-researcher.md +1 -1
  26. package/plugins/compound-engineering/agents/review/code-simplicity-reviewer.md +1 -1
  27. package/plugins/compound-engineering/commands/ce/brainstorm.md +145 -0
  28. package/plugins/compound-engineering/commands/ce/compound.md +240 -0
  29. package/plugins/compound-engineering/commands/ce/plan.md +636 -0
  30. package/plugins/compound-engineering/commands/ce/review.md +525 -0
  31. package/plugins/compound-engineering/commands/ce/work.md +470 -0
  32. package/plugins/compound-engineering/commands/create-agent-skill.md +1 -1
  33. package/plugins/compound-engineering/commands/deepen-plan.md +6 -6
  34. package/plugins/compound-engineering/commands/deploy-docs.md +1 -1
  35. package/plugins/compound-engineering/commands/feature-video.md +15 -6
  36. package/plugins/compound-engineering/commands/heal-skill.md +1 -1
  37. package/plugins/compound-engineering/commands/lfg.md +3 -3
  38. package/plugins/compound-engineering/commands/slfg.md +3 -3
  39. package/plugins/compound-engineering/commands/test-xcode.md +2 -2
  40. package/plugins/compound-engineering/commands/workflows/brainstorm.md +4 -123
  41. package/plugins/compound-engineering/commands/workflows/compound.md +4 -234
  42. package/plugins/compound-engineering/commands/workflows/plan.md +4 -562
  43. package/plugins/compound-engineering/commands/workflows/review.md +4 -522
  44. package/plugins/compound-engineering/commands/workflows/work.md +4 -448
  45. package/plugins/compound-engineering/skills/brainstorming/SKILL.md +3 -3
  46. package/plugins/compound-engineering/skills/create-agent-skills/workflows/add-workflow.md +6 -0
  47. package/plugins/compound-engineering/skills/create-agent-skills/workflows/create-new-skill.md +6 -0
  48. package/plugins/compound-engineering/skills/document-review/SKILL.md +1 -1
  49. package/plugins/compound-engineering/skills/file-todos/SKILL.md +1 -1
  50. package/plugins/compound-engineering/skills/git-worktree/SKILL.md +5 -5
  51. package/plugins/compound-engineering/skills/proof/SKILL.md +185 -0
  52. package/plugins/compound-engineering/skills/resolve-pr-parallel/SKILL.md +1 -1
  53. package/plugins/compound-engineering/skills/setup/SKILL.md +8 -2
  54. package/src/commands/convert.ts +101 -24
  55. package/src/commands/install.ts +102 -45
  56. package/src/commands/sync.ts +43 -62
  57. package/src/converters/claude-to-openclaw.ts +240 -0
  58. package/src/converters/claude-to-opencode.ts +12 -10
  59. package/src/converters/claude-to-qwen.ts +238 -0
  60. package/src/converters/claude-to-windsurf.ts +205 -0
  61. package/src/index.ts +2 -1
  62. package/src/parsers/claude-home.ts +55 -3
  63. package/src/sync/codex.ts +38 -62
  64. package/src/sync/commands.ts +198 -0
  65. package/src/sync/copilot.ts +14 -36
  66. package/src/sync/droid.ts +50 -9
  67. package/src/sync/gemini.ts +135 -0
  68. package/src/sync/json-config.ts +47 -0
  69. package/src/sync/kiro.ts +49 -0
  70. package/src/sync/mcp-transports.ts +19 -0
  71. package/src/sync/openclaw.ts +18 -0
  72. package/src/sync/opencode.ts +10 -30
  73. package/src/sync/pi.ts +12 -36
  74. package/src/sync/qwen.ts +66 -0
  75. package/src/sync/registry.ts +141 -0
  76. package/src/sync/skills.ts +21 -0
  77. package/src/sync/windsurf.ts +59 -0
  78. package/src/targets/index.ts +60 -1
  79. package/src/targets/openclaw.ts +96 -0
  80. package/src/targets/opencode.ts +76 -10
  81. package/src/targets/qwen.ts +64 -0
  82. package/src/targets/windsurf.ts +104 -0
  83. package/src/types/kiro.ts +3 -1
  84. package/src/types/openclaw.ts +52 -0
  85. package/src/types/opencode.ts +7 -8
  86. package/src/types/qwen.ts +51 -0
  87. package/src/types/windsurf.ts +35 -0
  88. package/src/utils/codex-agents.ts +1 -1
  89. package/src/utils/detect-tools.ts +37 -0
  90. package/src/utils/files.ts +14 -0
  91. package/src/utils/resolve-output.ts +50 -0
  92. package/src/utils/secrets.ts +24 -0
  93. package/src/utils/symlink.ts +4 -6
  94. package/tests/claude-home.test.ts +46 -0
  95. package/tests/cli.test.ts +180 -0
  96. package/tests/converter.test.ts +43 -10
  97. package/tests/detect-tools.test.ts +119 -0
  98. package/tests/openclaw-converter.test.ts +200 -0
  99. package/tests/opencode-writer.test.ts +142 -5
  100. package/tests/qwen-converter.test.ts +238 -0
  101. package/tests/resolve-output.test.ts +131 -0
  102. package/tests/sync-codex.test.ts +64 -0
  103. package/tests/sync-copilot.test.ts +60 -4
  104. package/tests/sync-droid.test.ts +44 -4
  105. package/tests/sync-gemini.test.ts +160 -0
  106. package/tests/sync-kiro.test.ts +83 -0
  107. package/tests/sync-openclaw.test.ts +51 -0
  108. package/tests/sync-qwen.test.ts +75 -0
  109. package/tests/sync-windsurf.test.ts +89 -0
  110. package/tests/windsurf-converter.test.ts +573 -0
  111. package/tests/windsurf-writer.test.ts +359 -0
  112. package/docs/css/docs.css +0 -675
  113. package/docs/css/style.css +0 -2886
  114. package/docs/index.html +0 -1046
  115. package/docs/js/main.js +0 -225
  116. package/docs/pages/agents.html +0 -649
  117. package/docs/pages/changelog.html +0 -534
  118. package/docs/pages/commands.html +0 -523
  119. package/docs/pages/getting-started.html +0 -582
  120. package/docs/pages/mcp-servers.html +0 -409
  121. package/docs/pages/skills.html +0 -611
@@ -0,0 +1,360 @@
1
+ ---
2
+ title: Auto-detect install targets and add Gemini sync
3
+ type: feat
4
+ status: completed
5
+ date: 2026-02-14
6
+ completed_date: 2026-02-14
7
+ completed_by: "Claude Opus 4.6"
8
+ actual_effort: "Completed in one session"
9
+ ---
10
+
11
+ # Auto-detect Install Targets and Add Gemini Sync
12
+
13
+ ## Overview
14
+
15
+ Two related improvements to the converter CLI:
16
+
17
+ 1. **`install --to all`** — Auto-detect which AI coding tools are installed and convert to all of them in one command
18
+ 2. **`sync --target gemini`** — Add Gemini CLI as a sync target (currently missing), then add `sync --target all` to sync personal config to every detected tool
19
+
20
+ ## Problem Statement
21
+
22
+ Users currently must run 6 separate commands to install to all targets:
23
+
24
+ ```bash
25
+ bunx @every-env/compound-plugin install compound-engineering --to opencode
26
+ bunx @every-env/compound-plugin install compound-engineering --to codex
27
+ bunx @every-env/compound-plugin install compound-engineering --to droid
28
+ bunx @every-env/compound-plugin install compound-engineering --to cursor
29
+ bunx @every-env/compound-plugin install compound-engineering --to pi
30
+ bunx @every-env/compound-plugin install compound-engineering --to gemini
31
+ ```
32
+
33
+ Similarly, sync requires separate commands per target. And Gemini sync doesn't exist yet.
34
+
35
+ ## Acceptance Criteria
36
+
37
+ ### Auto-detect install
38
+
39
+ - [x]`install --to all` detects installed tools and installs to each
40
+ - [x]Detection checks config directories and/or binaries for each tool
41
+ - [x]Prints which tools were detected and which were skipped
42
+ - [x]Tools with no detection signal are skipped (not errored)
43
+ - [x]`convert --to all` also works (same detection logic)
44
+ - [x]Existing `--to <target>` behavior unchanged
45
+ - [x]Tests for detection logic and `all` target handling
46
+
47
+ ### Gemini sync
48
+
49
+ - [x]`sync --target gemini` symlinks skills and writes MCP servers to `.gemini/settings.json`
50
+ - [x]MCP servers merged into existing `settings.json` (same pattern as writer)
51
+ - [x]`gemini` added to `validTargets` in `sync.ts`
52
+ - [x]Tests for Gemini sync
53
+
54
+ ### Sync all
55
+
56
+ - [x]`sync --target all` syncs to all detected tools
57
+ - [x]Reuses same detection logic as install
58
+ - [x]Prints summary of what was synced where
59
+
60
+ ## Implementation
61
+
62
+ ### Phase 1: Tool Detection Utility
63
+
64
+ **Create `src/utils/detect-tools.ts`**
65
+
66
+ ```typescript
67
+ import os from "os"
68
+ import path from "path"
69
+ import { pathExists } from "./files"
70
+
71
+ export type DetectedTool = {
72
+ name: string
73
+ detected: boolean
74
+ reason: string // e.g. "found ~/.codex/" or "not found"
75
+ }
76
+
77
+ export async function detectInstalledTools(): Promise<DetectedTool[]> {
78
+ const home = os.homedir()
79
+ const cwd = process.cwd()
80
+
81
+ const checks: Array<{ name: string; paths: string[] }> = [
82
+ { name: "opencode", paths: [path.join(home, ".config", "opencode"), path.join(cwd, ".opencode")] },
83
+ { name: "codex", paths: [path.join(home, ".codex")] },
84
+ { name: "droid", paths: [path.join(home, ".factory")] },
85
+ { name: "cursor", paths: [path.join(cwd, ".cursor"), path.join(home, ".cursor")] },
86
+ { name: "pi", paths: [path.join(home, ".pi")] },
87
+ { name: "gemini", paths: [path.join(cwd, ".gemini"), path.join(home, ".gemini")] },
88
+ ]
89
+
90
+ const results: DetectedTool[] = []
91
+ for (const check of checks) {
92
+ let detected = false
93
+ let reason = "not found"
94
+ for (const p of check.paths) {
95
+ if (await pathExists(p)) {
96
+ detected = true
97
+ reason = `found ${p}`
98
+ break
99
+ }
100
+ }
101
+ results.push({ name: check.name, detected, reason })
102
+ }
103
+ return results
104
+ }
105
+
106
+ export async function getDetectedTargetNames(): Promise<string[]> {
107
+ const tools = await detectInstalledTools()
108
+ return tools.filter((t) => t.detected).map((t) => t.name)
109
+ }
110
+ ```
111
+
112
+ **Detection heuristics:**
113
+
114
+ | Tool | Check paths | Notes |
115
+ |------|------------|-------|
116
+ | OpenCode | `~/.config/opencode/`, `.opencode/` | XDG config or project-local |
117
+ | Codex | `~/.codex/` | Global only |
118
+ | Droid | `~/.factory/` | Global only |
119
+ | Cursor | `.cursor/`, `~/.cursor/` | Project-local or global |
120
+ | Pi | `~/.pi/` | Global only |
121
+ | Gemini | `.gemini/`, `~/.gemini/` | Project-local or global |
122
+
123
+ ### Phase 2: Gemini Sync
124
+
125
+ **Create `src/sync/gemini.ts`**
126
+
127
+ Follow the Cursor sync pattern (`src/sync/cursor.ts`) since both use JSON config with `mcpServers` key:
128
+
129
+ ```typescript
130
+ import path from "path"
131
+ import { symlinkSkills } from "../utils/symlink"
132
+ import { backupFile, pathExists, readJson, writeJson } from "../utils/files"
133
+ import type { ClaudeMcpServer } from "../types/claude"
134
+
135
+ export async function syncToGemini(
136
+ skills: { name: string; sourceDir: string }[],
137
+ mcpServers: Record<string, ClaudeMcpServer>,
138
+ outputRoot: string,
139
+ ): Promise<void> {
140
+ const geminiDir = path.join(outputRoot, ".gemini")
141
+
142
+ // Symlink skills
143
+ if (skills.length > 0) {
144
+ const skillsDir = path.join(geminiDir, "skills")
145
+ await symlinkSkills(skills, skillsDir)
146
+ }
147
+
148
+ // Merge MCP servers into settings.json
149
+ if (Object.keys(mcpServers).length > 0) {
150
+ const settingsPath = path.join(geminiDir, "settings.json")
151
+ let existing: Record<string, unknown> = {}
152
+ if (await pathExists(settingsPath)) {
153
+ await backupFile(settingsPath)
154
+ try {
155
+ existing = await readJson<Record<string, unknown>>(settingsPath)
156
+ } catch {
157
+ console.warn("Warning: existing settings.json could not be parsed and will be replaced.")
158
+ }
159
+ }
160
+
161
+ const existingMcp = (existing.mcpServers && typeof existing.mcpServers === "object")
162
+ ? existing.mcpServers as Record<string, unknown>
163
+ : {}
164
+
165
+ const merged = { ...existing, mcpServers: { ...existingMcp, ...convertMcpServers(mcpServers) } }
166
+ await writeJson(settingsPath, merged)
167
+ }
168
+ }
169
+
170
+ function convertMcpServers(servers: Record<string, ClaudeMcpServer>) {
171
+ const result: Record<string, Record<string, unknown>> = {}
172
+ for (const [name, server] of Object.entries(servers)) {
173
+ const entry: Record<string, unknown> = {}
174
+ if (server.command) {
175
+ entry.command = server.command
176
+ if (server.args?.length) entry.args = server.args
177
+ if (server.env && Object.keys(server.env).length > 0) entry.env = server.env
178
+ } else if (server.url) {
179
+ entry.url = server.url
180
+ if (server.headers && Object.keys(server.headers).length > 0) entry.headers = server.headers
181
+ }
182
+ result[name] = entry
183
+ }
184
+ return result
185
+ }
186
+ ```
187
+
188
+ **Update `src/commands/sync.ts`:**
189
+
190
+ - Add `"gemini"` to `validTargets` array
191
+ - Import `syncToGemini` from `../sync/gemini`
192
+ - Add case in switch for `"gemini"` calling `syncToGemini(skills, mcpServers, outputRoot)`
193
+
194
+ ### Phase 3: Wire `--to all` into Install and Convert
195
+
196
+ **Modify `src/commands/install.ts`:**
197
+
198
+ ```typescript
199
+ import { detectInstalledTools } from "../utils/detect-tools"
200
+
201
+ // In args definition, update --to description:
202
+ to: {
203
+ type: "string",
204
+ default: "opencode",
205
+ description: "Target format (opencode | codex | droid | cursor | pi | gemini | all)",
206
+ },
207
+
208
+ // In run(), before the existing target lookup:
209
+ if (targetName === "all") {
210
+ const detected = await detectInstalledTools()
211
+ const activeTargets = detected.filter((t) => t.detected)
212
+
213
+ if (activeTargets.length === 0) {
214
+ console.log("No AI coding tools detected. Install at least one tool first.")
215
+ return
216
+ }
217
+
218
+ console.log(`Detected ${activeTargets.length} tools:`)
219
+ for (const tool of detected) {
220
+ console.log(` ${tool.detected ? "✓" : "✗"} ${tool.name} — ${tool.reason}`)
221
+ }
222
+
223
+ // Install to each detected target
224
+ for (const tool of activeTargets) {
225
+ const handler = targets[tool.name]
226
+ const bundle = handler.convert(plugin, options)
227
+ if (!bundle) continue
228
+ const root = resolveTargetOutputRoot(tool.name, outputRoot, codexHome, piHome, hasExplicitOutput)
229
+ await handler.write(root, bundle)
230
+ console.log(`Installed ${plugin.manifest.name} to ${tool.name} at ${root}`)
231
+ }
232
+
233
+ // Codex post-processing
234
+ if (activeTargets.some((t) => t.name === "codex")) {
235
+ await ensureCodexAgentsFile(codexHome)
236
+ }
237
+ return
238
+ }
239
+ ```
240
+
241
+ **Same change in `src/commands/convert.ts`** with its version of `resolveTargetOutputRoot`.
242
+
243
+ ### Phase 4: Wire `--target all` into Sync
244
+
245
+ **Modify `src/commands/sync.ts`:**
246
+
247
+ ```typescript
248
+ import { detectInstalledTools } from "../utils/detect-tools"
249
+
250
+ // Update validTargets:
251
+ const validTargets = ["opencode", "codex", "pi", "droid", "cursor", "gemini", "all"] as const
252
+
253
+ // In run(), handle "all":
254
+ if (targetName === "all") {
255
+ const detected = await detectInstalledTools()
256
+ const activeTargets = detected.filter((t) => t.detected).map((t) => t.name)
257
+
258
+ if (activeTargets.length === 0) {
259
+ console.log("No AI coding tools detected.")
260
+ return
261
+ }
262
+
263
+ console.log(`Syncing to ${activeTargets.length} detected tools...`)
264
+ for (const name of activeTargets) {
265
+ // call existing sync logic for each target
266
+ }
267
+ return
268
+ }
269
+ ```
270
+
271
+ ### Phase 5: Tests
272
+
273
+ **Create `tests/detect-tools.test.ts`**
274
+
275
+ - Test detection with mocked directories (create temp dirs, check detection)
276
+ - Test `getDetectedTargetNames` returns only detected tools
277
+ - Test empty detection returns empty array
278
+
279
+ **Create `tests/gemini-sync.test.ts`**
280
+
281
+ Follow `tests/sync-cursor.test.ts` pattern:
282
+
283
+ - Test skills are symlinked to `.gemini/skills/`
284
+ - Test MCP servers merged into `settings.json`
285
+ - Test existing `settings.json` is backed up
286
+ - Test empty skills/servers produce no output
287
+
288
+ **Update `tests/cli.test.ts`**
289
+
290
+ - Test `--to all` flag is accepted
291
+ - Test `sync --target all` is accepted
292
+ - Test `sync --target gemini` is accepted
293
+
294
+ ### Phase 6: Documentation
295
+
296
+ **Update `README.md`:**
297
+
298
+ Add to install section:
299
+ ```bash
300
+ # auto-detect installed tools and install to all
301
+ bunx @every-env/compound-plugin install compound-engineering --to all
302
+ ```
303
+
304
+ Add to sync section:
305
+ ```bash
306
+ # Sync to Gemini
307
+ bunx @every-env/compound-plugin sync --target gemini
308
+
309
+ # Sync to all detected tools
310
+ bunx @every-env/compound-plugin sync --target all
311
+ ```
312
+
313
+ ## What We're NOT Doing
314
+
315
+ - Not adding binary detection (`which cursor`, `which gemini`) — directory checks are sufficient and don't require shell execution
316
+ - Not adding interactive prompts ("Install to Cursor? y/n") — auto-detect is fire-and-forget
317
+ - Not adding `--exclude` flag for skipping specific targets — can use `--to X --also Y` for manual selection
318
+ - Not adding Gemini to the `sync` symlink watcher (no watcher exists for any target)
319
+
320
+ ## Complexity Assessment
321
+
322
+ **Low-medium change.** All patterns are established:
323
+ - Detection utility is new but simple (pathExists checks)
324
+ - Gemini sync follows cursor sync pattern exactly
325
+ - `--to all` is plumbing — iterate detected tools through existing handlers
326
+ - No new dependencies needed
327
+
328
+ ## References
329
+
330
+ - Cursor sync (reference pattern): `src/sync/cursor.ts`
331
+ - Gemini writer (merge pattern): `src/targets/gemini.ts`
332
+ - Install command: `src/commands/install.ts`
333
+ - Sync command: `src/commands/sync.ts`
334
+ - File utilities: `src/utils/files.ts`
335
+ - Symlink utilities: `src/utils/symlink.ts`
336
+
337
+ ## Completion Summary
338
+
339
+ ### What Was Delivered
340
+ - Tool detection utility (`src/utils/detect-tools.ts`) with `detectInstalledTools()` and `getDetectedTargetNames()`
341
+ - Gemini sync (`src/sync/gemini.ts`) following cursor sync pattern — symlinks skills, merges MCP servers into `settings.json`
342
+ - `install --to all` and `convert --to all` auto-detect and install to all detected tools
343
+ - `sync --target gemini` added to sync command
344
+ - `sync --target all` syncs to all detected tools with summary output
345
+ - 8 new tests across 2 test files (detect-tools + sync-gemini)
346
+
347
+ ### Implementation Statistics
348
+ - 4 new files, 3 modified files
349
+ - 139 tests passing (8 new + 131 existing)
350
+ - No new dependencies
351
+
352
+ ### Git Commits
353
+ - `e4d730d` feat: add detect-tools utility and Gemini sync with tests
354
+ - `bc655f7` feat: wire --to all into install/convert and --target all/gemini into sync
355
+ - `877e265` docs: add auto-detect and Gemini sync to README, bump to 0.8.0
356
+
357
+ ### Completion Details
358
+ - **Completed By:** Claude Opus 4.6
359
+ - **Date:** 2026-02-14
360
+ - **Session:** Single session, TDD approach