summer-engine 2.0.0 → 2.3.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 (62) hide show
  1. package/{marketplace.json → .claude-plugin/marketplace.json} +3 -3
  2. package/.claude-plugin/plugin.json +37 -4
  3. package/.codex-plugin/plugin.json +38 -5
  4. package/.cursor-plugin/plugin.json +37 -4
  5. package/.factory-plugin/plugin.json +20 -0
  6. package/.opencode/INSTALL.md +9 -3
  7. package/.opencode/plugins/summer.js +0 -2
  8. package/AGENTS.md +51 -0
  9. package/CLAUDE.md +5 -0
  10. package/GEMINI.md +56 -0
  11. package/README.md +211 -61
  12. package/_persona/summer/SKILL.md +113 -0
  13. package/dist/commands/install.js +2 -2
  14. package/dist/commands/setup.js +4 -0
  15. package/dist/commands/skills.js +115 -2
  16. package/dist/lib/agent-config.d.ts +2 -2
  17. package/dist/lib/agent-config.js +171 -5
  18. package/dist/lib/skills-registry.d.ts +290 -26
  19. package/dist/lib/skills-registry.js +503 -1
  20. package/dist/mcp/tools/generate-tools.js +101 -0
  21. package/gemini-extension.json +2 -2
  22. package/package.json +9 -3
  23. package/skills/2d-assets/character-portrait/SKILL.md +196 -0
  24. package/skills/2d-assets/concept-art/SKILL.md +152 -0
  25. package/skills/2d-assets/pixel-art/SKILL.md +180 -0
  26. package/skills/2d-assets/skybox-panorama/SKILL.md +207 -0
  27. package/skills/2d-assets/sprite-sheet/SKILL.md +239 -0
  28. package/skills/2d-assets/tileable-texture/SKILL.md +205 -0
  29. package/skills/2d-assets/ui-graphics/SKILL.md +210 -0
  30. package/skills/3d-assets/character-model/SKILL.md +225 -0
  31. package/skills/3d-assets/environment-kit/SKILL.md +164 -0
  32. package/skills/3d-assets/organic-model/SKILL.md +192 -0
  33. package/skills/3d-assets/prop-model/SKILL.md +133 -0
  34. package/skills/3d-assets/vehicle-model/SKILL.md +202 -0
  35. package/skills/ai-and-npcs/design-npc/SKILL.md +3 -1
  36. package/skills/animation/animation-tree/SKILL.md +260 -0
  37. package/skills/animation/facial-and-lipsync/SKILL.md +282 -0
  38. package/skills/animation/generate-motion/SKILL.md +129 -0
  39. package/skills/animation/procedural-animation/SKILL.md +234 -0
  40. package/skills/animation/retarget/SKILL.md +172 -0
  41. package/skills/asset-pipeline/asset-strategy/SKILL.md +102 -212
  42. package/skills/audio/adaptive-music/SKILL.md +326 -0
  43. package/skills/audio/ambient-bed/SKILL.md +278 -0
  44. package/skills/audio/music-track/SKILL.md +268 -0
  45. package/skills/audio/sound-effect/SKILL.md +237 -0
  46. package/skills/audio/voice-line/SKILL.md +253 -0
  47. package/skills/catalog.yaml +249 -3
  48. package/skills/video/animated-loop/SKILL.md +200 -0
  49. package/skills/video/cinematic-cutscene/SKILL.md +204 -0
  50. package/skills/video/trailer-shot/SKILL.md +203 -0
  51. package/skills/visual-effects/_building-blocks/additive-billboard-particles.md +28 -0
  52. package/skills/visual-effects/_building-blocks/noise-3d-fbm.gdshaderinc +45 -0
  53. package/skills/visual-effects/_building-blocks/trauma-shake-snippet.md +51 -0
  54. package/skills/visual-effects/{vfx → game-feel}/SKILL.md +1 -1
  55. package/skills/visual-effects/recipes/dissolve/SKILL.md +349 -0
  56. package/skills/visual-effects/recipes/fire/SKILL.md +387 -0
  57. package/skills/visual-effects/recipes/hit-spark/SKILL.md +330 -0
  58. package/skills/visual-effects/recipes/lightning/SKILL.md +372 -0
  59. package/skills/visual-effects/recipes/magic-glow/SKILL.md +377 -0
  60. package/skills/visual-effects/recipes/muzzle-flash/SKILL.md +326 -0
  61. package/skills/visual-effects/recipes/smoke/SKILL.md +381 -0
  62. package/skills/visual-effects/recipes/water-ripple/SKILL.md +340 -0
@@ -2,7 +2,7 @@ import { Command } from "commander";
2
2
  import { existsSync, mkdirSync, readFileSync, cpSync, writeFileSync, } from "fs";
3
3
  import { join, dirname } from "path";
4
4
  import { fileURLToPath } from "url";
5
- import { homedir } from "os";
5
+ import { homedir, platform } from "os";
6
6
  import { AGENT_CLIENTS, SKILL_REGISTRY, } from "../lib/skills-registry.js";
7
7
  import { tildeify } from "../lib/format.js";
8
8
  const __dirname = dirname(fileURLToPath(import.meta.url));
@@ -102,8 +102,12 @@ function resolveAgent(opts) {
102
102
  function resolveScope(agent, opts) {
103
103
  if (opts.scope)
104
104
  return parseScope(opts.scope);
105
- if (agent === "cursor" || agent === "windsurf")
105
+ if (agent === "cursor" ||
106
+ agent === "windsurf" ||
107
+ agent === "cline" ||
108
+ agent === "roo-code") {
106
109
  return "project";
110
+ }
107
111
  return "user";
108
112
  }
109
113
  function agentLabel(agent) {
@@ -116,6 +120,14 @@ function agentLabel(agent) {
116
120
  return "Cursor";
117
121
  case "windsurf":
118
122
  return "Windsurf";
123
+ case "cline":
124
+ return "Cline";
125
+ case "roo-code":
126
+ return "Roo Code";
127
+ case "gemini":
128
+ return "Gemini CLI";
129
+ case "opencode":
130
+ return "OpenCode";
119
131
  case "summer":
120
132
  return "Summer";
121
133
  }
@@ -128,6 +140,15 @@ function resolveInstallLocation(agent, scope) {
128
140
  if (agent === "windsurf") {
129
141
  return { kind: "windsurf-rule-file", path: join(overrideDir, ".windsurfrules") };
130
142
  }
143
+ if (agent === "cline" || agent === "roo-code") {
144
+ return { kind: "cline-rule-dir", path: overrideDir };
145
+ }
146
+ if (agent === "gemini") {
147
+ return { kind: "gemini-skill-dir", path: overrideDir };
148
+ }
149
+ if (agent === "opencode") {
150
+ return { kind: "opencode-skill-dir", path: overrideDir };
151
+ }
131
152
  return { kind: "skill-dir", path: overrideDir };
132
153
  }
133
154
  const root = scope === "user" ? homedir() : process.cwd();
@@ -140,10 +161,55 @@ function resolveInstallLocation(agent, scope) {
140
161
  return { kind: "cursor-rule-dir", path: join(root, ".cursor", "rules") };
141
162
  case "windsurf":
142
163
  return { kind: "windsurf-rule-file", path: join(root, ".windsurfrules") };
164
+ case "cline":
165
+ return {
166
+ kind: "cline-rule-dir",
167
+ path: scope === "user"
168
+ ? clineUserRulesDir()
169
+ : join(process.cwd(), ".clinerules"),
170
+ };
171
+ case "roo-code":
172
+ return {
173
+ kind: "cline-rule-dir",
174
+ path: scope === "user"
175
+ ? rooCodeUserRulesDir()
176
+ : join(process.cwd(), ".clinerules"),
177
+ };
178
+ case "gemini":
179
+ return {
180
+ kind: "gemini-skill-dir",
181
+ path: join(homedir(), ".gemini", "extensions", "summer-engine", "skills"),
182
+ };
183
+ case "opencode":
184
+ return {
185
+ kind: "opencode-skill-dir",
186
+ path: scope === "user"
187
+ ? opencodeUserAgentsDir()
188
+ : join(process.cwd(), ".opencode", "agents", "summer"),
189
+ };
143
190
  case "summer":
144
191
  return { kind: "skill-dir", path: join(root, ".summer", "skills") };
145
192
  }
146
193
  }
194
+ function clineUserRulesDir() {
195
+ // Cline reads global rules from the user's Documents/Cline/Rules folder.
196
+ return join(homedir(), "Documents", "Cline", "Rules");
197
+ }
198
+ function rooCodeUserRulesDir() {
199
+ // Roo Code reads global rules from the user's Documents/Roo/Rules folder.
200
+ return join(homedir(), "Documents", "Roo", "Rules");
201
+ }
202
+ function opencodeUserAgentsDir() {
203
+ // OpenCode's user-scope agent definition directory varies by OS.
204
+ // On Windows, OpenCode reads from %APPDATA%/opencode/agents/summer.
205
+ // On Linux/macOS, it reads from $XDG_CONFIG_HOME or ~/.config/opencode/agents/summer.
206
+ if (platform() === "win32") {
207
+ const appData = process.env.APPDATA ?? join(homedir(), "AppData", "Roaming");
208
+ return join(appData, "opencode", "agents", "summer");
209
+ }
210
+ const xdg = process.env.XDG_CONFIG_HOME ?? join(homedir(), ".config");
211
+ return join(xdg, "opencode", "agents", "summer");
212
+ }
147
213
  function selectSkills(name, opts) {
148
214
  if (opts.all && opts.recommended) {
149
215
  die("Use only one bulk option: --all or --recommended.");
@@ -189,6 +255,12 @@ function installSkill(skill, agent, location) {
189
255
  return writeCursorRule(skill, location.path);
190
256
  case "windsurf-rule-file":
191
257
  return upsertWindsurfRule(skill, location.path);
258
+ case "cline-rule-dir":
259
+ return writeClineRule(skill, location.path);
260
+ case "gemini-skill-dir":
261
+ return writeGeminiSkill(skill, location.path);
262
+ case "opencode-skill-dir":
263
+ return writeOpencodeSkill(skill, location.path);
192
264
  }
193
265
  }
194
266
  function copySkillDirectory(skill, targetDir) {
@@ -219,6 +291,35 @@ function upsertWindsurfRule(skill, rulePath) {
219
291
  writeFileSync(rulePath, next, "utf-8");
220
292
  return { action: "Generated", path: rulePath };
221
293
  }
294
+ function writeClineRule(skill, rulesDir) {
295
+ // Cline + Roo Code read project rules from .clinerules/ and global rules
296
+ // from Documents/Cline (or Roo)/Rules. Both expect plain markdown files.
297
+ // SKILL.md isn't recognized as a special filename, so we name files <skill>.md.
298
+ mkdirSync(rulesDir, { recursive: true });
299
+ const rulePath = join(rulesDir, `summer-${skill.name}.md`);
300
+ writeFileSync(rulePath, renderRuleBody(skill) + "\n", "utf-8");
301
+ return { action: "Generated", path: rulePath };
302
+ }
303
+ function writeGeminiSkill(skill, skillsDir) {
304
+ // Gemini extensions support a contextFileName, but skill discovery for
305
+ // arbitrary markdown is not standardized. We drop each SKILL.md alongside
306
+ // the extension so the agent can reference them by path; the install
307
+ // summary surfaces this so the user knows where to point Gemini.
308
+ mkdirSync(skillsDir, { recursive: true });
309
+ const rulePath = join(skillsDir, `${skill.name}.md`);
310
+ writeFileSync(rulePath, renderRuleBody(skill) + "\n", "utf-8");
311
+ return { action: "Generated", path: rulePath };
312
+ }
313
+ function writeOpencodeSkill(skill, skillsDir) {
314
+ // OpenCode supports agent markdown definitions; the exact discovery
315
+ // convention for ad-hoc skills isn't fully documented. We write each skill
316
+ // as a markdown file under agents/summer/ so OpenCode can reference them
317
+ // directly. The install summary shows the path.
318
+ mkdirSync(skillsDir, { recursive: true });
319
+ const rulePath = join(skillsDir, `${skill.name}.md`);
320
+ writeFileSync(rulePath, renderRuleBody(skill) + "\n", "utf-8");
321
+ return { action: "Generated", path: rulePath };
322
+ }
222
323
  function renderCursorRule(skill) {
223
324
  const description = `Summer skill ${skill.name}: ${skill.description}`;
224
325
  return `---\ndescription: ${JSON.stringify(description)}\nglobs: []\nalwaysApply: false\n---\n\n${renderRuleBody(skill)}\n`;
@@ -251,6 +352,18 @@ function printInstallSummary(count, agent, scope, location) {
251
352
  else if (location.kind === "cursor-rule-dir") {
252
353
  console.log(`Cursor rules are in ${tildeified}/summer-<skill>.mdc`);
253
354
  }
355
+ else if (location.kind === "cline-rule-dir") {
356
+ console.log(`${label} rules are in ${tildeified}/summer-<skill>.md`);
357
+ console.log("Restart VS Code to pick up new rules.");
358
+ }
359
+ else if (location.kind === "gemini-skill-dir") {
360
+ console.log(`Skill files are in ${tildeified}/<skill>.md`);
361
+ console.log("Reference them from Gemini by path, or run `gemini extensions enable summer-engine` to load the bundled context.");
362
+ }
363
+ else if (location.kind === "opencode-skill-dir") {
364
+ console.log(`Skill files are in ${tildeified}/<skill>.md`);
365
+ console.log("Restart OpenCode so it picks up the new agent definitions.");
366
+ }
254
367
  else {
255
368
  console.log(`Windsurf rules are in ${tildeified}`);
256
369
  }
@@ -1,5 +1,5 @@
1
1
  export declare const SUMMER_MCP_SERVER_NAME = "summer-engine";
2
- export declare const supportedAgents: readonly ["codex", "claude-code", "cursor", "windsurf"];
2
+ export declare const supportedAgents: readonly ["codex", "claude-code", "cursor", "windsurf", "cline", "roo-code", "gemini", "opencode"];
3
3
  export type SupportedAgent = (typeof supportedAgents)[number];
4
4
  export type ConfigScope = "user" | "project";
5
5
  export interface StdioMcpServerConfig {
@@ -22,7 +22,7 @@ export interface AgentConfigResult {
22
22
  path: string;
23
23
  serverName: string;
24
24
  server: StdioMcpServerConfig;
25
- format: "json" | "toml";
25
+ format: "json" | "toml" | "json-opencode";
26
26
  snippet: string;
27
27
  changed: boolean;
28
28
  wrote: boolean;
@@ -2,13 +2,17 @@ import { existsSync } from "fs";
2
2
  import { mkdir, readFile, writeFile } from "fs/promises";
3
3
  import { dirname, join, resolve } from "path";
4
4
  import { fileURLToPath } from "url";
5
- import { homedir } from "os";
5
+ import { homedir, platform } from "os";
6
6
  export const SUMMER_MCP_SERVER_NAME = "summer-engine";
7
7
  export const supportedAgents = [
8
8
  "codex",
9
9
  "claude-code",
10
10
  "cursor",
11
11
  "windsurf",
12
+ "cline",
13
+ "roo-code",
14
+ "gemini",
15
+ "opencode",
12
16
  ];
13
17
  const agentAliases = {
14
18
  claude: "claude-code",
@@ -16,6 +20,14 @@ const agentAliases = {
16
20
  codex: "codex",
17
21
  cursor: "cursor",
18
22
  windsurf: "windsurf",
23
+ cline: "cline",
24
+ "roo-code": "roo-code",
25
+ roo: "roo-code",
26
+ roocode: "roo-code",
27
+ gemini: "gemini",
28
+ "gemini-cli": "gemini",
29
+ opencode: "opencode",
30
+ "open-code": "opencode",
19
31
  };
20
32
  export function parseAgent(value) {
21
33
  if (!value)
@@ -43,7 +55,11 @@ export async function configureAgentMcp(options) {
43
55
  ? { changed: true }
44
56
  : target.format === "toml"
45
57
  ? await upsertCodexConfig(target.path, server, shouldWrite)
46
- : await upsertJsonMcpConfig(target.path, server, shouldWrite);
58
+ : target.format === "json-opencode"
59
+ ? await upsertOpencodeConfig(target.path, server, shouldWrite)
60
+ : options.agent === "gemini"
61
+ ? await upsertGeminiExtension(target.path, server, shouldWrite)
62
+ : await upsertJsonMcpConfig(target.path, server, shouldWrite);
47
63
  return {
48
64
  agent: options.agent,
49
65
  scope: options.scope,
@@ -70,13 +86,24 @@ export function createSummerMcpServerConfig(localDev) {
70
86
  }
71
87
  return {
72
88
  command: "npx",
73
- args: ["summer-engine", "mcp"],
89
+ args: ["-y", "summer-engine@latest", "mcp"],
74
90
  };
75
91
  }
76
92
  export function renderConfigSnippet(agent, server) {
77
93
  if (agent === "codex") {
78
94
  return renderCodexServerTable(server);
79
95
  }
96
+ if (agent === "opencode") {
97
+ return (JSON.stringify({
98
+ $schema: "https://opencode.ai/config.json",
99
+ mcp: {
100
+ [SUMMER_MCP_SERVER_NAME]: opencodeServerEntry(server),
101
+ },
102
+ }, null, 2) + "\n");
103
+ }
104
+ if (agent === "gemini") {
105
+ return (JSON.stringify(geminiExtensionManifest(server), null, 2) + "\n");
106
+ }
80
107
  return (JSON.stringify({
81
108
  mcpServers: {
82
109
  [SUMMER_MCP_SERVER_NAME]: server,
@@ -91,9 +118,17 @@ function resolveConfigTarget(agent, scope, cwd, env) {
91
118
  const override = getConfigPathOverride(agent, env);
92
119
  const warnings = [];
93
120
  if (override) {
121
+ if (scope === "project" &&
122
+ (agent === "cline" || agent === "roo-code" || agent === "gemini")) {
123
+ warnings.push(`${agent} MCP config has no project scope today; treating as user scope.`);
124
+ }
94
125
  return {
95
126
  path: resolve(override),
96
- format: agent === "codex" ? "toml" : "json",
127
+ format: agent === "codex"
128
+ ? "toml"
129
+ : agent === "opencode"
130
+ ? "json-opencode"
131
+ : "json",
97
132
  warnings,
98
133
  };
99
134
  }
@@ -124,6 +159,45 @@ function resolveConfigTarget(agent, scope, cwd, env) {
124
159
  warnings,
125
160
  };
126
161
  }
162
+ if (agent === "cline") {
163
+ if (scope === "project") {
164
+ warnings.push("Cline MCP config has no project scope today; writing to user-scope global VS Code storage instead.");
165
+ }
166
+ return {
167
+ path: vsCodeGlobalStoragePath(env, "saoudrizwan.claude-dev"),
168
+ format: "json",
169
+ warnings,
170
+ };
171
+ }
172
+ if (agent === "roo-code") {
173
+ if (scope === "project") {
174
+ warnings.push("Roo Code MCP config has no project scope today; writing to user-scope global VS Code storage instead.");
175
+ }
176
+ return {
177
+ path: vsCodeGlobalStoragePath(env, "rooveterinaryinc.roo-cline"),
178
+ format: "json",
179
+ warnings,
180
+ };
181
+ }
182
+ if (agent === "gemini") {
183
+ if (scope === "project") {
184
+ warnings.push("Gemini extensions are user-scoped today; writing to ~/.gemini/extensions/summer-engine/ instead of project.");
185
+ }
186
+ return {
187
+ path: join(homedir(), ".gemini", "extensions", "summer-engine", "gemini-extension.json"),
188
+ format: "json",
189
+ warnings,
190
+ };
191
+ }
192
+ if (agent === "opencode") {
193
+ return {
194
+ path: scope === "user"
195
+ ? opencodeUserConfigPath(env)
196
+ : join(cwd, "opencode.json"),
197
+ format: "json-opencode",
198
+ warnings,
199
+ };
200
+ }
127
201
  if (scope === "project") {
128
202
  warnings.push("Windsurf documents MCP configuration as user-scoped; project scope writes .windsurf/mcp_config.json for teams that load workspace config.");
129
203
  }
@@ -135,6 +209,28 @@ function resolveConfigTarget(agent, scope, cwd, env) {
135
209
  warnings,
136
210
  };
137
211
  }
212
+ function vsCodeGlobalStoragePath(env, extensionId) {
213
+ const os = platform();
214
+ if (os === "win32") {
215
+ const appData = env.APPDATA ?? join(homedir(), "AppData", "Roaming");
216
+ return join(appData, "Code", "User", "globalStorage", extensionId, "settings", "cline_mcp_settings.json");
217
+ }
218
+ if (os === "darwin") {
219
+ return join(homedir(), "Library", "Application Support", "Code", "User", "globalStorage", extensionId, "settings", "cline_mcp_settings.json");
220
+ }
221
+ // Linux and other Unix
222
+ const xdg = env.XDG_CONFIG_HOME ?? join(homedir(), ".config");
223
+ return join(xdg, "Code", "User", "globalStorage", extensionId, "settings", "cline_mcp_settings.json");
224
+ }
225
+ function opencodeUserConfigPath(env) {
226
+ const os = platform();
227
+ if (os === "win32") {
228
+ const appData = env.APPDATA ?? join(homedir(), "AppData", "Roaming");
229
+ return join(appData, "opencode", "opencode.json");
230
+ }
231
+ const xdg = env.XDG_CONFIG_HOME ?? join(homedir(), ".config");
232
+ return join(xdg, "opencode", "opencode.json");
233
+ }
138
234
  function getConfigPathOverride(agent, env) {
139
235
  if (agent === "codex")
140
236
  return env.SUMMER_CODEX_CONFIG_FILE;
@@ -142,6 +238,14 @@ function getConfigPathOverride(agent, env) {
142
238
  return env.SUMMER_CLAUDE_CONFIG_FILE;
143
239
  if (agent === "cursor")
144
240
  return env.SUMMER_CURSOR_MCP_CONFIG_FILE;
241
+ if (agent === "cline")
242
+ return env.SUMMER_CLINE_CONFIG_FILE;
243
+ if (agent === "roo-code")
244
+ return env.SUMMER_ROO_CODE_CONFIG_FILE;
245
+ if (agent === "gemini")
246
+ return env.SUMMER_GEMINI_CONFIG_FILE;
247
+ if (agent === "opencode")
248
+ return env.SUMMER_OPENCODE_CONFIG_FILE;
145
249
  return env.SUMMER_WINDSURF_MCP_CONFIG_FILE;
146
250
  }
147
251
  async function upsertJsonMcpConfig(path, server, write) {
@@ -198,6 +302,60 @@ async function upsertCodexConfig(path, server, write) {
198
302
  }
199
303
  return { changed };
200
304
  }
305
+ async function upsertOpencodeConfig(path, server, write) {
306
+ const current = await readJsonConfig(path);
307
+ const next = copyJsonObject(current);
308
+ if (typeof next.$schema !== "string") {
309
+ next.$schema = "https://opencode.ai/config.json";
310
+ }
311
+ const existingMcp = isJsonObject(next.mcp) ? next.mcp : {};
312
+ next.mcp = {
313
+ ...existingMcp,
314
+ [SUMMER_MCP_SERVER_NAME]: opencodeServerEntry(server),
315
+ };
316
+ const currentRendered = renderJsonFile(current);
317
+ const nextRendered = renderJsonFile(next);
318
+ const changed = currentRendered !== nextRendered;
319
+ if (write && changed) {
320
+ await writeTextFile(path, nextRendered);
321
+ }
322
+ return { changed };
323
+ }
324
+ async function upsertGeminiExtension(path, server, write) {
325
+ const current = await readJsonConfig(path);
326
+ const next = geminiExtensionManifest(server, current);
327
+ const currentRendered = renderJsonFile(current);
328
+ const nextRendered = renderJsonFile(next);
329
+ const changed = currentRendered !== nextRendered;
330
+ if (write && changed) {
331
+ await writeTextFile(path, nextRendered);
332
+ }
333
+ return { changed };
334
+ }
335
+ function opencodeServerEntry(server) {
336
+ const entry = {
337
+ type: "local",
338
+ command: [server.command, ...server.args],
339
+ };
340
+ if (server.env && Object.keys(server.env).length > 0) {
341
+ entry.environment = { ...server.env };
342
+ }
343
+ return entry;
344
+ }
345
+ function geminiExtensionManifest(server, base = {}) {
346
+ const manifest = { ...base };
347
+ manifest.name = "summer";
348
+ manifest.description =
349
+ "Superpowers for AI game dev. MCP bridge to the local Summer Engine plus a context primer that teaches Gemini the Summer skills.";
350
+ manifest.contextFileName = "GEMINI.md";
351
+ manifest.mcpServers = {
352
+ [SUMMER_MCP_SERVER_NAME]: {
353
+ command: server.command,
354
+ args: server.args,
355
+ },
356
+ };
357
+ return manifest;
358
+ }
201
359
  async function readTextFileIfExists(path) {
202
360
  if (!existsSync(path))
203
361
  return "";
@@ -273,7 +431,15 @@ function createNextSteps(agent, scope, path) {
273
431
  ? "Restart Codex or run /mcp in a new session."
274
432
  : agent === "cursor"
275
433
  ? "Restart Cursor and enable the summer-engine MCP server if prompted."
276
- : "Restart Windsurf and refresh MCP servers from Cascade settings.";
434
+ : agent === "cline"
435
+ ? "Restart VS Code so Cline reloads its MCP config."
436
+ : agent === "roo-code"
437
+ ? "Restart VS Code so Roo Code reloads its MCP config."
438
+ : agent === "gemini"
439
+ ? "Run `gemini extensions enable summer-engine` (if not already enabled), then restart Gemini CLI."
440
+ : agent === "opencode"
441
+ ? "Restart OpenCode so it reloads opencode.json."
442
+ : "Restart Windsurf and refresh MCP servers from Cascade settings.";
277
443
  const projectTrust = scope === "project" && agent === "codex"
278
444
  ? "Codex only loads project .codex/config.toml from trusted projects."
279
445
  : null;