@3lineas/grooveskills 1.0.0 → 1.0.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.
- package/README.md +1 -0
- package/dist/{chunk-75476IDS.js → chunk-TYA2EELM.js} +135 -59
- package/dist/chunk-TYA2EELM.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/main.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-75476IDS.js.map +0 -1
package/README.md
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
- **Cursor IDE**: `.cursor/rules/<skill-name>.mdc` (auto-adapted to Cursor rules format)
|
|
16
16
|
- **Gemini Code Assist**: `.gemini/skills/<skill-name>/`
|
|
17
17
|
- **✨ Interactive & Friendly CLI**: Clean terminal experience built with `@clack/prompts` and courteous, persuasive feedback.
|
|
18
|
+
- **🔗 Centralized Global Store & Symlinks**: Skills are synced globally to `~/.grooveskills/` and linked into local projects via symlinks. Updates to global skills instantly reflect across all your projects with zero file duplication.
|
|
18
19
|
- **🛡️ Battle-tested Architectural Standards**:
|
|
19
20
|
- **Universal Best Practices**: Multi-language clean code (TypeScript, PHP, Dart, Rust, etc.), early returns, zero barrel files, strict typing, <200 lines per file.
|
|
20
21
|
- **Hono API Architecture**: Independent routes by domain, isolated Actions layer, database queries exclusively inside Actions, strict Valibot validation, and Cloudflare/Hono RPC.
|
|
@@ -145,7 +145,7 @@ async function promptConfirmOverwrite() {
|
|
|
145
145
|
}
|
|
146
146
|
|
|
147
147
|
// src/domains/installer/verify-skill-exists.ts
|
|
148
|
-
import {
|
|
148
|
+
import { lstatSync } from "fs";
|
|
149
149
|
import { join as join2 } from "path";
|
|
150
150
|
var AGENT_DESTINATION_MAP = {
|
|
151
151
|
antigravity: (dir) => join2(".agents", "skills", dir),
|
|
@@ -157,118 +157,193 @@ function verifySkillExists(targetPath, skillDirectoryName, agents) {
|
|
|
157
157
|
for (const agent of agents) {
|
|
158
158
|
const relativePathResolver = AGENT_DESTINATION_MAP[agent];
|
|
159
159
|
const destination = join2(targetPath, relativePathResolver(skillDirectoryName));
|
|
160
|
-
|
|
160
|
+
try {
|
|
161
|
+
lstatSync(destination);
|
|
161
162
|
return true;
|
|
163
|
+
} catch {
|
|
162
164
|
}
|
|
163
165
|
}
|
|
164
166
|
return false;
|
|
165
167
|
}
|
|
166
168
|
|
|
167
169
|
// src/domains/installer/install-orchestrator.ts
|
|
168
|
-
import { join as
|
|
170
|
+
import { join as join10 } from "path";
|
|
169
171
|
|
|
170
172
|
// src/domains/adapters/antigravity.adapter.ts
|
|
171
|
-
import {
|
|
173
|
+
import { mkdirSync, existsSync as existsSync2 } from "fs";
|
|
174
|
+
import { join as join4 } from "path";
|
|
175
|
+
|
|
176
|
+
// src/domains/global-store/global-paths.ts
|
|
177
|
+
import { homedir } from "os";
|
|
172
178
|
import { join as join3 } from "path";
|
|
179
|
+
function getGlobalStoreDir() {
|
|
180
|
+
return join3(homedir(), ".grooveskills");
|
|
181
|
+
}
|
|
182
|
+
function getGlobalSkillsDir() {
|
|
183
|
+
return join3(getGlobalStoreDir(), "skills");
|
|
184
|
+
}
|
|
185
|
+
function getGlobalCursorRulesDir() {
|
|
186
|
+
return join3(getGlobalStoreDir(), "cursor-rules");
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// src/domains/adapters/link-helper.ts
|
|
190
|
+
import { lstatSync as lstatSync2, unlinkSync, rmSync, symlinkSync } from "fs";
|
|
191
|
+
function removeExistingLinkPath(path) {
|
|
192
|
+
try {
|
|
193
|
+
const lstat = lstatSync2(path);
|
|
194
|
+
if (lstat.isDirectory() && !lstat.isSymbolicLink()) {
|
|
195
|
+
rmSync(path, { recursive: true, force: true });
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
unlinkSync(path);
|
|
199
|
+
} catch {
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
function createOrReplaceSymlink(target, linkPath, type) {
|
|
203
|
+
removeExistingLinkPath(linkPath);
|
|
204
|
+
symlinkSync(target, linkPath, type);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// src/domains/adapters/antigravity.adapter.ts
|
|
173
208
|
var AntigravityAdapter = class {
|
|
174
209
|
id = "antigravity";
|
|
175
210
|
name = "Antigravity";
|
|
176
211
|
targetRelativeDir = ".agents/skills";
|
|
177
|
-
async installSkill(targetPath, skill,
|
|
178
|
-
const
|
|
179
|
-
if (!
|
|
180
|
-
mkdirSync(
|
|
212
|
+
async installSkill(targetPath, skill, _skillSourceDir) {
|
|
213
|
+
const parentDir = join4(targetPath, this.targetRelativeDir);
|
|
214
|
+
if (!existsSync2(parentDir)) {
|
|
215
|
+
mkdirSync(parentDir, { recursive: true });
|
|
181
216
|
}
|
|
182
|
-
|
|
217
|
+
const destination = join4(parentDir, skill.directoryName);
|
|
218
|
+
const globalSkillDir = join4(getGlobalSkillsDir(), skill.directoryName);
|
|
219
|
+
createOrReplaceSymlink(globalSkillDir, destination, "dir");
|
|
183
220
|
return [destination];
|
|
184
221
|
}
|
|
185
222
|
};
|
|
186
223
|
|
|
187
224
|
// src/domains/adapters/claude.adapter.ts
|
|
188
|
-
import {
|
|
189
|
-
import { join as
|
|
225
|
+
import { mkdirSync as mkdirSync2, existsSync as existsSync3 } from "fs";
|
|
226
|
+
import { join as join5 } from "path";
|
|
190
227
|
var ClaudeAdapter = class {
|
|
191
228
|
id = "claude";
|
|
192
229
|
name = "Claude Code";
|
|
193
230
|
targetRelativeDir = ".claude/skills";
|
|
194
|
-
async installSkill(targetPath, skill,
|
|
195
|
-
const
|
|
196
|
-
if (!
|
|
197
|
-
mkdirSync2(
|
|
231
|
+
async installSkill(targetPath, skill, _skillSourceDir) {
|
|
232
|
+
const parentDir = join5(targetPath, this.targetRelativeDir);
|
|
233
|
+
if (!existsSync3(parentDir)) {
|
|
234
|
+
mkdirSync2(parentDir, { recursive: true });
|
|
198
235
|
}
|
|
199
|
-
|
|
236
|
+
const destination = join5(parentDir, skill.directoryName);
|
|
237
|
+
const globalSkillDir = join5(getGlobalSkillsDir(), skill.directoryName);
|
|
238
|
+
createOrReplaceSymlink(globalSkillDir, destination, "dir");
|
|
200
239
|
return [destination];
|
|
201
240
|
}
|
|
202
241
|
};
|
|
203
242
|
|
|
204
243
|
// src/domains/adapters/cursor.adapter.ts
|
|
205
|
-
import {
|
|
206
|
-
import { join as
|
|
244
|
+
import { mkdirSync as mkdirSync3, existsSync as existsSync4 } from "fs";
|
|
245
|
+
import { join as join6 } from "path";
|
|
207
246
|
var CursorAdapter = class {
|
|
208
247
|
id = "cursor";
|
|
209
248
|
name = "Cursor";
|
|
210
249
|
targetRelativeDir = ".cursor/rules";
|
|
211
|
-
async installSkill(targetPath, skill,
|
|
212
|
-
const rulesDir =
|
|
213
|
-
if (!
|
|
250
|
+
async installSkill(targetPath, skill, _skillSourceDir) {
|
|
251
|
+
const rulesDir = join6(targetPath, this.targetRelativeDir);
|
|
252
|
+
if (!existsSync4(rulesDir)) {
|
|
214
253
|
mkdirSync3(rulesDir, { recursive: true });
|
|
215
254
|
}
|
|
216
|
-
const
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
const mdcHeader = `---
|
|
222
|
-
description: ${skill.description}
|
|
223
|
-
globs: ["**/*"]
|
|
224
|
-
alwaysApply: false
|
|
225
|
-
---
|
|
226
|
-
|
|
227
|
-
`;
|
|
228
|
-
const cleanedBody = content.replace(/^---[\s\S]*?---\s*/, "");
|
|
229
|
-
const targetFile = join5(rulesDir, `${skill.id}.mdc`);
|
|
230
|
-
writeFileSync(targetFile, `${mdcHeader}${cleanedBody}`, "utf-8");
|
|
231
|
-
return [targetFile];
|
|
255
|
+
const filename = `${skill.id}.mdc`;
|
|
256
|
+
const destination = join6(rulesDir, filename);
|
|
257
|
+
const globalRuleFile = join6(getGlobalCursorRulesDir(), filename);
|
|
258
|
+
createOrReplaceSymlink(globalRuleFile, destination, "file");
|
|
259
|
+
return [destination];
|
|
232
260
|
}
|
|
233
261
|
};
|
|
234
262
|
|
|
235
263
|
// src/domains/adapters/gemini.adapter.ts
|
|
236
|
-
import {
|
|
237
|
-
import { join as
|
|
264
|
+
import { mkdirSync as mkdirSync4, existsSync as existsSync5 } from "fs";
|
|
265
|
+
import { join as join7 } from "path";
|
|
238
266
|
var GeminiAdapter = class {
|
|
239
267
|
id = "gemini";
|
|
240
268
|
name = "Gemini Code Assist";
|
|
241
269
|
targetRelativeDir = ".gemini/skills";
|
|
242
|
-
async installSkill(targetPath, skill,
|
|
243
|
-
const
|
|
244
|
-
if (!
|
|
245
|
-
mkdirSync4(
|
|
270
|
+
async installSkill(targetPath, skill, _skillSourceDir) {
|
|
271
|
+
const parentDir = join7(targetPath, this.targetRelativeDir);
|
|
272
|
+
if (!existsSync5(parentDir)) {
|
|
273
|
+
mkdirSync4(parentDir, { recursive: true });
|
|
246
274
|
}
|
|
247
|
-
|
|
275
|
+
const destination = join7(parentDir, skill.directoryName);
|
|
276
|
+
const globalSkillDir = join7(getGlobalSkillsDir(), skill.directoryName);
|
|
277
|
+
createOrReplaceSymlink(globalSkillDir, destination, "dir");
|
|
248
278
|
return [destination];
|
|
249
279
|
}
|
|
250
280
|
};
|
|
251
281
|
|
|
282
|
+
// src/domains/global-store/sync-global-store.ts
|
|
283
|
+
import { cpSync, mkdirSync as mkdirSync5, existsSync as existsSync7, writeFileSync, readFileSync as readFileSync2 } from "fs";
|
|
284
|
+
import { join as join9 } from "path";
|
|
285
|
+
|
|
252
286
|
// src/domains/installer/resolve-skills-source.ts
|
|
253
287
|
import { fileURLToPath } from "url";
|
|
254
|
-
import { dirname, resolve, join as
|
|
255
|
-
import { existsSync as
|
|
288
|
+
import { dirname, resolve, join as join8 } from "path";
|
|
289
|
+
import { existsSync as existsSync6 } from "fs";
|
|
256
290
|
function resolveSkillsSourceRoot() {
|
|
257
291
|
const currentFilePath = fileURLToPath(import.meta.url);
|
|
258
292
|
const currentDir = dirname(currentFilePath);
|
|
259
|
-
const
|
|
260
|
-
if (
|
|
261
|
-
return
|
|
293
|
+
const candidateFromDist = resolve(currentDir, "../skills");
|
|
294
|
+
if (existsSync6(candidateFromDist)) {
|
|
295
|
+
return candidateFromDist;
|
|
296
|
+
}
|
|
297
|
+
const candidateFromSrc = resolve(currentDir, "../../../skills");
|
|
298
|
+
if (existsSync6(candidateFromSrc)) {
|
|
299
|
+
return candidateFromSrc;
|
|
300
|
+
}
|
|
301
|
+
let searchDir = currentDir;
|
|
302
|
+
for (let i = 0; i < 5; i++) {
|
|
303
|
+
const candidate = join8(searchDir, "skills");
|
|
304
|
+
if (existsSync6(candidate)) {
|
|
305
|
+
return candidate;
|
|
306
|
+
}
|
|
307
|
+
const parent = dirname(searchDir);
|
|
308
|
+
if (parent === searchDir) {
|
|
309
|
+
break;
|
|
310
|
+
}
|
|
311
|
+
searchDir = parent;
|
|
312
|
+
}
|
|
313
|
+
throw new Error(
|
|
314
|
+
`GrooveSkills internal error: Unable to locate bundled skills directory from ${currentDir}`
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// src/domains/global-store/sync-global-store.ts
|
|
319
|
+
function syncGlobalStore() {
|
|
320
|
+
const bundledSkillsDir = resolveSkillsSourceRoot();
|
|
321
|
+
const globalSkillsDir = getGlobalSkillsDir();
|
|
322
|
+
const globalCursorRulesDir = getGlobalCursorRulesDir();
|
|
323
|
+
if (!existsSync7(globalSkillsDir)) {
|
|
324
|
+
mkdirSync5(globalSkillsDir, { recursive: true });
|
|
262
325
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
return candidate2;
|
|
326
|
+
if (!existsSync7(globalCursorRulesDir)) {
|
|
327
|
+
mkdirSync5(globalCursorRulesDir, { recursive: true });
|
|
266
328
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
329
|
+
cpSync(bundledSkillsDir, globalSkillsDir, { recursive: true });
|
|
330
|
+
for (const skill of SKILL_CATALOG) {
|
|
331
|
+
const skillMdPath = join9(globalSkillsDir, skill.directoryName, "SKILL.md");
|
|
332
|
+
if (!existsSync7(skillMdPath)) {
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
const content = readFileSync2(skillMdPath, "utf-8");
|
|
336
|
+
const mdcHeader = `---
|
|
337
|
+
description: ${skill.description}
|
|
338
|
+
globs: ["**/*"]
|
|
339
|
+
alwaysApply: false
|
|
340
|
+
---
|
|
341
|
+
|
|
342
|
+
`;
|
|
343
|
+
const cleanedBody = content.replace(/^---[\s\S]*?---\s*/, "");
|
|
344
|
+
const targetMdc = join9(globalCursorRulesDir, `${skill.id}.mdc`);
|
|
345
|
+
writeFileSync(targetMdc, `${mdcHeader}${cleanedBody}`, "utf-8");
|
|
270
346
|
}
|
|
271
|
-
return join7(process.cwd(), "skills");
|
|
272
347
|
}
|
|
273
348
|
|
|
274
349
|
// src/domains/installer/install-orchestrator.ts
|
|
@@ -279,14 +354,15 @@ var ADAPTER_REGISTRY = {
|
|
|
279
354
|
gemini: new GeminiAdapter()
|
|
280
355
|
};
|
|
281
356
|
async function installSkills(options) {
|
|
282
|
-
|
|
357
|
+
syncGlobalStore();
|
|
358
|
+
const globalSkillsDir = getGlobalSkillsDir();
|
|
283
359
|
const createdFiles = [];
|
|
284
360
|
for (const skillId of options.selectedSkillIds) {
|
|
285
361
|
const skill = SKILL_CATALOG.find((item) => item.id === skillId);
|
|
286
362
|
if (!skill) {
|
|
287
363
|
continue;
|
|
288
364
|
}
|
|
289
|
-
const skillSourceDir =
|
|
365
|
+
const skillSourceDir = join10(globalSkillsDir, skill.directoryName);
|
|
290
366
|
for (const agentId of options.selectedAgents) {
|
|
291
367
|
const adapter = ADAPTER_REGISTRY[agentId];
|
|
292
368
|
if (!adapter) {
|
|
@@ -373,4 +449,4 @@ async function runGrooveSkills(options = {}) {
|
|
|
373
449
|
export {
|
|
374
450
|
runGrooveSkills
|
|
375
451
|
};
|
|
376
|
-
//# sourceMappingURL=chunk-
|
|
452
|
+
//# sourceMappingURL=chunk-TYA2EELM.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/domains/detector/detect-agents.ts","../src/domains/detector/detect-dependencies.ts","../src/domains/registry/skill-catalog.ts","../src/domains/detector/project-detector.ts","../src/domains/ui/ui-orchestrator.ts","../src/domains/ui/banners.ts","../src/domains/ui/prompt-skills.ts","../src/domains/ui/prompt-agents.ts","../src/domains/ui/prompt-confirm-overwrite.ts","../src/domains/installer/verify-skill-exists.ts","../src/domains/installer/install-orchestrator.ts","../src/domains/adapters/antigravity.adapter.ts","../src/domains/global-store/global-paths.ts","../src/domains/adapters/link-helper.ts","../src/domains/adapters/claude.adapter.ts","../src/domains/adapters/cursor.adapter.ts","../src/domains/adapters/gemini.adapter.ts","../src/domains/global-store/sync-global-store.ts","../src/domains/installer/resolve-skills-source.ts","../src/main.ts"],"sourcesContent":["import { readdirSync } from \"node:fs\";\nimport type { AgentId } from \"@/types/agent.types\";\n\nexport function detectAgents(targetPath: string): AgentId[] {\n const detected: AgentId[] = [];\n\n try {\n const entries = new Set(readdirSync(targetPath));\n\n if (entries.has(\".agents\")) {\n detected.push(\"antigravity\");\n }\n if (entries.has(\".claude\")) {\n detected.push(\"claude\");\n }\n if (entries.has(\".cursor\")) {\n detected.push(\"cursor\");\n }\n if (entries.has(\".gemini\")) {\n detected.push(\"gemini\");\n }\n } catch {\n // If directory cannot be read, return empty list gracefully\n }\n\n return detected;\n}\n","import { readFileSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport interface PackageJsonDetection {\n dependencies: string[];\n exists: boolean;\n}\n\nexport function detectDependencies(targetPath: string): PackageJsonDetection {\n const packageJsonPath = join(targetPath, \"package.json\");\n\n if (!existsSync(packageJsonPath)) {\n return { dependencies: [], exists: false };\n }\n\n try {\n const raw = readFileSync(packageJsonPath, \"utf-8\");\n const parsed = JSON.parse(raw) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n\n const direct = Object.keys(parsed.dependencies ?? {});\n const dev = Object.keys(parsed.devDependencies ?? {});\n const all = Array.from(new Set([...direct, ...dev]));\n\n return { dependencies: all, exists: true };\n } catch {\n return { dependencies: [], exists: true };\n }\n}\n","import type { SkillMetadata } from \"@/types/skill.types\";\n\nexport const SKILL_CATALOG: SkillMetadata[] = [\n {\n id: \"best-practices\",\n name: \"Universal Best Practices\",\n description: \"Multi-language clean code standards, early returns, no barrel files, strict typing, <200 lines\",\n dependencies: [],\n directoryName: \"best-practices\",\n },\n {\n id: \"hono\",\n name: \"Hono Architecture (Valibot)\",\n description: \"Enterprise Hono API standard with Valibot validation, isolated Actions layer, and RPC bindings\",\n dependencies: [\"hono\", \"@hono/valibot-validator\", \"@hono/standard-validator\"],\n directoryName: \"hono\",\n },\n];\n","import { detectAgents } from \"@/domains/detector/detect-agents\";\nimport { detectDependencies } from \"@/domains/detector/detect-dependencies\";\nimport { SKILL_CATALOG } from \"@/domains/registry/skill-catalog\";\nimport type { ProjectContext } from \"@/types/context.types\";\n\nexport function detectProjectContext(targetPath: string): ProjectContext {\n const detectedAgents = detectAgents(targetPath);\n const { dependencies, exists } = detectDependencies(targetPath);\n\n const suggestedSkillIds: string[] = [\"best-practices\"];\n\n for (const skill of SKILL_CATALOG) {\n if (skill.dependencies.length === 0) {\n continue;\n }\n const hasMatch = skill.dependencies.some((dep) => dependencies.includes(dep));\n if (hasMatch && !suggestedSkillIds.includes(skill.id)) {\n suggestedSkillIds.push(skill.id);\n }\n }\n\n return {\n targetPath,\n detectedDependencies: dependencies,\n suggestedSkillIds,\n detectedAgents,\n packageJsonExists: exists,\n };\n}\n","import * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\nimport { renderBanner } from \"@/domains/ui/banners\";\nimport { promptSkills } from \"@/domains/ui/prompt-skills\";\nimport { promptAgents } from \"@/domains/ui/prompt-agents\";\nimport { promptConfirmOverwrite } from \"@/domains/ui/prompt-confirm-overwrite\";\nimport { verifySkillExists } from \"@/domains/installer/verify-skill-exists\";\nimport { installSkills } from \"@/domains/installer/install-orchestrator\";\nimport { SKILL_CATALOG } from \"@/domains/registry/skill-catalog\";\nimport type { ProjectContext } from \"@/types/context.types\";\nimport type { AgentId } from \"@/types/agent.types\";\n\nexport async function runInteractiveUi(context: ProjectContext): Promise<void> {\n console.log(renderBanner());\n p.intro(pc.magenta(\"Welcome to GrooveSkills! Let's tailor your AI agents with clean architectural standards.\"));\n\n if (context.detectedDependencies.length > 0) {\n p.note(\n `Detected dependencies: ${context.detectedDependencies.map((d) => pc.bold(d)).join(\", \")}\\n` +\n `Active AI folders: ${context.detectedAgents.map((a) => pc.green(a)).join(\", \") || \"None (will be created)\"}`,\n \"Project Environment\"\n );\n }\n\n const selectedSkills = await promptSkills(context.suggestedSkillIds);\n if (p.isCancel(selectedSkills)) {\n p.cancel(\"Installation cancelled. Have a wonderful day!\");\n process.exit(0);\n }\n\n const selectedAgents = await promptAgents(context.detectedAgents);\n if (p.isCancel(selectedAgents)) {\n p.cancel(\"Installation cancelled. Have a wonderful day!\");\n process.exit(0);\n }\n\n let forceOverwrite = true;\n const anyExists = (selectedSkills as string[]).some((skillId) => {\n const meta = SKILL_CATALOG.find((s) => s.id === skillId);\n return meta ? verifySkillExists(context.targetPath, meta.directoryName, selectedAgents as AgentId[]) : false;\n });\n\n if (anyExists) {\n const confirm = await promptConfirmOverwrite();\n if (p.isCancel(confirm) || !confirm) {\n p.cancel(\"Installation stopped to protect existing skills.\");\n process.exit(0);\n }\n forceOverwrite = Boolean(confirm);\n }\n\n const s = p.spinner();\n s.start(\"Installing and adapting skills across your configured AI agents...\");\n\n const result = await installSkills({\n targetPath: context.targetPath,\n selectedSkillIds: selectedSkills as string[],\n selectedAgents: selectedAgents as AgentId[],\n forceOverwrite,\n });\n\n s.stop(pc.green(\"All skills have been successfully installed and configured!\"));\n\n p.note(\n `Configured skills: ${result.installedSkills.map((s) => pc.bold(s)).join(\", \")}\\n` +\n `Target agents: ${result.configuredAgents.map((a) => pc.cyan(a)).join(\", \")}`,\n \"Installation Summary\"\n );\n\n p.outro(pc.green(\"Your AI programming pair is now empowered with your team's architectural habits! 🚀\"));\n}\n","import pc from \"picocolors\";\n\nexport function renderBanner(): string {\n const title = pc.bold(pc.white(\" GROOVE SKILLS \"));\n const badge = pc.bgMagenta(pc.black(title));\n const subtitle = pc.dim(\"Multi-Agent AI Skills & Architectural Standards\");\n\n return `${badge} ${subtitle}\\n`;\n}\n","import * as p from \"@clack/prompts\";\nimport { SKILL_CATALOG } from \"@/domains/registry/skill-catalog\";\n\nexport async function promptSkills(suggestedSkillIds: string[]): Promise<string[] | symbol> {\n const options = SKILL_CATALOG.map((skill) => {\n const isSuggested = suggestedSkillIds.includes(skill.id);\n return {\n value: skill.id,\n label: skill.name,\n hint: isSuggested ? \"Suggested based on your project stack\" : skill.description,\n };\n });\n\n const selected = await p.multiselect({\n message: \"Which skills would you like to install in this project?\",\n options,\n initialValues: suggestedSkillIds,\n required: true,\n });\n\n return selected;\n}\n","import * as p from \"@clack/prompts\";\nimport type { AgentId } from \"@/types/agent.types\";\n\nexport async function promptAgents(detectedAgents: AgentId[]): Promise<AgentId[] | symbol> {\n const options: Array<{ value: AgentId; label: string; hint: string }> = [\n { value: \"antigravity\", label: \"Antigravity\", hint: \".agents/skills (Google Agentic IDE)\" },\n { value: \"claude\", label: \"Claude Code\", hint: \".claude/skills (Anthropic Claude Code)\" },\n { value: \"cursor\", label: \"Cursor\", hint: \".cursor/rules/*.mdc (Cursor IDE Rules)\" },\n { value: \"gemini\", label: \"Gemini Code Assist\", hint: \".gemini/skills (Google Gemini)\" },\n ];\n\n const initialValues: AgentId[] = detectedAgents.length > 0 ? detectedAgents : [\"antigravity\"];\n\n const selected = await p.multiselect({\n message: \"Which AI agents should be configured?\",\n options,\n initialValues,\n required: true,\n });\n\n return selected as AgentId[] | symbol;\n}\n","import * as p from \"@clack/prompts\";\n\nexport async function promptConfirmOverwrite(): Promise<boolean | symbol> {\n return await p.confirm({\n message: \"Some skills already exist in this project. Would you like to overwrite them with the latest version?\",\n initialValue: true,\n });\n}\n","import { lstatSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { AgentId } from \"@/types/agent.types\";\n\nconst AGENT_DESTINATION_MAP: Record<AgentId, (dir: string) => string> = {\n antigravity: (dir) => join(\".agents\", \"skills\", dir),\n claude: (dir) => join(\".claude\", \"skills\", dir),\n cursor: (dir) => join(\".cursor\", \"rules\", `${dir}.mdc`),\n gemini: (dir) => join(\".gemini\", \"skills\", dir),\n};\n\nexport function verifySkillExists(\n targetPath: string,\n skillDirectoryName: string,\n agents: AgentId[]\n): boolean {\n for (const agent of agents) {\n const relativePathResolver = AGENT_DESTINATION_MAP[agent];\n const destination = join(targetPath, relativePathResolver(skillDirectoryName));\n\n try {\n lstatSync(destination);\n return true;\n } catch {\n // Path does not exist\n }\n }\n\n return false;\n}\n","import { join } from \"node:path\";\nimport { AntigravityAdapter } from \"@/domains/adapters/antigravity.adapter\";\nimport { ClaudeAdapter } from \"@/domains/adapters/claude.adapter\";\nimport { CursorAdapter } from \"@/domains/adapters/cursor.adapter\";\nimport { GeminiAdapter } from \"@/domains/adapters/gemini.adapter\";\nimport { syncGlobalStore } from \"@/domains/global-store/sync-global-store\";\nimport { getGlobalSkillsDir } from \"@/domains/global-store/global-paths\";\nimport { SKILL_CATALOG } from \"@/domains/registry/skill-catalog\";\nimport type { AgentAdapter } from \"@/domains/adapters/adapter.interface\";\nimport type { InstallOptions, InstallResult } from \"@/types/installer.types\";\nimport type { AgentId } from \"@/types/agent.types\";\n\nconst ADAPTER_REGISTRY: Record<AgentId, AgentAdapter> = {\n antigravity: new AntigravityAdapter(),\n claude: new ClaudeAdapter(),\n cursor: new CursorAdapter(),\n gemini: new GeminiAdapter(),\n};\n\nexport async function installSkills(options: InstallOptions): Promise<InstallResult> {\n syncGlobalStore();\n\n const globalSkillsDir = getGlobalSkillsDir();\n const createdFiles: string[] = [];\n\n for (const skillId of options.selectedSkillIds) {\n const skill = SKILL_CATALOG.find((item) => item.id === skillId);\n if (!skill) {\n continue;\n }\n\n const skillSourceDir = join(globalSkillsDir, skill.directoryName);\n\n for (const agentId of options.selectedAgents) {\n const adapter = ADAPTER_REGISTRY[agentId];\n if (!adapter) {\n continue;\n }\n\n const files = await adapter.installSkill(options.targetPath, skill, skillSourceDir);\n createdFiles.push(...files);\n }\n }\n\n return {\n installedSkills: options.selectedSkillIds,\n configuredAgents: options.selectedAgents,\n createdFiles,\n };\n}\n","import { mkdirSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { getGlobalSkillsDir } from \"@/domains/global-store/global-paths\";\nimport { createOrReplaceSymlink } from \"@/domains/adapters/link-helper\";\nimport type { AgentAdapter } from \"@/domains/adapters/adapter.interface\";\nimport type { SkillMetadata } from \"@/types/skill.types\";\n\nexport class AntigravityAdapter implements AgentAdapter {\n readonly id = \"antigravity\" as const;\n readonly name = \"Antigravity\";\n readonly targetRelativeDir = \".agents/skills\";\n\n async installSkill(\n targetPath: string,\n skill: SkillMetadata,\n _skillSourceDir: string\n ): Promise<string[]> {\n const parentDir = join(targetPath, this.targetRelativeDir);\n if (!existsSync(parentDir)) {\n mkdirSync(parentDir, { recursive: true });\n }\n\n const destination = join(parentDir, skill.directoryName);\n const globalSkillDir = join(getGlobalSkillsDir(), skill.directoryName);\n\n createOrReplaceSymlink(globalSkillDir, destination, \"dir\");\n\n return [destination];\n }\n}\n","import { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport function getGlobalStoreDir(): string {\n return join(homedir(), \".grooveskills\");\n}\n\nexport function getGlobalSkillsDir(): string {\n return join(getGlobalStoreDir(), \"skills\");\n}\n\nexport function getGlobalCursorRulesDir(): string {\n return join(getGlobalStoreDir(), \"cursor-rules\");\n}\n","import { lstatSync, unlinkSync, rmSync, symlinkSync } from \"node:fs\";\n\nfunction removeExistingLinkPath(path: string): void {\n try {\n const lstat = lstatSync(path);\n\n if (lstat.isDirectory() && !lstat.isSymbolicLink()) {\n rmSync(path, { recursive: true, force: true });\n return;\n }\n\n unlinkSync(path);\n } catch {\n // If path does not exist, exit early\n }\n}\n\nexport function createOrReplaceSymlink(\n target: string,\n linkPath: string,\n type: \"dir\" | \"file\"\n): void {\n removeExistingLinkPath(linkPath);\n symlinkSync(target, linkPath, type);\n}\n\n","import { mkdirSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { getGlobalSkillsDir } from \"@/domains/global-store/global-paths\";\nimport { createOrReplaceSymlink } from \"@/domains/adapters/link-helper\";\nimport type { AgentAdapter } from \"@/domains/adapters/adapter.interface\";\nimport type { SkillMetadata } from \"@/types/skill.types\";\n\nexport class ClaudeAdapter implements AgentAdapter {\n readonly id = \"claude\" as const;\n readonly name = \"Claude Code\";\n readonly targetRelativeDir = \".claude/skills\";\n\n async installSkill(\n targetPath: string,\n skill: SkillMetadata,\n _skillSourceDir: string\n ): Promise<string[]> {\n const parentDir = join(targetPath, this.targetRelativeDir);\n if (!existsSync(parentDir)) {\n mkdirSync(parentDir, { recursive: true });\n }\n\n const destination = join(parentDir, skill.directoryName);\n const globalSkillDir = join(getGlobalSkillsDir(), skill.directoryName);\n\n createOrReplaceSymlink(globalSkillDir, destination, \"dir\");\n\n return [destination];\n }\n}\n","import { mkdirSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { getGlobalCursorRulesDir } from \"@/domains/global-store/global-paths\";\nimport { createOrReplaceSymlink } from \"@/domains/adapters/link-helper\";\nimport type { AgentAdapter } from \"@/domains/adapters/adapter.interface\";\nimport type { SkillMetadata } from \"@/types/skill.types\";\n\nexport class CursorAdapter implements AgentAdapter {\n readonly id = \"cursor\" as const;\n readonly name = \"Cursor\";\n readonly targetRelativeDir = \".cursor/rules\";\n\n async installSkill(\n targetPath: string,\n skill: SkillMetadata,\n _skillSourceDir: string\n ): Promise<string[]> {\n const rulesDir = join(targetPath, this.targetRelativeDir);\n if (!existsSync(rulesDir)) {\n mkdirSync(rulesDir, { recursive: true });\n }\n\n const filename = `${skill.id}.mdc`;\n const destination = join(rulesDir, filename);\n const globalRuleFile = join(getGlobalCursorRulesDir(), filename);\n\n createOrReplaceSymlink(globalRuleFile, destination, \"file\");\n\n return [destination];\n }\n}\n","import { mkdirSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { getGlobalSkillsDir } from \"@/domains/global-store/global-paths\";\nimport { createOrReplaceSymlink } from \"@/domains/adapters/link-helper\";\nimport type { AgentAdapter } from \"@/domains/adapters/adapter.interface\";\nimport type { SkillMetadata } from \"@/types/skill.types\";\n\nexport class GeminiAdapter implements AgentAdapter {\n readonly id = \"gemini\" as const;\n readonly name = \"Gemini Code Assist\";\n readonly targetRelativeDir = \".gemini/skills\";\n\n async installSkill(\n targetPath: string,\n skill: SkillMetadata,\n _skillSourceDir: string\n ): Promise<string[]> {\n const parentDir = join(targetPath, this.targetRelativeDir);\n if (!existsSync(parentDir)) {\n mkdirSync(parentDir, { recursive: true });\n }\n\n const destination = join(parentDir, skill.directoryName);\n const globalSkillDir = join(getGlobalSkillsDir(), skill.directoryName);\n\n createOrReplaceSymlink(globalSkillDir, destination, \"dir\");\n\n return [destination];\n }\n}\n","import { cpSync, mkdirSync, existsSync, writeFileSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { getGlobalSkillsDir, getGlobalCursorRulesDir } from \"@/domains/global-store/global-paths\";\nimport { resolveSkillsSourceRoot } from \"@/domains/installer/resolve-skills-source\";\nimport { SKILL_CATALOG } from \"@/domains/registry/skill-catalog\";\n\nexport function syncGlobalStore(): void {\n const bundledSkillsDir = resolveSkillsSourceRoot();\n const globalSkillsDir = getGlobalSkillsDir();\n const globalCursorRulesDir = getGlobalCursorRulesDir();\n\n if (!existsSync(globalSkillsDir)) {\n mkdirSync(globalSkillsDir, { recursive: true });\n }\n if (!existsSync(globalCursorRulesDir)) {\n mkdirSync(globalCursorRulesDir, { recursive: true });\n }\n\n cpSync(bundledSkillsDir, globalSkillsDir, { recursive: true });\n\n for (const skill of SKILL_CATALOG) {\n const skillMdPath = join(globalSkillsDir, skill.directoryName, \"SKILL.md\");\n if (!existsSync(skillMdPath)) {\n continue;\n }\n\n const content = readFileSync(skillMdPath, \"utf-8\");\n const mdcHeader = `---\ndescription: ${skill.description}\nglobs: [\"**/*\"]\nalwaysApply: false\n---\n\n`;\n const cleanedBody = content.replace(/^---[\\s\\S]*?---\\s*/, \"\");\n const targetMdc = join(globalCursorRulesDir, `${skill.id}.mdc`);\n writeFileSync(targetMdc, `${mdcHeader}${cleanedBody}`, \"utf-8\");\n }\n}\n","import { fileURLToPath } from \"node:url\";\nimport { dirname, resolve, join } from \"node:path\";\nimport { existsSync } from \"node:fs\";\n\nexport function resolveSkillsSourceRoot(): string {\n const currentFilePath = fileURLToPath(import.meta.url);\n const currentDir = dirname(currentFilePath);\n\n // 1. From dist/ in published npm package or local build: dist/../skills\n const candidateFromDist = resolve(currentDir, \"../skills\");\n if (existsSync(candidateFromDist)) {\n return candidateFromDist;\n }\n\n // 2. From src/domains/installer/ during development: ../../../skills\n const candidateFromSrc = resolve(currentDir, \"../../../skills\");\n if (existsSync(candidateFromSrc)) {\n return candidateFromSrc;\n }\n\n // 3. Search upward for the package root containing a skills directory\n let searchDir = currentDir;\n for (let i = 0; i < 5; i++) {\n const candidate = join(searchDir, \"skills\");\n if (existsSync(candidate)) {\n return candidate;\n }\n const parent = dirname(searchDir);\n if (parent === searchDir) {\n break;\n }\n searchDir = parent;\n }\n\n throw new Error(\n `GrooveSkills internal error: Unable to locate bundled skills directory from ${currentDir}`\n );\n}\n","import { detectProjectContext } from \"@/domains/detector/project-detector\";\nimport { runInteractiveUi } from \"@/domains/ui/ui-orchestrator\";\nimport { installSkills } from \"@/domains/installer/install-orchestrator\";\nimport type { AgentId } from \"@/types/agent.types\";\n\nexport interface CliOptions {\n skills?: string[];\n agents?: AgentId[];\n yes?: boolean;\n}\n\nexport async function runGrooveSkills(options: CliOptions = {}): Promise<void> {\n const targetPath = process.cwd();\n const context = detectProjectContext(targetPath);\n\n if (options.skills && options.skills.length > 0 && options.agents && options.agents.length > 0) {\n await installSkills({\n targetPath,\n selectedSkillIds: options.skills,\n selectedAgents: options.agents,\n forceOverwrite: Boolean(options.yes),\n });\n return;\n }\n\n await runInteractiveUi(context);\n}\n"],"mappings":"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","names":["p","pc","p","p","join","join","existsSync","join","join","lstatSync","join","existsSync","mkdirSync","existsSync","join","join","existsSync","mkdirSync","mkdirSync","existsSync","join","join","existsSync","mkdirSync","mkdirSync","existsSync","join","join","existsSync","mkdirSync","mkdirSync","existsSync","readFileSync","join","join","existsSync","existsSync","mkdirSync","join","readFileSync","join","pc","s","confirm"]}
|
package/dist/cli.js
CHANGED
package/dist/main.js
CHANGED
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/domains/detector/detect-agents.ts","../src/domains/detector/detect-dependencies.ts","../src/domains/registry/skill-catalog.ts","../src/domains/detector/project-detector.ts","../src/domains/ui/ui-orchestrator.ts","../src/domains/ui/banners.ts","../src/domains/ui/prompt-skills.ts","../src/domains/ui/prompt-agents.ts","../src/domains/ui/prompt-confirm-overwrite.ts","../src/domains/installer/verify-skill-exists.ts","../src/domains/installer/install-orchestrator.ts","../src/domains/adapters/antigravity.adapter.ts","../src/domains/adapters/claude.adapter.ts","../src/domains/adapters/cursor.adapter.ts","../src/domains/adapters/gemini.adapter.ts","../src/domains/installer/resolve-skills-source.ts","../src/main.ts"],"sourcesContent":["import { readdirSync } from \"node:fs\";\nimport type { AgentId } from \"@/types/agent.types\";\n\nexport function detectAgents(targetPath: string): AgentId[] {\n const detected: AgentId[] = [];\n\n try {\n const entries = new Set(readdirSync(targetPath));\n\n if (entries.has(\".agents\")) {\n detected.push(\"antigravity\");\n }\n if (entries.has(\".claude\")) {\n detected.push(\"claude\");\n }\n if (entries.has(\".cursor\")) {\n detected.push(\"cursor\");\n }\n if (entries.has(\".gemini\")) {\n detected.push(\"gemini\");\n }\n } catch {\n // If directory cannot be read, return empty list gracefully\n }\n\n return detected;\n}\n","import { readFileSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\n\nexport interface PackageJsonDetection {\n dependencies: string[];\n exists: boolean;\n}\n\nexport function detectDependencies(targetPath: string): PackageJsonDetection {\n const packageJsonPath = join(targetPath, \"package.json\");\n\n if (!existsSync(packageJsonPath)) {\n return { dependencies: [], exists: false };\n }\n\n try {\n const raw = readFileSync(packageJsonPath, \"utf-8\");\n const parsed = JSON.parse(raw) as {\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n };\n\n const direct = Object.keys(parsed.dependencies ?? {});\n const dev = Object.keys(parsed.devDependencies ?? {});\n const all = Array.from(new Set([...direct, ...dev]));\n\n return { dependencies: all, exists: true };\n } catch {\n return { dependencies: [], exists: true };\n }\n}\n","import type { SkillMetadata } from \"@/types/skill.types\";\n\nexport const SKILL_CATALOG: SkillMetadata[] = [\n {\n id: \"best-practices\",\n name: \"Universal Best Practices\",\n description: \"Multi-language clean code standards, early returns, no barrel files, strict typing, <200 lines\",\n dependencies: [],\n directoryName: \"best-practices\",\n },\n {\n id: \"hono\",\n name: \"Hono Architecture (Valibot)\",\n description: \"Enterprise Hono API standard with Valibot validation, isolated Actions layer, and RPC bindings\",\n dependencies: [\"hono\", \"@hono/valibot-validator\", \"@hono/standard-validator\"],\n directoryName: \"hono\",\n },\n];\n","import { detectAgents } from \"@/domains/detector/detect-agents\";\nimport { detectDependencies } from \"@/domains/detector/detect-dependencies\";\nimport { SKILL_CATALOG } from \"@/domains/registry/skill-catalog\";\nimport type { ProjectContext } from \"@/types/context.types\";\n\nexport function detectProjectContext(targetPath: string): ProjectContext {\n const detectedAgents = detectAgents(targetPath);\n const { dependencies, exists } = detectDependencies(targetPath);\n\n const suggestedSkillIds: string[] = [\"best-practices\"];\n\n for (const skill of SKILL_CATALOG) {\n if (skill.dependencies.length === 0) {\n continue;\n }\n const hasMatch = skill.dependencies.some((dep) => dependencies.includes(dep));\n if (hasMatch && !suggestedSkillIds.includes(skill.id)) {\n suggestedSkillIds.push(skill.id);\n }\n }\n\n return {\n targetPath,\n detectedDependencies: dependencies,\n suggestedSkillIds,\n detectedAgents,\n packageJsonExists: exists,\n };\n}\n","import * as p from \"@clack/prompts\";\nimport pc from \"picocolors\";\nimport { renderBanner } from \"@/domains/ui/banners\";\nimport { promptSkills } from \"@/domains/ui/prompt-skills\";\nimport { promptAgents } from \"@/domains/ui/prompt-agents\";\nimport { promptConfirmOverwrite } from \"@/domains/ui/prompt-confirm-overwrite\";\nimport { verifySkillExists } from \"@/domains/installer/verify-skill-exists\";\nimport { installSkills } from \"@/domains/installer/install-orchestrator\";\nimport { SKILL_CATALOG } from \"@/domains/registry/skill-catalog\";\nimport type { ProjectContext } from \"@/types/context.types\";\nimport type { AgentId } from \"@/types/agent.types\";\n\nexport async function runInteractiveUi(context: ProjectContext): Promise<void> {\n console.log(renderBanner());\n p.intro(pc.magenta(\"Welcome to GrooveSkills! Let's tailor your AI agents with clean architectural standards.\"));\n\n if (context.detectedDependencies.length > 0) {\n p.note(\n `Detected dependencies: ${context.detectedDependencies.map((d) => pc.bold(d)).join(\", \")}\\n` +\n `Active AI folders: ${context.detectedAgents.map((a) => pc.green(a)).join(\", \") || \"None (will be created)\"}`,\n \"Project Environment\"\n );\n }\n\n const selectedSkills = await promptSkills(context.suggestedSkillIds);\n if (p.isCancel(selectedSkills)) {\n p.cancel(\"Installation cancelled. Have a wonderful day!\");\n process.exit(0);\n }\n\n const selectedAgents = await promptAgents(context.detectedAgents);\n if (p.isCancel(selectedAgents)) {\n p.cancel(\"Installation cancelled. Have a wonderful day!\");\n process.exit(0);\n }\n\n let forceOverwrite = true;\n const anyExists = (selectedSkills as string[]).some((skillId) => {\n const meta = SKILL_CATALOG.find((s) => s.id === skillId);\n return meta ? verifySkillExists(context.targetPath, meta.directoryName, selectedAgents as AgentId[]) : false;\n });\n\n if (anyExists) {\n const confirm = await promptConfirmOverwrite();\n if (p.isCancel(confirm) || !confirm) {\n p.cancel(\"Installation stopped to protect existing skills.\");\n process.exit(0);\n }\n forceOverwrite = Boolean(confirm);\n }\n\n const s = p.spinner();\n s.start(\"Installing and adapting skills across your configured AI agents...\");\n\n const result = await installSkills({\n targetPath: context.targetPath,\n selectedSkillIds: selectedSkills as string[],\n selectedAgents: selectedAgents as AgentId[],\n forceOverwrite,\n });\n\n s.stop(pc.green(\"All skills have been successfully installed and configured!\"));\n\n p.note(\n `Configured skills: ${result.installedSkills.map((s) => pc.bold(s)).join(\", \")}\\n` +\n `Target agents: ${result.configuredAgents.map((a) => pc.cyan(a)).join(\", \")}`,\n \"Installation Summary\"\n );\n\n p.outro(pc.green(\"Your AI programming pair is now empowered with your team's architectural habits! 🚀\"));\n}\n","import pc from \"picocolors\";\n\nexport function renderBanner(): string {\n const title = pc.bold(pc.white(\" GROOVE SKILLS \"));\n const badge = pc.bgMagenta(pc.black(title));\n const subtitle = pc.dim(\"Multi-Agent AI Skills & Architectural Standards\");\n\n return `${badge} ${subtitle}\\n`;\n}\n","import * as p from \"@clack/prompts\";\nimport { SKILL_CATALOG } from \"@/domains/registry/skill-catalog\";\n\nexport async function promptSkills(suggestedSkillIds: string[]): Promise<string[] | symbol> {\n const options = SKILL_CATALOG.map((skill) => {\n const isSuggested = suggestedSkillIds.includes(skill.id);\n return {\n value: skill.id,\n label: skill.name,\n hint: isSuggested ? \"Suggested based on your project stack\" : skill.description,\n };\n });\n\n const selected = await p.multiselect({\n message: \"Which skills would you like to install in this project?\",\n options,\n initialValues: suggestedSkillIds,\n required: true,\n });\n\n return selected;\n}\n","import * as p from \"@clack/prompts\";\nimport type { AgentId } from \"@/types/agent.types\";\n\nexport async function promptAgents(detectedAgents: AgentId[]): Promise<AgentId[] | symbol> {\n const options: Array<{ value: AgentId; label: string; hint: string }> = [\n { value: \"antigravity\", label: \"Antigravity\", hint: \".agents/skills (Google Agentic IDE)\" },\n { value: \"claude\", label: \"Claude Code\", hint: \".claude/skills (Anthropic Claude Code)\" },\n { value: \"cursor\", label: \"Cursor\", hint: \".cursor/rules/*.mdc (Cursor IDE Rules)\" },\n { value: \"gemini\", label: \"Gemini Code Assist\", hint: \".gemini/skills (Google Gemini)\" },\n ];\n\n const initialValues: AgentId[] = detectedAgents.length > 0 ? detectedAgents : [\"antigravity\"];\n\n const selected = await p.multiselect({\n message: \"Which AI agents should be configured?\",\n options,\n initialValues,\n required: true,\n });\n\n return selected as AgentId[] | symbol;\n}\n","import * as p from \"@clack/prompts\";\n\nexport async function promptConfirmOverwrite(): Promise<boolean | symbol> {\n return await p.confirm({\n message: \"Some skills already exist in this project. Would you like to overwrite them with the latest version?\",\n initialValue: true,\n });\n}\n","import { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { AgentId } from \"@/types/agent.types\";\n\nconst AGENT_DESTINATION_MAP: Record<AgentId, (dir: string) => string> = {\n antigravity: (dir) => join(\".agents\", \"skills\", dir),\n claude: (dir) => join(\".claude\", \"skills\", dir),\n cursor: (dir) => join(\".cursor\", \"rules\", `${dir}.mdc`),\n gemini: (dir) => join(\".gemini\", \"skills\", dir),\n};\n\nexport function verifySkillExists(\n targetPath: string,\n skillDirectoryName: string,\n agents: AgentId[]\n): boolean {\n for (const agent of agents) {\n const relativePathResolver = AGENT_DESTINATION_MAP[agent];\n const destination = join(targetPath, relativePathResolver(skillDirectoryName));\n if (existsSync(destination)) {\n return true;\n }\n }\n\n return false;\n}\n","import { join } from \"node:path\";\nimport { AntigravityAdapter } from \"@/domains/adapters/antigravity.adapter\";\nimport { ClaudeAdapter } from \"@/domains/adapters/claude.adapter\";\nimport { CursorAdapter } from \"@/domains/adapters/cursor.adapter\";\nimport { GeminiAdapter } from \"@/domains/adapters/gemini.adapter\";\nimport { resolveSkillsSourceRoot } from \"@/domains/installer/resolve-skills-source\";\nimport { SKILL_CATALOG } from \"@/domains/registry/skill-catalog\";\nimport type { AgentAdapter } from \"@/domains/adapters/adapter.interface\";\nimport type { InstallOptions, InstallResult } from \"@/types/installer.types\";\nimport type { AgentId } from \"@/types/agent.types\";\n\nconst ADAPTER_REGISTRY: Record<AgentId, AgentAdapter> = {\n antigravity: new AntigravityAdapter(),\n claude: new ClaudeAdapter(),\n cursor: new CursorAdapter(),\n gemini: new GeminiAdapter(),\n};\n\nexport async function installSkills(options: InstallOptions): Promise<InstallResult> {\n const sourceRoot = resolveSkillsSourceRoot();\n const createdFiles: string[] = [];\n\n for (const skillId of options.selectedSkillIds) {\n const skill = SKILL_CATALOG.find((item) => item.id === skillId);\n if (!skill) {\n continue;\n }\n\n const skillSourceDir = join(sourceRoot, skill.directoryName);\n\n for (const agentId of options.selectedAgents) {\n const adapter = ADAPTER_REGISTRY[agentId];\n if (!adapter) {\n continue;\n }\n\n const files = await adapter.installSkill(options.targetPath, skill, skillSourceDir);\n createdFiles.push(...files);\n }\n }\n\n return {\n installedSkills: options.selectedSkillIds,\n configuredAgents: options.selectedAgents,\n createdFiles,\n };\n}\n","import { cpSync, mkdirSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { AgentAdapter } from \"@/domains/adapters/adapter.interface\";\nimport type { SkillMetadata } from \"@/types/skill.types\";\n\nexport class AntigravityAdapter implements AgentAdapter {\n readonly id = \"antigravity\" as const;\n readonly name = \"Antigravity\";\n readonly targetRelativeDir = \".agents/skills\";\n\n async installSkill(\n targetPath: string,\n skill: SkillMetadata,\n skillSourceDir: string\n ): Promise<string[]> {\n const destination = join(targetPath, this.targetRelativeDir, skill.directoryName);\n\n if (!existsSync(destination)) {\n mkdirSync(destination, { recursive: true });\n }\n\n cpSync(skillSourceDir, destination, { recursive: true });\n\n return [destination];\n }\n}\n","import { cpSync, mkdirSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { AgentAdapter } from \"@/domains/adapters/adapter.interface\";\nimport type { SkillMetadata } from \"@/types/skill.types\";\n\nexport class ClaudeAdapter implements AgentAdapter {\n readonly id = \"claude\" as const;\n readonly name = \"Claude Code\";\n readonly targetRelativeDir = \".claude/skills\";\n\n async installSkill(\n targetPath: string,\n skill: SkillMetadata,\n skillSourceDir: string\n ): Promise<string[]> {\n const destination = join(targetPath, this.targetRelativeDir, skill.directoryName);\n\n if (!existsSync(destination)) {\n mkdirSync(destination, { recursive: true });\n }\n\n cpSync(skillSourceDir, destination, { recursive: true });\n\n return [destination];\n }\n}\n","import { writeFileSync, mkdirSync, existsSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { AgentAdapter } from \"@/domains/adapters/adapter.interface\";\nimport type { SkillMetadata } from \"@/types/skill.types\";\n\nexport class CursorAdapter implements AgentAdapter {\n readonly id = \"cursor\" as const;\n readonly name = \"Cursor\";\n readonly targetRelativeDir = \".cursor/rules\";\n\n async installSkill(\n targetPath: string,\n skill: SkillMetadata,\n skillSourceDir: string\n ): Promise<string[]> {\n const rulesDir = join(targetPath, this.targetRelativeDir);\n\n if (!existsSync(rulesDir)) {\n mkdirSync(rulesDir, { recursive: true });\n }\n\n const skillMdPath = join(skillSourceDir, \"SKILL.md\");\n let content = \"\";\n\n if (existsSync(skillMdPath)) {\n content = readFileSync(skillMdPath, \"utf-8\");\n }\n\n const mdcHeader = `---\ndescription: ${skill.description}\nglobs: [\"**/*\"]\nalwaysApply: false\n---\n\n`;\n\n const cleanedBody = content.replace(/^---[\\s\\S]*?---\\s*/, \"\");\n const targetFile = join(rulesDir, `${skill.id}.mdc`);\n\n writeFileSync(targetFile, `${mdcHeader}${cleanedBody}`, \"utf-8\");\n\n return [targetFile];\n }\n}\n","import { cpSync, mkdirSync, existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { AgentAdapter } from \"@/domains/adapters/adapter.interface\";\nimport type { SkillMetadata } from \"@/types/skill.types\";\n\nexport class GeminiAdapter implements AgentAdapter {\n readonly id = \"gemini\" as const;\n readonly name = \"Gemini Code Assist\";\n readonly targetRelativeDir = \".gemini/skills\";\n\n async installSkill(\n targetPath: string,\n skill: SkillMetadata,\n skillSourceDir: string\n ): Promise<string[]> {\n const destination = join(targetPath, this.targetRelativeDir, skill.directoryName);\n\n if (!existsSync(destination)) {\n mkdirSync(destination, { recursive: true });\n }\n\n cpSync(skillSourceDir, destination, { recursive: true });\n\n return [destination];\n }\n}\n","import { fileURLToPath } from \"node:url\";\nimport { dirname, resolve, join } from \"node:path\";\nimport { existsSync } from \"node:fs\";\n\nexport function resolveSkillsSourceRoot(): string {\n const currentFilePath = fileURLToPath(import.meta.url);\n const currentDir = dirname(currentFilePath);\n\n const candidate1 = resolve(currentDir, \"../../../skills\");\n if (existsSync(candidate1)) {\n return candidate1;\n }\n\n const candidate2 = resolve(currentDir, \"../../skills\");\n if (existsSync(candidate2)) {\n return candidate2;\n }\n\n const candidate3 = resolve(process.cwd(), \"skills\");\n if (existsSync(candidate3)) {\n return candidate3;\n }\n\n return join(process.cwd(), \"skills\");\n}\n","import { detectProjectContext } from \"@/domains/detector/project-detector\";\nimport { runInteractiveUi } from \"@/domains/ui/ui-orchestrator\";\nimport { installSkills } from \"@/domains/installer/install-orchestrator\";\nimport type { AgentId } from \"@/types/agent.types\";\n\nexport interface CliOptions {\n skills?: string[];\n agents?: AgentId[];\n yes?: boolean;\n}\n\nexport async function runGrooveSkills(options: CliOptions = {}): Promise<void> {\n const targetPath = process.cwd();\n const context = detectProjectContext(targetPath);\n\n if (options.skills && options.skills.length > 0 && options.agents && options.agents.length > 0) {\n await installSkills({\n targetPath,\n selectedSkillIds: options.skills,\n selectedAgents: options.agents,\n forceOverwrite: Boolean(options.yes),\n });\n return;\n }\n\n await runInteractiveUi(context);\n}\n"],"mappings":"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","names":["p","pc","p","p","existsSync","join","join","existsSync","join","cpSync","mkdirSync","existsSync","join","mkdirSync","existsSync","readFileSync","join","cpSync","mkdirSync","existsSync","join","join","existsSync","join","pc","s","confirm"]}
|