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.
- package/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +20 -5
- package/.codex-plugin/plugin.json +15 -5
- package/.cursor-plugin/plugin.json +15 -5
- package/.factory-plugin/plugin.json +2 -2
- package/.opencode/INSTALL.md +1 -1
- package/CHANGELOG.md +27 -6
- package/CLAUDE.md +2 -2
- package/GEMINI.md +2 -3
- package/README.md +82 -58
- package/_persona/summer/SKILL.md +5 -6
- package/commands/gameskill.md +103 -0
- package/dist/bin/summer.js +12 -4
- package/dist/commands/create.js +2 -0
- package/dist/commands/doctor.js +71 -1
- package/dist/commands/install.d.ts +17 -0
- package/dist/commands/install.js +63 -4
- package/dist/commands/memory.d.ts +14 -0
- package/dist/commands/memory.js +196 -0
- package/dist/commands/setup.js +12 -2
- package/dist/commands/skills.js +205 -8
- package/dist/commands/status.js +3 -0
- package/dist/lib/agent-config.d.ts +2 -2
- package/dist/lib/agent-config.js +298 -5
- package/dist/lib/api-client.d.ts +13 -0
- package/dist/lib/api-client.js +63 -26
- package/dist/lib/async-op-lifecycle.d.ts +60 -0
- package/dist/lib/async-op-lifecycle.js +83 -0
- package/dist/lib/project-memory.d.ts +33 -0
- package/dist/lib/project-memory.js +220 -0
- package/dist/lib/skills-registry.d.ts +134 -61
- package/dist/lib/skills-registry.js +106 -4
- package/dist/lib/version-check.d.ts +106 -0
- package/dist/lib/version-check.js +338 -0
- package/dist/mcp/server.d.ts +2 -0
- package/dist/mcp/server.js +81 -0
- package/dist/mcp/tools/debug-tools.js +32 -2
- package/dist/mcp/tools/project-tools.js +18 -6
- package/dist/mcp/tools/with-engine.d.ts +14 -0
- package/dist/mcp/tools/with-engine.js +52 -7
- package/gemini-extension.json +2 -2
- package/hooks/pre-commit-doctor.sh +0 -0
- package/hooks/run-hook.cmd +0 -0
- package/hooks/session-start.sh +0 -0
- package/package.json +6 -4
- package/skills/2d-assets/character-portrait/SKILL.md +1 -1
- package/skills/2d-assets/concept-art/SKILL.md +1 -1
- package/skills/2d-assets/create-asset-sheet/SKILL.md +163 -0
- package/skills/2d-assets/instantiate-asset-pack/SKILL.md +245 -0
- package/skills/2d-assets/pixel-art/SKILL.md +1 -1
- package/skills/2d-assets/skybox-panorama/SKILL.md +1 -1
- package/skills/2d-assets/sprite-sheet/SKILL.md +1 -1
- package/skills/2d-assets/tileable-texture/SKILL.md +1 -1
- package/skills/2d-assets/ui-graphics/SKILL.md +1 -1
- package/skills/2d-assets/use-widget-asset/SKILL.md +217 -0
- package/skills/3d-assets/character-model/SKILL.md +1 -1
- package/skills/3d-assets/organic-model/SKILL.md +1 -1
- package/skills/3d-assets/prop-model/SKILL.md +1 -1
- package/skills/3d-assets/vehicle-model/SKILL.md +1 -1
- package/skills/README.md +37 -30
- package/skills/ai-and-npcs/design-npc/SKILL.md +6 -6
- package/skills/animation/animation-tree/SKILL.md +2 -2
- package/skills/animation/facial-and-lipsync/SKILL.md +1 -1
- package/skills/animation/generate-motion/SKILL.md +1 -1
- package/skills/animation/procedural-animation/SKILL.md +2 -2
- package/skills/audio/adaptive-music/SKILL.md +1 -1
- package/skills/audio/audio-direction/SKILL.md +5 -5
- package/skills/audio/sound-effect/SKILL.md +2 -2
- package/skills/audio/voice-line/SKILL.md +25 -3
- package/skills/character-controllers/fps-controller/SKILL.md +5 -5
- package/skills/debugging/debug/SKILL.md +39 -1
- package/skills/deployment/export-and-ship/SKILL.md +4 -4
- package/skills/gameplay-mechanics/auto-fire-targeting/SKILL.md +170 -0
- package/skills/gameplay-mechanics/design-mechanic/SKILL.md +8 -8
- package/skills/level-design/design-level/SKILL.md +5 -5
- package/skills/level-design/scene-to-level/SKILL.md +125 -0
- package/skills/multiplayer-and-networking/host-authoritative-state/SKILL.md +4 -4
- package/skills/multiplayer-and-networking/peer-to-peer-multiplayer/SKILL.md +4 -4
- package/skills/multiplayer-and-networking/setup-multiplayer/SKILL.md +7 -7
- package/skills/performance/tune-performance/SKILL.md +5 -5
- package/skills/rendering-and-lighting/3d-lighting/SKILL.md +1 -1
- package/skills/rendering-and-lighting/art-direction/SKILL.md +5 -5
- package/skills/scene-and-project/brainstorm-game/SKILL.md +4 -4
- package/skills/scene-and-project/play/SKILL.md +1 -1
- package/skills/scene-and-project/scene-composition/SKILL.md +30 -1
- package/skills/scripting-patterns/gdscript-patterns/SKILL.md +53 -0
- package/skills/ui-and-ux/ui-basics/SKILL.md +1 -1
- package/skills/video/animated-loop/SKILL.md +1 -1
- package/skills/video/cinematic-cutscene/SKILL.md +1 -1
- package/skills/video/trailer-shot/SKILL.md +1 -1
- package/skills/visual-effects/game-feel/SKILL.md +6 -6
- package/skills/workflow/brainstorming/SKILL.md +164 -0
- package/skills/workflow/brainstorming/scripts/frame-template.html +214 -0
- package/skills/workflow/brainstorming/scripts/helper.js +88 -0
- package/skills/workflow/brainstorming/scripts/server.cjs +354 -0
- package/skills/workflow/brainstorming/scripts/start-server.sh +148 -0
- package/skills/workflow/brainstorming/scripts/stop-server.sh +56 -0
- package/skills/workflow/brainstorming/spec-document-reviewer-prompt.md +49 -0
- package/skills/workflow/brainstorming/visual-companion.md +287 -0
- package/skills/workflow/debugging-game-feel/SKILL.md +174 -0
- package/skills/workflow/diagnosing-perf-regressions/SKILL.md +190 -0
- package/skills/workflow/dispatching-parallel-agents/SKILL.md +182 -0
- package/skills/workflow/gameskill/SKILL.md +111 -0
- package/skills/workflow/investigating-bugs/CREATION-LOG.md +119 -0
- package/skills/workflow/investigating-bugs/SKILL.md +296 -0
- package/skills/workflow/investigating-bugs/condition-based-waiting-example.ts +158 -0
- package/skills/workflow/investigating-bugs/condition-based-waiting.md +115 -0
- package/skills/workflow/investigating-bugs/defense-in-depth.md +122 -0
- package/skills/workflow/investigating-bugs/find-polluter.sh +63 -0
- package/skills/workflow/investigating-bugs/root-cause-tracing.md +169 -0
- package/skills/workflow/investigating-bugs/test-academic.md +14 -0
- package/skills/workflow/investigating-bugs/test-pressure-1.md +58 -0
- package/skills/workflow/investigating-bugs/test-pressure-2.md +68 -0
- package/skills/workflow/investigating-bugs/test-pressure-3.md +69 -0
- package/skills/workflow/playtesting-a-feature/SKILL.md +173 -0
- package/skills/{_meta → workflow}/skill-create/SKILL.md +32 -22
- package/skills/{_meta → workflow}/skill-improve/SKILL.md +9 -10
- package/skills/{_meta → workflow}/skill-test/SKILL.md +12 -12
- package/skills/{_meta → workflow}/using-summer/SKILL.md +5 -2
- package/skills/workflow/verification-before-completion/SKILL.md +139 -0
- package/skills/workflow/writing-plans/SKILL.md +152 -0
- package/skills/workflow/writing-plans/plan-document-reviewer-prompt.md +49 -0
- package/skills/workflow/writing-skills/SKILL.md +655 -0
- package/skills/workflow/writing-skills/anthropic-best-practices.md +1150 -0
- package/skills/workflow/writing-skills/examples/CLAUDE_MD_TESTING.md +189 -0
- package/skills/workflow/writing-skills/graphviz-conventions.dot +172 -0
- package/skills/workflow/writing-skills/persuasion-principles.md +187 -0
- package/skills/workflow/writing-skills/render-graphs.js +168 -0
- package/skills/workflow/writing-skills/testing-skills-with-subagents.md +384 -0
- package/dist/commands/assets.d.ts +0 -2
- package/dist/commands/assets.js +0 -189
- package/dist/commands/debug.d.ts +0 -2
- package/dist/commands/debug.js +0 -127
- package/dist/commands/doctor.test.d.ts +0 -1
- package/dist/commands/doctor.test.js +0 -29
- package/dist/commands/project.d.ts +0 -2
- package/dist/commands/project.js +0 -170
- package/dist/commands/scene.d.ts +0 -2
- package/dist/commands/scene.js +0 -290
- package/dist/lib/agent-config.test.d.ts +0 -1
- package/dist/lib/agent-config.test.js +0 -80
- package/dist/lib/format.test.d.ts +0 -1
- package/dist/lib/format.test.js +0 -36
- package/dist/lib/plugin-manifests.test.d.ts +0 -1
- package/dist/lib/plugin-manifests.test.js +0 -134
- package/dist/lib/with-engine.d.ts +0 -14
- package/dist/lib/with-engine.js +0 -109
- package/skills/_shared/collaborative-protocol.md +0 -50
- package/skills/_shared/gd-style.md +0 -121
- package/skills/_shared/godot-version.md +0 -32
- package/skills/_shared/mcp-tools-reference.md +0 -133
- package/skills/_shared/summer-folder.md +0 -44
- package/skills/_shared/template-registry.md +0 -40
- package/skills/_tests/runner.md +0 -90
- package/skills/_tests/specs/3d-lighting.md +0 -19
- package/skills/_tests/specs/art-direction.md +0 -115
- package/skills/_tests/specs/asset-strategy.md +0 -19
- package/skills/_tests/specs/audio-direction.md +0 -123
- package/skills/_tests/specs/brainstorm-game.md +0 -99
- package/skills/_tests/specs/debug.md +0 -94
- package/skills/_tests/specs/design-level.md +0 -113
- package/skills/_tests/specs/design-mechanic.md +0 -112
- package/skills/_tests/specs/design-npc.md +0 -143
- package/skills/_tests/specs/export-and-ship.md +0 -114
- package/skills/_tests/specs/fps-controller.md +0 -113
- package/skills/_tests/specs/gdscript-patterns.md +0 -19
- package/skills/_tests/specs/host-authoritative-state.md +0 -104
- package/skills/_tests/specs/make-game.md +0 -19
- package/skills/_tests/specs/peer-to-peer-multiplayer.md +0 -99
- package/skills/_tests/specs/play.md +0 -88
- package/skills/_tests/specs/scene-composition.md +0 -19
- package/skills/_tests/specs/setup-multiplayer.md +0 -106
- package/skills/_tests/specs/tune-performance.md +0 -104
- package/skills/_tests/specs/ui-basics.md +0 -19
- package/skills/_tests/specs/vfx.md +0 -116
- package/skills/catalog.yaml +0 -991
package/dist/commands/setup.js
CHANGED
|
@@ -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],
|
package/dist/commands/skills.js
CHANGED
|
@@ -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" ||
|
|
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
|
-
|
|
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")
|
package/dist/commands/status.js
CHANGED
|
@@ -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;
|