summer-engine 2.2.0 → 2.5.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 (176) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +20 -5
  3. package/.codex-plugin/plugin.json +15 -5
  4. package/.cursor-plugin/plugin.json +15 -5
  5. package/.factory-plugin/plugin.json +2 -2
  6. package/.opencode/INSTALL.md +1 -1
  7. package/CHANGELOG.md +27 -6
  8. package/CLAUDE.md +2 -2
  9. package/GEMINI.md +2 -3
  10. package/README.md +82 -58
  11. package/_persona/summer/SKILL.md +5 -6
  12. package/commands/gameskill.md +103 -0
  13. package/dist/bin/summer.js +12 -4
  14. package/dist/commands/create.js +2 -0
  15. package/dist/commands/doctor.js +71 -1
  16. package/dist/commands/install.d.ts +17 -0
  17. package/dist/commands/install.js +63 -4
  18. package/dist/commands/memory.d.ts +14 -0
  19. package/dist/commands/memory.js +196 -0
  20. package/dist/commands/setup.js +12 -2
  21. package/dist/commands/skills.js +205 -8
  22. package/dist/commands/status.js +3 -0
  23. package/dist/lib/agent-config.d.ts +2 -2
  24. package/dist/lib/agent-config.js +298 -5
  25. package/dist/lib/api-client.d.ts +13 -0
  26. package/dist/lib/api-client.js +63 -26
  27. package/dist/lib/async-op-lifecycle.d.ts +60 -0
  28. package/dist/lib/async-op-lifecycle.js +83 -0
  29. package/dist/lib/project-memory.d.ts +33 -0
  30. package/dist/lib/project-memory.js +220 -0
  31. package/dist/lib/skills-registry.d.ts +134 -61
  32. package/dist/lib/skills-registry.js +106 -4
  33. package/dist/lib/version-check.d.ts +106 -0
  34. package/dist/lib/version-check.js +338 -0
  35. package/dist/mcp/server.d.ts +2 -0
  36. package/dist/mcp/server.js +81 -0
  37. package/dist/mcp/tools/debug-tools.js +32 -2
  38. package/dist/mcp/tools/project-tools.js +18 -6
  39. package/dist/mcp/tools/with-engine.d.ts +14 -0
  40. package/dist/mcp/tools/with-engine.js +52 -7
  41. package/gemini-extension.json +2 -2
  42. package/hooks/pre-commit-doctor.sh +0 -0
  43. package/hooks/run-hook.cmd +0 -0
  44. package/hooks/session-start.sh +0 -0
  45. package/package.json +6 -4
  46. package/skills/2d-assets/character-portrait/SKILL.md +1 -1
  47. package/skills/2d-assets/concept-art/SKILL.md +1 -1
  48. package/skills/2d-assets/create-asset-sheet/SKILL.md +163 -0
  49. package/skills/2d-assets/instantiate-asset-pack/SKILL.md +245 -0
  50. package/skills/2d-assets/pixel-art/SKILL.md +1 -1
  51. package/skills/2d-assets/skybox-panorama/SKILL.md +1 -1
  52. package/skills/2d-assets/sprite-sheet/SKILL.md +1 -1
  53. package/skills/2d-assets/tileable-texture/SKILL.md +1 -1
  54. package/skills/2d-assets/ui-graphics/SKILL.md +1 -1
  55. package/skills/2d-assets/use-widget-asset/SKILL.md +217 -0
  56. package/skills/3d-assets/character-model/SKILL.md +1 -1
  57. package/skills/3d-assets/organic-model/SKILL.md +1 -1
  58. package/skills/3d-assets/prop-model/SKILL.md +1 -1
  59. package/skills/3d-assets/vehicle-model/SKILL.md +1 -1
  60. package/skills/README.md +37 -30
  61. package/skills/ai-and-npcs/design-npc/SKILL.md +6 -6
  62. package/skills/animation/animation-tree/SKILL.md +2 -2
  63. package/skills/animation/facial-and-lipsync/SKILL.md +1 -1
  64. package/skills/animation/generate-motion/SKILL.md +1 -1
  65. package/skills/animation/procedural-animation/SKILL.md +2 -2
  66. package/skills/audio/adaptive-music/SKILL.md +1 -1
  67. package/skills/audio/audio-direction/SKILL.md +5 -5
  68. package/skills/audio/sound-effect/SKILL.md +2 -2
  69. package/skills/audio/voice-line/SKILL.md +25 -3
  70. package/skills/character-controllers/fps-controller/SKILL.md +5 -5
  71. package/skills/debugging/debug/SKILL.md +39 -1
  72. package/skills/deployment/export-and-ship/SKILL.md +4 -4
  73. package/skills/gameplay-mechanics/auto-fire-targeting/SKILL.md +170 -0
  74. package/skills/gameplay-mechanics/design-mechanic/SKILL.md +8 -8
  75. package/skills/level-design/design-level/SKILL.md +5 -5
  76. package/skills/level-design/scene-to-level/SKILL.md +125 -0
  77. package/skills/multiplayer-and-networking/host-authoritative-state/SKILL.md +4 -4
  78. package/skills/multiplayer-and-networking/peer-to-peer-multiplayer/SKILL.md +4 -4
  79. package/skills/multiplayer-and-networking/setup-multiplayer/SKILL.md +7 -7
  80. package/skills/performance/tune-performance/SKILL.md +5 -5
  81. package/skills/rendering-and-lighting/3d-lighting/SKILL.md +1 -1
  82. package/skills/rendering-and-lighting/art-direction/SKILL.md +5 -5
  83. package/skills/scene-and-project/brainstorm-game/SKILL.md +4 -4
  84. package/skills/scene-and-project/play/SKILL.md +1 -1
  85. package/skills/scene-and-project/scene-composition/SKILL.md +30 -1
  86. package/skills/scripting-patterns/gdscript-patterns/SKILL.md +53 -0
  87. package/skills/ui-and-ux/ui-basics/SKILL.md +1 -1
  88. package/skills/video/animated-loop/SKILL.md +1 -1
  89. package/skills/video/cinematic-cutscene/SKILL.md +1 -1
  90. package/skills/video/trailer-shot/SKILL.md +1 -1
  91. package/skills/visual-effects/game-feel/SKILL.md +6 -6
  92. package/skills/workflow/brainstorming/SKILL.md +164 -0
  93. package/skills/workflow/brainstorming/scripts/frame-template.html +214 -0
  94. package/skills/workflow/brainstorming/scripts/helper.js +88 -0
  95. package/skills/workflow/brainstorming/scripts/server.cjs +354 -0
  96. package/skills/workflow/brainstorming/scripts/start-server.sh +148 -0
  97. package/skills/workflow/brainstorming/scripts/stop-server.sh +56 -0
  98. package/skills/workflow/brainstorming/spec-document-reviewer-prompt.md +49 -0
  99. package/skills/workflow/brainstorming/visual-companion.md +287 -0
  100. package/skills/workflow/debugging-game-feel/SKILL.md +174 -0
  101. package/skills/workflow/diagnosing-perf-regressions/SKILL.md +190 -0
  102. package/skills/workflow/dispatching-parallel-agents/SKILL.md +182 -0
  103. package/skills/workflow/gameskill/SKILL.md +111 -0
  104. package/skills/workflow/investigating-bugs/CREATION-LOG.md +119 -0
  105. package/skills/workflow/investigating-bugs/SKILL.md +296 -0
  106. package/skills/workflow/investigating-bugs/condition-based-waiting-example.ts +158 -0
  107. package/skills/workflow/investigating-bugs/condition-based-waiting.md +115 -0
  108. package/skills/workflow/investigating-bugs/defense-in-depth.md +122 -0
  109. package/skills/workflow/investigating-bugs/find-polluter.sh +63 -0
  110. package/skills/workflow/investigating-bugs/root-cause-tracing.md +169 -0
  111. package/skills/workflow/investigating-bugs/test-academic.md +14 -0
  112. package/skills/workflow/investigating-bugs/test-pressure-1.md +58 -0
  113. package/skills/workflow/investigating-bugs/test-pressure-2.md +68 -0
  114. package/skills/workflow/investigating-bugs/test-pressure-3.md +69 -0
  115. package/skills/workflow/playtesting-a-feature/SKILL.md +173 -0
  116. package/skills/{_meta → workflow}/skill-create/SKILL.md +32 -22
  117. package/skills/{_meta → workflow}/skill-improve/SKILL.md +9 -10
  118. package/skills/{_meta → workflow}/skill-test/SKILL.md +12 -12
  119. package/skills/{_meta → workflow}/using-summer/SKILL.md +5 -2
  120. package/skills/workflow/verification-before-completion/SKILL.md +139 -0
  121. package/skills/workflow/writing-plans/SKILL.md +152 -0
  122. package/skills/workflow/writing-plans/plan-document-reviewer-prompt.md +49 -0
  123. package/skills/workflow/writing-skills/SKILL.md +655 -0
  124. package/skills/workflow/writing-skills/anthropic-best-practices.md +1150 -0
  125. package/skills/workflow/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
  126. package/skills/workflow/writing-skills/graphviz-conventions.dot +172 -0
  127. package/skills/workflow/writing-skills/persuasion-principles.md +187 -0
  128. package/skills/workflow/writing-skills/render-graphs.js +168 -0
  129. package/skills/workflow/writing-skills/testing-skills-with-subagents.md +384 -0
  130. package/dist/commands/assets.d.ts +0 -2
  131. package/dist/commands/assets.js +0 -189
  132. package/dist/commands/debug.d.ts +0 -2
  133. package/dist/commands/debug.js +0 -127
  134. package/dist/commands/doctor.test.d.ts +0 -1
  135. package/dist/commands/doctor.test.js +0 -29
  136. package/dist/commands/project.d.ts +0 -2
  137. package/dist/commands/project.js +0 -170
  138. package/dist/commands/scene.d.ts +0 -2
  139. package/dist/commands/scene.js +0 -290
  140. package/dist/lib/agent-config.test.d.ts +0 -1
  141. package/dist/lib/agent-config.test.js +0 -80
  142. package/dist/lib/format.test.d.ts +0 -1
  143. package/dist/lib/format.test.js +0 -36
  144. package/dist/lib/plugin-manifests.test.d.ts +0 -1
  145. package/dist/lib/plugin-manifests.test.js +0 -134
  146. package/dist/lib/with-engine.d.ts +0 -14
  147. package/dist/lib/with-engine.js +0 -109
  148. package/skills/_shared/collaborative-protocol.md +0 -50
  149. package/skills/_shared/gd-style.md +0 -121
  150. package/skills/_shared/godot-version.md +0 -32
  151. package/skills/_shared/mcp-tools-reference.md +0 -133
  152. package/skills/_shared/summer-folder.md +0 -44
  153. package/skills/_shared/template-registry.md +0 -40
  154. package/skills/_tests/runner.md +0 -90
  155. package/skills/_tests/specs/3d-lighting.md +0 -19
  156. package/skills/_tests/specs/art-direction.md +0 -115
  157. package/skills/_tests/specs/asset-strategy.md +0 -19
  158. package/skills/_tests/specs/audio-direction.md +0 -123
  159. package/skills/_tests/specs/brainstorm-game.md +0 -99
  160. package/skills/_tests/specs/debug.md +0 -94
  161. package/skills/_tests/specs/design-level.md +0 -113
  162. package/skills/_tests/specs/design-mechanic.md +0 -112
  163. package/skills/_tests/specs/design-npc.md +0 -143
  164. package/skills/_tests/specs/export-and-ship.md +0 -114
  165. package/skills/_tests/specs/fps-controller.md +0 -113
  166. package/skills/_tests/specs/gdscript-patterns.md +0 -19
  167. package/skills/_tests/specs/host-authoritative-state.md +0 -104
  168. package/skills/_tests/specs/make-game.md +0 -19
  169. package/skills/_tests/specs/peer-to-peer-multiplayer.md +0 -99
  170. package/skills/_tests/specs/play.md +0 -88
  171. package/skills/_tests/specs/scene-composition.md +0 -19
  172. package/skills/_tests/specs/setup-multiplayer.md +0 -106
  173. package/skills/_tests/specs/tune-performance.md +0 -104
  174. package/skills/_tests/specs/ui-basics.md +0 -19
  175. package/skills/_tests/specs/vfx.md +0 -116
  176. package/skills/catalog.yaml +0 -991
@@ -11,6 +11,12 @@ const AGENT_LABEL = {
11
11
  codex: "Codex",
12
12
  cursor: "Cursor",
13
13
  windsurf: "Windsurf",
14
+ cline: "Cline",
15
+ "roo-code": "Roo Code",
16
+ gemini: "Gemini CLI",
17
+ "github-copilot": "GitHub Copilot CLI",
18
+ "vscode-copilot": "GitHub Copilot in VS Code",
19
+ opencode: "OpenCode",
14
20
  };
15
21
  export const setupCommand = new Command("setup")
16
22
  .description("Configure Summer Engine for an AI agent and run diagnostics")
@@ -21,6 +27,7 @@ export const setupCommand = new Command("setup")
21
27
  .option("--print", "Print the MCP config snippet instead of writing files")
22
28
  .option("--yes", "Apply practical setup steps without prompting")
23
29
  .option("--json", "Print setup result as JSON")
30
+ .option("--force", "Overwrite existing skill content (passes --force through to skills install)")
24
31
  .action(async (agentArg, opts) => {
25
32
  const agent = resolveAgent(agentArg, opts.agent);
26
33
  const scope = resolveScope(opts.scope);
@@ -33,6 +40,7 @@ export const setupCommand = new Command("setup")
33
40
  const skills = setupRecommendedSkills(agent, {
34
41
  dryRun: Boolean(opts.dryRun || opts.print),
35
42
  yes: Boolean(opts.yes),
43
+ force: Boolean(opts.force),
36
44
  });
37
45
  const doctor = await runDoctor({ quiet: true });
38
46
  if (opts.json) {
@@ -68,7 +76,7 @@ function resolveScope(scopeOpt) {
68
76
  return parsed;
69
77
  }
70
78
  function setupRecommendedSkills(agent, options) {
71
- const invocation = skillInstallInvocation(agent);
79
+ const invocation = skillInstallInvocation(agent, { force: options.force });
72
80
  if (!invocation) {
73
81
  return {
74
82
  status: "skipped",
@@ -103,13 +111,15 @@ function setupRecommendedSkills(agent, options) {
103
111
  stderr: result.stderr.trim(),
104
112
  };
105
113
  }
106
- function skillInstallInvocation(agent) {
114
+ function skillInstallInvocation(agent, opts = { force: false }) {
107
115
  const cliPath = process.argv[1];
108
116
  if (!cliPath)
109
117
  return null;
110
118
  const command = cliPath.endsWith(".js") ? process.execPath : cliPath;
111
119
  const prefix = cliPath.endsWith(".js") ? [cliPath] : [];
112
120
  const baseArgs = ["skills", "install", "--recommended", "--agent", agent];
121
+ if (opts.force)
122
+ baseArgs.push("--force");
113
123
  return {
114
124
  command,
115
125
  args: [...prefix, ...baseArgs],
@@ -1,13 +1,21 @@
1
1
  import { Command } from "commander";
2
- import { existsSync, mkdirSync, readFileSync, cpSync, writeFileSync, } from "fs";
2
+ import { existsSync, mkdirSync, readFileSync, cpSync, rmSync, writeFileSync, readdirSync, copyFileSync, } 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
+ import { createRequire } from "node:module";
6
7
  import { AGENT_CLIENTS, SKILL_REGISTRY, } from "../lib/skills-registry.js";
7
8
  import { tildeify } from "../lib/format.js";
9
+ import { writeSkillMarker } from "../lib/version-check.js";
10
+ const requireFromHere = createRequire(import.meta.url);
11
+ const { version: cliVersion } = requireFromHere("../../package.json");
8
12
  const __dirname = dirname(fileURLToPath(import.meta.url));
9
13
  // Resolve skills dir: from dist/commands/skills.js -> ../../skills
10
14
  const skillsDir = join(__dirname, "..", "..", "skills");
15
+ // Resolve commands dir: same parent. Used by Claude Code installs to also copy
16
+ // slash commands (e.g. /gameskill) to ~/.claude/commands/. Other agents don't
17
+ // have an equivalent today, so the copy is gated to claude-code.
18
+ const commandsDir = join(__dirname, "..", "..", "commands");
11
19
  const SKILL_SCOPES = ["user", "project"];
12
20
  function getBuiltinSkills() {
13
21
  const skills = [];
@@ -102,8 +110,12 @@ function resolveAgent(opts) {
102
110
  function resolveScope(agent, opts) {
103
111
  if (opts.scope)
104
112
  return parseScope(opts.scope);
105
- if (agent === "cursor" || agent === "windsurf")
113
+ if (agent === "cursor" ||
114
+ agent === "windsurf" ||
115
+ agent === "cline" ||
116
+ agent === "roo-code") {
106
117
  return "project";
118
+ }
107
119
  return "user";
108
120
  }
109
121
  function agentLabel(agent) {
@@ -116,6 +128,18 @@ function agentLabel(agent) {
116
128
  return "Cursor";
117
129
  case "windsurf":
118
130
  return "Windsurf";
131
+ case "cline":
132
+ return "Cline";
133
+ case "roo-code":
134
+ return "Roo Code";
135
+ case "gemini":
136
+ return "Gemini CLI";
137
+ case "github-copilot":
138
+ return "GitHub Copilot CLI";
139
+ case "vscode-copilot":
140
+ return "GitHub Copilot in VS Code";
141
+ case "opencode":
142
+ return "OpenCode";
119
143
  case "summer":
120
144
  return "Summer";
121
145
  }
@@ -128,6 +152,15 @@ function resolveInstallLocation(agent, scope) {
128
152
  if (agent === "windsurf") {
129
153
  return { kind: "windsurf-rule-file", path: join(overrideDir, ".windsurfrules") };
130
154
  }
155
+ if (agent === "cline" || agent === "roo-code") {
156
+ return { kind: "cline-rule-dir", path: overrideDir };
157
+ }
158
+ if (agent === "gemini") {
159
+ return { kind: "gemini-skill-dir", path: overrideDir };
160
+ }
161
+ if (agent === "opencode") {
162
+ return { kind: "opencode-skill-dir", path: overrideDir };
163
+ }
131
164
  return { kind: "skill-dir", path: overrideDir };
132
165
  }
133
166
  const root = scope === "user" ? homedir() : process.cwd();
@@ -140,10 +173,63 @@ function resolveInstallLocation(agent, scope) {
140
173
  return { kind: "cursor-rule-dir", path: join(root, ".cursor", "rules") };
141
174
  case "windsurf":
142
175
  return { kind: "windsurf-rule-file", path: join(root, ".windsurfrules") };
176
+ case "cline":
177
+ return {
178
+ kind: "cline-rule-dir",
179
+ path: scope === "user"
180
+ ? clineUserRulesDir()
181
+ : join(process.cwd(), ".clinerules"),
182
+ };
183
+ case "roo-code":
184
+ return {
185
+ kind: "cline-rule-dir",
186
+ path: scope === "user"
187
+ ? rooCodeUserRulesDir()
188
+ : join(process.cwd(), ".clinerules"),
189
+ };
190
+ case "gemini":
191
+ return {
192
+ kind: "gemini-skill-dir",
193
+ path: join(homedir(), ".gemini", "extensions", "summer-engine", "skills"),
194
+ };
195
+ case "github-copilot":
196
+ case "vscode-copilot":
197
+ return {
198
+ kind: "skill-dir",
199
+ path: scope === "user"
200
+ ? join(homedir(), ".copilot", "skills")
201
+ : join(process.cwd(), ".github", "skills"),
202
+ };
203
+ case "opencode":
204
+ return {
205
+ kind: "opencode-skill-dir",
206
+ path: scope === "user"
207
+ ? opencodeUserAgentsDir()
208
+ : join(process.cwd(), ".opencode", "agents", "summer"),
209
+ };
143
210
  case "summer":
144
211
  return { kind: "skill-dir", path: join(root, ".summer", "skills") };
145
212
  }
146
213
  }
214
+ function clineUserRulesDir() {
215
+ // Cline reads global rules from the user's Documents/Cline/Rules folder.
216
+ return join(homedir(), "Documents", "Cline", "Rules");
217
+ }
218
+ function rooCodeUserRulesDir() {
219
+ // Roo Code reads global rules from the user's Documents/Roo/Rules folder.
220
+ return join(homedir(), "Documents", "Roo", "Rules");
221
+ }
222
+ function opencodeUserAgentsDir() {
223
+ // OpenCode's user-scope agent definition directory varies by OS.
224
+ // On Windows, OpenCode reads from %APPDATA%/opencode/agents/summer.
225
+ // On Linux/macOS, it reads from $XDG_CONFIG_HOME or ~/.config/opencode/agents/summer.
226
+ if (platform() === "win32") {
227
+ const appData = process.env.APPDATA ?? join(homedir(), "AppData", "Roaming");
228
+ return join(appData, "opencode", "agents", "summer");
229
+ }
230
+ const xdg = process.env.XDG_CONFIG_HOME ?? join(homedir(), ".config");
231
+ return join(xdg, "opencode", "agents", "summer");
232
+ }
147
233
  function selectSkills(name, opts) {
148
234
  if (opts.all && opts.recommended) {
149
235
  die("Use only one bulk option: --all or --recommended.");
@@ -178,26 +264,37 @@ function printAvailableSkillNames() {
178
264
  console.log(` ${skill.name}`);
179
265
  }
180
266
  }
181
- function installSkill(skill, agent, location) {
267
+ function installSkill(skill, agent, location, options) {
182
268
  if (!skill.clients.includes(agent)) {
183
269
  die(`${skill.name} does not support ${agentLabel(agent)}.`);
184
270
  }
185
271
  switch (location.kind) {
186
272
  case "skill-dir":
187
- return copySkillDirectory(skill, location.path);
273
+ return copySkillDirectory(skill, location.path, options);
188
274
  case "cursor-rule-dir":
189
275
  return writeCursorRule(skill, location.path);
190
276
  case "windsurf-rule-file":
191
277
  return upsertWindsurfRule(skill, location.path);
278
+ case "cline-rule-dir":
279
+ return writeClineRule(skill, location.path);
280
+ case "gemini-skill-dir":
281
+ return writeGeminiSkill(skill, location.path);
282
+ case "opencode-skill-dir":
283
+ return writeOpencodeSkill(skill, location.path);
192
284
  }
193
285
  }
194
- function copySkillDirectory(skill, targetDir) {
286
+ function copySkillDirectory(skill, targetDir, options) {
195
287
  const src = getSkillPath(skill.name);
196
288
  if (!src)
197
289
  die(`Skill files missing: ${skill.name}`);
198
290
  mkdirSync(targetDir, { recursive: true });
199
291
  const dest = join(targetDir, skill.name);
200
- cpSync(src, dest, { recursive: true });
292
+ if (options.force && existsSync(dest)) {
293
+ // Wipe stale skill content so re-installs overwrite cleanly even if files
294
+ // were renamed or removed upstream.
295
+ rmSync(dest, { recursive: true, force: true });
296
+ }
297
+ cpSync(src, dest, { recursive: true, force: true });
201
298
  return { action: "Installed", path: dest };
202
299
  }
203
300
  function writeCursorRule(skill, rulesDir) {
@@ -219,6 +316,35 @@ function upsertWindsurfRule(skill, rulePath) {
219
316
  writeFileSync(rulePath, next, "utf-8");
220
317
  return { action: "Generated", path: rulePath };
221
318
  }
319
+ function writeClineRule(skill, rulesDir) {
320
+ // Cline + Roo Code read project rules from .clinerules/ and global rules
321
+ // from Documents/Cline (or Roo)/Rules. Both expect plain markdown files.
322
+ // SKILL.md isn't recognized as a special filename, so we name files <skill>.md.
323
+ mkdirSync(rulesDir, { recursive: true });
324
+ const rulePath = join(rulesDir, `summer-${skill.name}.md`);
325
+ writeFileSync(rulePath, renderRuleBody(skill) + "\n", "utf-8");
326
+ return { action: "Generated", path: rulePath };
327
+ }
328
+ function writeGeminiSkill(skill, skillsDir) {
329
+ // Gemini extensions support a contextFileName, but skill discovery for
330
+ // arbitrary markdown is not standardized. We drop each SKILL.md alongside
331
+ // the extension so the agent can reference them by path; the install
332
+ // summary surfaces this so the user knows where to point Gemini.
333
+ mkdirSync(skillsDir, { recursive: true });
334
+ const rulePath = join(skillsDir, `${skill.name}.md`);
335
+ writeFileSync(rulePath, renderRuleBody(skill) + "\n", "utf-8");
336
+ return { action: "Generated", path: rulePath };
337
+ }
338
+ function writeOpencodeSkill(skill, skillsDir) {
339
+ // OpenCode supports agent markdown definitions; the exact discovery
340
+ // convention for ad-hoc skills isn't fully documented. We write each skill
341
+ // as a markdown file under agents/summer/ so OpenCode can reference them
342
+ // directly. The install summary shows the path.
343
+ mkdirSync(skillsDir, { recursive: true });
344
+ const rulePath = join(skillsDir, `${skill.name}.md`);
345
+ writeFileSync(rulePath, renderRuleBody(skill) + "\n", "utf-8");
346
+ return { action: "Generated", path: rulePath };
347
+ }
222
348
  function renderCursorRule(skill) {
223
349
  const description = `Summer skill ${skill.name}: ${skill.description}`;
224
350
  return `---\ndescription: ${JSON.stringify(description)}\nglobs: []\nalwaysApply: false\n---\n\n${renderRuleBody(skill)}\n`;
@@ -251,6 +377,18 @@ function printInstallSummary(count, agent, scope, location) {
251
377
  else if (location.kind === "cursor-rule-dir") {
252
378
  console.log(`Cursor rules are in ${tildeified}/summer-<skill>.mdc`);
253
379
  }
380
+ else if (location.kind === "cline-rule-dir") {
381
+ console.log(`${label} rules are in ${tildeified}/summer-<skill>.md`);
382
+ console.log("Restart VS Code to pick up new rules.");
383
+ }
384
+ else if (location.kind === "gemini-skill-dir") {
385
+ console.log(`Skill files are in ${tildeified}/<skill>.md`);
386
+ console.log("Reference them from Gemini by path, or run `gemini extensions enable summer-engine` to load the bundled context.");
387
+ }
388
+ else if (location.kind === "opencode-skill-dir") {
389
+ console.log(`Skill files are in ${tildeified}/<skill>.md`);
390
+ console.log("Restart OpenCode so it picks up the new agent definitions.");
391
+ }
254
392
  else {
255
393
  console.log(`Windsurf rules are in ${tildeified}`);
256
394
  }
@@ -287,6 +425,7 @@ skillsCommand
287
425
  .option("--scope <scope>", "Install scope: user or project")
288
426
  .option("--as-claude-skill", "Legacy alias for --agent claude-code")
289
427
  .option("--as-cursor-skill", "Legacy alias for --agent cursor")
428
+ .option("--force", "Overwrite existing skill files (wipe stale skill dirs before copying)")
290
429
  .action((name, opts) => {
291
430
  const agent = resolveAgent(opts);
292
431
  const scope = resolveScope(agent, opts);
@@ -297,11 +436,69 @@ skillsCommand
297
436
  return;
298
437
  }
299
438
  for (const skill of skills) {
300
- const result = installSkill(skill, agent, location);
439
+ const result = installSkill(skill, agent, location, {
440
+ force: Boolean(opts.force),
441
+ });
301
442
  console.log(` ${result.action} ${skill.name} -> ${result.path}`);
302
443
  }
444
+ // Claude Code: also install slash commands (`tools/summer-cli/commands/*.md`)
445
+ // into `~/.claude/commands/`. Other agents don't have an equivalent today.
446
+ if (agent === "claude-code") {
447
+ const commandResults = installClaudeCommands(scope, Boolean(opts.force));
448
+ for (const r of commandResults) {
449
+ console.log(` ${r.action} command ${r.name} -> ${r.path}`);
450
+ }
451
+ }
452
+ writeMarkerForLocation(location);
303
453
  printInstallSummary(skills.length, agent, scope, location);
304
454
  });
455
+ /**
456
+ * Copy every `.md` file in `tools/summer-cli/commands/` to the user's
457
+ * `~/.claude/commands/` directory so the slash commands (e.g. `/gameskill`)
458
+ * are available on every machine that runs `summer skills install`.
459
+ *
460
+ * Project-scope installs go to `<cwd>/.claude/commands/`. Returns one result
461
+ * per command file copied. Silent no-op if no commands directory exists in
462
+ * the package (older summer-cli releases didn't ship one).
463
+ */
464
+ function installClaudeCommands(scope, force) {
465
+ if (!existsSync(commandsDir))
466
+ return [];
467
+ const root = scope === "user" ? homedir() : process.cwd();
468
+ const targetDir = join(root, ".claude", "commands");
469
+ mkdirSync(targetDir, { recursive: true });
470
+ const results = [];
471
+ for (const entry of readdirSync(commandsDir)) {
472
+ if (!entry.endsWith(".md"))
473
+ continue;
474
+ const src = join(commandsDir, entry);
475
+ const dest = join(targetDir, entry);
476
+ if (existsSync(dest) && !force) {
477
+ results.push({ action: "Kept", name: entry, path: dest });
478
+ continue;
479
+ }
480
+ copyFileSync(src, dest);
481
+ results.push({ action: "Installed", name: entry, path: dest });
482
+ }
483
+ return results;
484
+ }
485
+ /**
486
+ * Drop a `.summer-version` marker into the install dir so doctor's
487
+ * `skills-version-stale` check can detect drift later. Windsurf writes a
488
+ * single rules file with no surrounding dir, so we skip it there.
489
+ */
490
+ function writeMarkerForLocation(location) {
491
+ if (location.kind === "windsurf-rule-file")
492
+ return;
493
+ try {
494
+ mkdirSync(location.path, { recursive: true });
495
+ writeSkillMarker(location.path, cliVersion);
496
+ }
497
+ catch {
498
+ // Marker is purely informational. If the FS rejects it (e.g. permission
499
+ // surprises on locked-down corp machines) we don't want to fail the install.
500
+ }
501
+ }
305
502
  skillsCommand
306
503
  .command("info <name>")
307
504
  .description("Show skill description and preview")
@@ -1,6 +1,8 @@
1
1
  import { Command } from "commander";
2
2
  import { getAuthToken, getUserInfo } from "../lib/auth.js";
3
3
  import { getApiToken, getApiPort, checkEngineHealth } from "../lib/engine.js";
4
+ import { getProjectMemorySummary } from "../lib/project-memory.js";
5
+ import { formatStatusMemoryLine } from "./memory.js";
4
6
  export const statusCommand = new Command("status")
5
7
  .description("Check Summer Engine status, connection, and auth state")
6
8
  .action(async () => {
@@ -36,6 +38,7 @@ export const statusCommand = new Command("status")
36
38
  }
37
39
  if (health.project_path) {
38
40
  console.log(` Path: ${health.project_path}`);
41
+ console.log(` ${formatStatusMemoryLine(getProjectMemorySummary(health.project_path))}`);
39
42
  }
40
43
  if (health.scene) {
41
44
  console.log(` Scene: ${health.scene}`);
@@ -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", "github-copilot", "vscode-copilot", "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" | "json-copilot" | "json-vscode";
26
26
  snippet: string;
27
27
  changed: boolean;
28
28
  wrote: boolean;