prjct-cli 0.37.0 → 0.39.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 (33) hide show
  1. package/CHANGELOG.md +108 -0
  2. package/README.md +84 -37
  3. package/bin/prjct.ts +11 -1
  4. package/core/index.ts +53 -26
  5. package/core/infrastructure/ai-provider.ts +157 -1
  6. package/core/infrastructure/setup.ts +225 -7
  7. package/core/types/provider.ts +18 -1
  8. package/dist/bin/prjct.mjs +3607 -1050
  9. package/dist/core/infrastructure/command-installer.js +458 -47
  10. package/dist/core/infrastructure/setup.js +728 -211
  11. package/package.json +1 -1
  12. package/templates/antigravity/SKILL.md +39 -0
  13. package/templates/cursor/commands/bug.md +8 -0
  14. package/templates/cursor/commands/done.md +4 -0
  15. package/templates/cursor/commands/pause.md +6 -0
  16. package/templates/cursor/commands/resume.md +4 -0
  17. package/templates/cursor/commands/ship.md +8 -0
  18. package/templates/cursor/commands/sync.md +4 -0
  19. package/templates/cursor/commands/task.md +8 -0
  20. package/templates/cursor/router.mdc +6 -6
  21. package/templates/global/ANTIGRAVITY.md +256 -0
  22. package/templates/global/CLAUDE.md +30 -0
  23. package/templates/global/CURSOR.mdc +60 -25
  24. package/templates/global/GEMINI.md +30 -0
  25. package/templates/global/WINDSURF.md +268 -0
  26. package/templates/windsurf/router.md +28 -0
  27. package/templates/windsurf/workflows/bug.md +8 -0
  28. package/templates/windsurf/workflows/done.md +4 -0
  29. package/templates/windsurf/workflows/pause.md +4 -0
  30. package/templates/windsurf/workflows/resume.md +4 -0
  31. package/templates/windsurf/workflows/ship.md +8 -0
  32. package/templates/windsurf/workflows/sync.md +4 -0
  33. package/templates/windsurf/workflows/task.md +8 -0
@@ -6,6 +6,9 @@ var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
8
  var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
9
+ var __esm = (fn, res) => function __init() {
10
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
11
+ };
9
12
  var __export = (target, all) => {
10
13
  for (var name in all)
11
14
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -28,6 +31,386 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
28
31
  ));
29
32
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
30
33
 
34
+ // core/infrastructure/ai-provider.ts
35
+ var ai_provider_exports = {};
36
+ __export(ai_provider_exports, {
37
+ AntigravityProvider: () => AntigravityProvider,
38
+ ClaudeProvider: () => ClaudeProvider,
39
+ CursorProvider: () => CursorProvider,
40
+ GeminiProvider: () => GeminiProvider,
41
+ Providers: () => Providers,
42
+ WindsurfProvider: () => WindsurfProvider,
43
+ default: () => ai_provider_default,
44
+ detectAllProviders: () => detectAllProviders,
45
+ detectAntigravity: () => detectAntigravity,
46
+ detectCursorProject: () => detectCursorProject,
47
+ detectProvider: () => detectProvider,
48
+ detectWindsurfProject: () => detectWindsurfProject,
49
+ getActiveProvider: () => getActiveProvider,
50
+ getCommandsDir: () => getCommandsDir,
51
+ getGlobalContextPath: () => getGlobalContextPath,
52
+ getGlobalSettingsPath: () => getGlobalSettingsPath,
53
+ getProjectCommandsPath: () => getProjectCommandsPath,
54
+ getProviderBranding: () => getProviderBranding,
55
+ getSkillsPath: () => getSkillsPath,
56
+ hasProviderConfig: () => hasProviderConfig,
57
+ needsCursorRouterRegeneration: () => needsCursorRouterRegeneration,
58
+ needsWindsurfRouterRegeneration: () => needsWindsurfRouterRegeneration,
59
+ selectProvider: () => selectProvider
60
+ });
61
+ function whichCommand(command) {
62
+ try {
63
+ const result = (0, import_child_process.execSync)(`which ${command}`, { stdio: "pipe", encoding: "utf-8" });
64
+ return result.trim();
65
+ } catch {
66
+ return null;
67
+ }
68
+ }
69
+ function getCliVersion(command) {
70
+ try {
71
+ const result = (0, import_child_process.execSync)(`${command} --version`, { stdio: "pipe", encoding: "utf-8" });
72
+ const match = result.match(/\d+\.\d+\.\d+/);
73
+ return match ? match[0] : result.trim();
74
+ } catch {
75
+ return null;
76
+ }
77
+ }
78
+ function detectProvider(provider) {
79
+ const config = Providers[provider];
80
+ if (!config.cliCommand) {
81
+ return { installed: false };
82
+ }
83
+ const cliPath = whichCommand(config.cliCommand);
84
+ if (!cliPath) {
85
+ return { installed: false };
86
+ }
87
+ const version = getCliVersion(config.cliCommand);
88
+ return {
89
+ installed: true,
90
+ version: version || void 0,
91
+ path: cliPath
92
+ };
93
+ }
94
+ function detectAllProviders() {
95
+ return {
96
+ claude: detectProvider("claude"),
97
+ gemini: detectProvider("gemini")
98
+ };
99
+ }
100
+ function getActiveProvider(projectProvider) {
101
+ if (projectProvider && Providers[projectProvider]) {
102
+ return Providers[projectProvider];
103
+ }
104
+ const detection = detectAllProviders();
105
+ if (detection.claude.installed && !detection.gemini.installed) {
106
+ return ClaudeProvider;
107
+ }
108
+ if (detection.gemini.installed && !detection.claude.installed) {
109
+ return GeminiProvider;
110
+ }
111
+ return ClaudeProvider;
112
+ }
113
+ function hasProviderConfig(provider) {
114
+ const config = Providers[provider];
115
+ if (!config.configDir) {
116
+ return false;
117
+ }
118
+ return import_fs2.default.existsSync(config.configDir);
119
+ }
120
+ function getProviderBranding(provider) {
121
+ const config = Providers[provider];
122
+ if (provider === "gemini") {
123
+ return {
124
+ commitFooter: `\u{1F916} Generated with [p/](https://www.prjct.app/)
125
+ Designed for [Gemini](${config.websiteUrl})`,
126
+ signature: "\u26A1 prjct + Gemini"
127
+ };
128
+ }
129
+ if (provider === "cursor") {
130
+ return {
131
+ commitFooter: `\u{1F916} Generated with [p/](https://www.prjct.app/)
132
+ Built with [Cursor](${config.websiteUrl})`,
133
+ signature: "\u26A1 prjct + Cursor"
134
+ };
135
+ }
136
+ if (provider === "antigravity") {
137
+ return {
138
+ commitFooter: `\u{1F916} Generated with [p/](https://www.prjct.app/)
139
+ Powered by [Antigravity](${config.websiteUrl})`,
140
+ signature: "\u26A1 prjct + Antigravity"
141
+ };
142
+ }
143
+ if (provider === "windsurf") {
144
+ return {
145
+ commitFooter: `\u{1F916} Generated with [p/](https://www.prjct.app/)
146
+ Built with [Windsurf](${config.websiteUrl})`,
147
+ signature: "\u26A1 prjct + Windsurf"
148
+ };
149
+ }
150
+ return {
151
+ commitFooter: `\u{1F916} Generated with [p/](https://www.prjct.app/)
152
+ Designed for [Claude](${config.websiteUrl})`,
153
+ signature: "\u26A1 prjct + Claude"
154
+ };
155
+ }
156
+ function detectCursorProject(projectRoot) {
157
+ const cursorDir = import_path2.default.join(projectRoot, ".cursor");
158
+ const rulesDir = import_path2.default.join(cursorDir, "rules");
159
+ const routerPath = import_path2.default.join(rulesDir, "prjct.mdc");
160
+ const detected = import_fs2.default.existsSync(cursorDir);
161
+ const routerInstalled = import_fs2.default.existsSync(routerPath);
162
+ return {
163
+ detected,
164
+ routerInstalled,
165
+ projectRoot: detected ? projectRoot : void 0
166
+ };
167
+ }
168
+ function needsCursorRouterRegeneration(projectRoot) {
169
+ const detection = detectCursorProject(projectRoot);
170
+ return detection.detected && !detection.routerInstalled;
171
+ }
172
+ function detectWindsurfProject(projectRoot) {
173
+ const windsurfDir = import_path2.default.join(projectRoot, ".windsurf");
174
+ const rulesDir = import_path2.default.join(windsurfDir, "rules");
175
+ const routerPath = import_path2.default.join(rulesDir, "prjct.md");
176
+ const detected = import_fs2.default.existsSync(windsurfDir);
177
+ const routerInstalled = import_fs2.default.existsSync(routerPath);
178
+ return {
179
+ detected,
180
+ routerInstalled,
181
+ projectRoot: detected ? projectRoot : void 0
182
+ };
183
+ }
184
+ function needsWindsurfRouterRegeneration(projectRoot) {
185
+ const detection = detectWindsurfProject(projectRoot);
186
+ return detection.detected && !detection.routerInstalled;
187
+ }
188
+ function detectAntigravity() {
189
+ const configPath = AntigravityProvider.configDir;
190
+ if (!configPath) {
191
+ return { installed: false, skillInstalled: false };
192
+ }
193
+ const installed = import_fs2.default.existsSync(configPath);
194
+ const skillPath = import_path2.default.join(configPath, "skills", "prjct", "SKILL.md");
195
+ const skillInstalled = import_fs2.default.existsSync(skillPath);
196
+ return {
197
+ installed,
198
+ skillInstalled,
199
+ configPath: installed ? configPath : void 0
200
+ };
201
+ }
202
+ function getGlobalContextPath(provider) {
203
+ const config = Providers[provider];
204
+ if (!config.configDir) {
205
+ return null;
206
+ }
207
+ return import_path2.default.join(config.configDir, config.contextFile);
208
+ }
209
+ function getGlobalSettingsPath(provider) {
210
+ const config = Providers[provider];
211
+ if (!config.configDir || !config.settingsFile) {
212
+ return null;
213
+ }
214
+ return import_path2.default.join(config.configDir, config.settingsFile);
215
+ }
216
+ function getSkillsPath(provider) {
217
+ return Providers[provider].skillsDir;
218
+ }
219
+ function getCommandsDir(provider) {
220
+ return Providers[provider].commandsDir;
221
+ }
222
+ function getProjectCommandsPath(provider, projectRoot) {
223
+ const config = Providers[provider];
224
+ return import_path2.default.join(projectRoot, config.commandsDir);
225
+ }
226
+ function selectProvider() {
227
+ const detection = detectAllProviders();
228
+ const claudeInstalled = detection.claude.installed;
229
+ const geminiInstalled = detection.gemini.installed;
230
+ if (!claudeInstalled && !geminiInstalled) {
231
+ return {
232
+ provider: "claude",
233
+ userSelected: false,
234
+ detection
235
+ };
236
+ }
237
+ if (claudeInstalled && !geminiInstalled) {
238
+ return {
239
+ provider: "claude",
240
+ userSelected: false,
241
+ detection
242
+ };
243
+ }
244
+ if (geminiInstalled && !claudeInstalled) {
245
+ return {
246
+ provider: "gemini",
247
+ userSelected: false,
248
+ detection
249
+ };
250
+ }
251
+ return {
252
+ provider: "claude",
253
+ userSelected: true,
254
+ // Indicates user should be prompted
255
+ detection
256
+ };
257
+ }
258
+ var import_child_process, import_fs2, import_path2, import_os, ClaudeProvider, GeminiProvider, AntigravityProvider, CursorProvider, WindsurfProvider, Providers, ai_provider_default;
259
+ var init_ai_provider = __esm({
260
+ "core/infrastructure/ai-provider.ts"() {
261
+ "use strict";
262
+ import_child_process = require("child_process");
263
+ import_fs2 = __toESM(require("fs"));
264
+ import_path2 = __toESM(require("path"));
265
+ import_os = __toESM(require("os"));
266
+ ClaudeProvider = {
267
+ name: "claude",
268
+ displayName: "Claude Code",
269
+ cliCommand: "claude",
270
+ configDir: import_path2.default.join(import_os.default.homedir(), ".claude"),
271
+ contextFile: "CLAUDE.md",
272
+ skillsDir: import_path2.default.join(import_os.default.homedir(), ".claude", "skills"),
273
+ commandsDir: ".claude/commands",
274
+ commandFormat: "md",
275
+ settingsFile: "settings.json",
276
+ projectSettingsFile: "settings.local.json",
277
+ ignoreFile: ".claudeignore",
278
+ websiteUrl: "https://www.anthropic.com/claude",
279
+ docsUrl: "https://docs.anthropic.com/claude-code"
280
+ };
281
+ GeminiProvider = {
282
+ name: "gemini",
283
+ displayName: "Gemini CLI",
284
+ cliCommand: "gemini",
285
+ configDir: import_path2.default.join(import_os.default.homedir(), ".gemini"),
286
+ contextFile: "GEMINI.md",
287
+ skillsDir: import_path2.default.join(import_os.default.homedir(), ".gemini", "skills"),
288
+ commandsDir: ".gemini/commands",
289
+ commandFormat: "toml",
290
+ settingsFile: "settings.json",
291
+ projectSettingsFile: "settings.json",
292
+ ignoreFile: ".geminiignore",
293
+ websiteUrl: "https://geminicli.com",
294
+ docsUrl: "https://geminicli.com/docs"
295
+ };
296
+ AntigravityProvider = {
297
+ name: "antigravity",
298
+ displayName: "Google Antigravity",
299
+ cliCommand: null,
300
+ // Not a CLI command, but a platform/app
301
+ configDir: import_path2.default.join(import_os.default.homedir(), ".gemini", "antigravity"),
302
+ contextFile: "ANTIGRAVITY.md",
303
+ skillsDir: import_path2.default.join(import_os.default.homedir(), ".gemini", "antigravity", "global_skills"),
304
+ commandsDir: ".agent/skills",
305
+ // Antigravity uses .agent/skills in projects
306
+ commandFormat: "md",
307
+ // Uses SKILL.md
308
+ settingsFile: "mcp_config.json",
309
+ // Uses MCP config
310
+ projectSettingsFile: null,
311
+ ignoreFile: ".agentignore",
312
+ // Assumed
313
+ websiteUrl: "https://gemini.google.com/app/antigravity",
314
+ docsUrl: "https://gemini.google.com/app/antigravity"
315
+ };
316
+ CursorProvider = {
317
+ name: "cursor",
318
+ displayName: "Cursor IDE",
319
+ cliCommand: null,
320
+ // Not a CLI - GUI app
321
+ configDir: null,
322
+ // No global config directory
323
+ contextFile: "prjct.mdc",
324
+ // Uses .mdc format with frontmatter
325
+ skillsDir: null,
326
+ // No skills directory
327
+ commandsDir: ".cursor/commands",
328
+ rulesDir: ".cursor/rules",
329
+ // Cursor-specific: rules directory
330
+ commandFormat: "md",
331
+ settingsFile: null,
332
+ projectSettingsFile: null,
333
+ ignoreFile: ".cursorignore",
334
+ isProjectLevel: true,
335
+ // Config is project-level only
336
+ websiteUrl: "https://cursor.com",
337
+ docsUrl: "https://cursor.com/docs"
338
+ };
339
+ WindsurfProvider = {
340
+ name: "windsurf",
341
+ displayName: "Windsurf IDE",
342
+ cliCommand: null,
343
+ // Not a CLI - GUI app
344
+ configDir: null,
345
+ // No global config directory
346
+ contextFile: "prjct.md",
347
+ // Uses .md format (not .mdc)
348
+ skillsDir: null,
349
+ // No skills directory
350
+ commandsDir: ".windsurf/workflows",
351
+ // Windsurf uses "workflows" not "commands"
352
+ rulesDir: ".windsurf/rules",
353
+ commandFormat: "md",
354
+ settingsFile: null,
355
+ projectSettingsFile: null,
356
+ ignoreFile: ".windsurfignore",
357
+ isProjectLevel: true,
358
+ // Config is project-level only
359
+ websiteUrl: "https://windsurf.com",
360
+ docsUrl: "https://docs.windsurf.com"
361
+ };
362
+ Providers = {
363
+ claude: ClaudeProvider,
364
+ gemini: GeminiProvider,
365
+ cursor: CursorProvider,
366
+ antigravity: AntigravityProvider,
367
+ windsurf: WindsurfProvider
368
+ };
369
+ __name(whichCommand, "whichCommand");
370
+ __name(getCliVersion, "getCliVersion");
371
+ __name(detectProvider, "detectProvider");
372
+ __name(detectAllProviders, "detectAllProviders");
373
+ __name(getActiveProvider, "getActiveProvider");
374
+ __name(hasProviderConfig, "hasProviderConfig");
375
+ __name(getProviderBranding, "getProviderBranding");
376
+ __name(detectCursorProject, "detectCursorProject");
377
+ __name(needsCursorRouterRegeneration, "needsCursorRouterRegeneration");
378
+ __name(detectWindsurfProject, "detectWindsurfProject");
379
+ __name(needsWindsurfRouterRegeneration, "needsWindsurfRouterRegeneration");
380
+ __name(detectAntigravity, "detectAntigravity");
381
+ __name(getGlobalContextPath, "getGlobalContextPath");
382
+ __name(getGlobalSettingsPath, "getGlobalSettingsPath");
383
+ __name(getSkillsPath, "getSkillsPath");
384
+ __name(getCommandsDir, "getCommandsDir");
385
+ __name(getProjectCommandsPath, "getProjectCommandsPath");
386
+ __name(selectProvider, "selectProvider");
387
+ ai_provider_default = {
388
+ Providers,
389
+ ClaudeProvider,
390
+ GeminiProvider,
391
+ CursorProvider,
392
+ AntigravityProvider,
393
+ WindsurfProvider,
394
+ detectProvider,
395
+ detectAllProviders,
396
+ detectAntigravity,
397
+ getActiveProvider,
398
+ hasProviderConfig,
399
+ getProviderBranding,
400
+ getGlobalContextPath,
401
+ getGlobalSettingsPath,
402
+ getSkillsPath,
403
+ getCommandsDir,
404
+ getProjectCommandsPath,
405
+ selectProvider,
406
+ detectCursorProject,
407
+ needsCursorRouterRegeneration,
408
+ detectWindsurfProject,
409
+ needsWindsurfRouterRegeneration
410
+ };
411
+ }
412
+ });
413
+
31
414
  // core/infrastructure/command-installer.ts
32
415
  var command_installer_exports = {};
33
416
  __export(command_installer_exports, {
@@ -40,8 +423,8 @@ __export(command_installer_exports, {
40
423
  });
41
424
  module.exports = __toCommonJS(command_installer_exports);
42
425
  var import_promises = __toESM(require("fs/promises"));
43
- var import_path2 = __toESM(require("path"));
44
- var import_os = __toESM(require("os"));
426
+ var import_path3 = __toESM(require("path"));
427
+ var import_os2 = __toESM(require("os"));
45
428
 
46
429
  // core/utils/version.ts
47
430
  var import_fs = __toESM(require("fs"));
@@ -100,14 +483,14 @@ __name(isNotFoundError, "isNotFoundError");
100
483
  // core/infrastructure/command-installer.ts
101
484
  async function installDocs() {
102
485
  try {
103
- const docsDir = import_path2.default.join(import_os.default.homedir(), ".prjct-cli", "docs");
104
- const templateDocsDir = import_path2.default.join(getPackageRoot(), "templates/global/docs");
486
+ const docsDir = import_path3.default.join(import_os2.default.homedir(), ".prjct-cli", "docs");
487
+ const templateDocsDir = import_path3.default.join(getPackageRoot(), "templates/global/docs");
105
488
  await import_promises.default.mkdir(docsDir, { recursive: true });
106
489
  const docFiles = await import_promises.default.readdir(templateDocsDir);
107
490
  for (const file of docFiles) {
108
491
  if (file.endsWith(".md")) {
109
- const srcPath = import_path2.default.join(templateDocsDir, file);
110
- const destPath = import_path2.default.join(docsDir, file);
492
+ const srcPath = import_path3.default.join(templateDocsDir, file);
493
+ const destPath = import_path3.default.join(docsDir, file);
111
494
  const content = await import_promises.default.readFile(srcPath, "utf-8");
112
495
  await import_promises.default.writeFile(destPath, content, "utf-8");
113
496
  }
@@ -118,21 +501,32 @@ async function installDocs() {
118
501
  }
119
502
  }
120
503
  __name(installDocs, "installDocs");
121
- async function installGlobalConfig(claudeConfigPath, detectClaude) {
122
- const claudeDetected = await detectClaude();
123
- if (!claudeDetected) {
504
+ async function installGlobalConfig() {
505
+ const aiProvider = (init_ai_provider(), __toCommonJS(ai_provider_exports));
506
+ const activeProvider = aiProvider.getActiveProvider();
507
+ const providerName = activeProvider.name;
508
+ const detection = aiProvider.detectProvider(providerName);
509
+ if (!detection.installed && !activeProvider.configDir) {
124
510
  return {
125
511
  success: false,
126
- error: "Claude not detected",
512
+ error: `${activeProvider.displayName} not detected`,
127
513
  action: "skipped"
128
514
  };
129
515
  }
130
516
  try {
131
- const claudeDir = import_path2.default.join(import_os.default.homedir(), ".claude");
132
- await import_promises.default.mkdir(claudeDir, { recursive: true });
133
- const globalConfigPath = import_path2.default.join(claudeDir, "CLAUDE.md");
134
- const templatePath = import_path2.default.join(getPackageRoot(), "templates/global/CLAUDE.md");
135
- const templateContent = await import_promises.default.readFile(templatePath, "utf-8");
517
+ await import_promises.default.mkdir(activeProvider.configDir, { recursive: true });
518
+ const globalConfigPath = import_path3.default.join(activeProvider.configDir, activeProvider.contextFile);
519
+ const templatePath = import_path3.default.join(getPackageRoot(), "templates", "global", activeProvider.contextFile);
520
+ let templateContent = "";
521
+ try {
522
+ templateContent = await import_promises.default.readFile(templatePath, "utf-8");
523
+ } catch (error) {
524
+ const fallbackTemplatePath = import_path3.default.join(getPackageRoot(), "templates/global/CLAUDE.md");
525
+ templateContent = await import_promises.default.readFile(fallbackTemplatePath, "utf-8");
526
+ if (providerName === "gemini") {
527
+ templateContent = templateContent.replace(/Claude/g, "Gemini");
528
+ }
529
+ }
136
530
  let existingContent = "";
137
531
  let fileExists = false;
138
532
  try {
@@ -200,15 +594,21 @@ var CommandInstaller = class {
200
594
  claudeConfigPath;
201
595
  templatesDir;
202
596
  constructor() {
203
- this.homeDir = import_os.default.homedir();
204
- this.claudeCommandsPath = import_path2.default.join(this.homeDir, ".claude", "commands", "p");
205
- this.claudeConfigPath = import_path2.default.join(this.homeDir, ".claude");
206
- this.templatesDir = import_path2.default.join(getPackageRoot(), "templates", "commands");
597
+ this.homeDir = import_os2.default.homedir();
598
+ const aiProvider = (init_ai_provider(), __toCommonJS(ai_provider_exports));
599
+ const activeProvider = aiProvider.getActiveProvider();
600
+ if (activeProvider.name === "gemini") {
601
+ this.claudeCommandsPath = import_path3.default.join(activeProvider.configDir, "commands");
602
+ } else {
603
+ this.claudeCommandsPath = import_path3.default.join(activeProvider.configDir, "commands", "p");
604
+ }
605
+ this.claudeConfigPath = activeProvider.configDir;
606
+ this.templatesDir = import_path3.default.join(getPackageRoot(), "templates", "commands");
207
607
  }
208
608
  /**
209
- * Detect if Claude is installed
609
+ * Detect if active provider is installed
210
610
  */
211
- async detectClaude() {
611
+ async detectActiveProvider() {
212
612
  try {
213
613
  await import_promises.default.access(this.claudeConfigPath);
214
614
  return true;
@@ -219,6 +619,12 @@ var CommandInstaller = class {
219
619
  throw error;
220
620
  }
221
621
  }
622
+ /**
623
+ * Detect if Claude is installed (legacy support)
624
+ */
625
+ async detectClaude() {
626
+ return this.detectActiveProvider();
627
+ }
222
628
  /**
223
629
  * Get list of command files to install
224
630
  */
@@ -251,14 +657,16 @@ var CommandInstaller = class {
251
657
  }
252
658
  }
253
659
  /**
254
- * Install commands to Claude
660
+ * Install commands to active AI agent
255
661
  */
256
662
  async installCommands() {
257
- const claudeDetected = await this.detectClaude();
258
- if (!claudeDetected) {
663
+ const providerDetected = await this.detectActiveProvider();
664
+ const aiProvider = (init_ai_provider(), __toCommonJS(ai_provider_exports));
665
+ const activeProvider = aiProvider.getActiveProvider();
666
+ if (!providerDetected) {
259
667
  return {
260
668
  success: false,
261
- error: "Claude not detected. Please install Claude Code or Claude Desktop first."
669
+ error: `${activeProvider.displayName} not detected. Please install it first.`
262
670
  };
263
671
  }
264
672
  try {
@@ -269,8 +677,8 @@ var CommandInstaller = class {
269
677
  const errors = [];
270
678
  for (const file of commandFiles) {
271
679
  try {
272
- const sourcePath = import_path2.default.join(this.templatesDir, file);
273
- const destPath = import_path2.default.join(this.claudeCommandsPath, file);
680
+ const sourcePath = import_path3.default.join(this.templatesDir, file);
681
+ const destPath = import_path3.default.join(this.claudeCommandsPath, file);
274
682
  const content = await import_promises.default.readFile(sourcePath, "utf-8");
275
683
  await import_promises.default.writeFile(destPath, content, "utf-8");
276
684
  installed.push(file.replace(".md", ""));
@@ -301,7 +709,7 @@ var CommandInstaller = class {
301
709
  const errors = [];
302
710
  for (const file of commandFiles) {
303
711
  try {
304
- const filePath = import_path2.default.join(this.claudeCommandsPath, file);
712
+ const filePath = import_path3.default.join(this.claudeCommandsPath, file);
305
713
  await import_promises.default.unlink(filePath);
306
714
  uninstalled.push(file.replace(".md", ""));
307
715
  } catch (error) {
@@ -386,7 +794,7 @@ var CommandInstaller = class {
386
794
  */
387
795
  async verifyTemplate(commandName) {
388
796
  try {
389
- const templatePath = import_path2.default.join(this.templatesDir, `${commandName}.md`);
797
+ const templatePath = import_path3.default.join(this.templatesDir, `${commandName}.md`);
390
798
  await import_promises.default.access(templatePath);
391
799
  return true;
392
800
  } catch (error) {
@@ -397,14 +805,17 @@ var CommandInstaller = class {
397
805
  }
398
806
  }
399
807
  /**
400
- * Install the p.md router to ~/.claude/commands/
808
+ * Install the router (p.md for Claude, p.toml for Gemini) to commands directory
401
809
  * This enables the "p. task" natural language trigger
402
- * Claude Code bug #2422 prevents subdirectory slash command discovery
403
810
  */
404
811
  async installRouter() {
812
+ const aiProvider = (init_ai_provider(), __toCommonJS(ai_provider_exports));
813
+ const activeProvider = aiProvider.getActiveProvider();
814
+ const routerFile = activeProvider.name === "gemini" ? "p.toml" : "p.md";
405
815
  try {
406
- const routerSource = import_path2.default.join(this.templatesDir, "p.md");
407
- const routerDest = import_path2.default.join(this.homeDir, ".claude", "commands", "p.md");
816
+ const routerSource = import_path3.default.join(this.templatesDir, routerFile);
817
+ const routerDest = import_path3.default.join(activeProvider.configDir, "commands", routerFile);
818
+ await import_promises.default.mkdir(import_path3.default.dirname(routerDest), { recursive: true });
408
819
  const content = await import_promises.default.readFile(routerSource, "utf-8");
409
820
  await import_promises.default.writeFile(routerDest, content, "utf-8");
410
821
  return true;
@@ -419,11 +830,11 @@ var CommandInstaller = class {
419
830
  * Sync commands - intelligent update that detects and removes orphans
420
831
  */
421
832
  async syncCommands() {
422
- const claudeDetected = await this.detectClaude();
423
- if (!claudeDetected) {
833
+ const providerDetected = await this.detectActiveProvider();
834
+ if (!providerDetected) {
424
835
  return {
425
836
  success: false,
426
- error: "Claude not detected",
837
+ error: "AI agent not detected",
427
838
  added: 0,
428
839
  updated: 0,
429
840
  removed: 0
@@ -453,8 +864,8 @@ var CommandInstaller = class {
453
864
  };
454
865
  for (const file of templateFiles) {
455
866
  try {
456
- const sourcePath = import_path2.default.join(this.templatesDir, file);
457
- const destPath = import_path2.default.join(this.claudeCommandsPath, file);
867
+ const sourcePath = import_path3.default.join(this.templatesDir, file);
868
+ const destPath = import_path3.default.join(this.claudeCommandsPath, file);
458
869
  const exists = installedFiles.includes(file);
459
870
  const content = await import_promises.default.readFile(sourcePath, "utf-8");
460
871
  await import_promises.default.writeFile(destPath, content, "utf-8");
@@ -479,10 +890,10 @@ var CommandInstaller = class {
479
890
  }
480
891
  }
481
892
  /**
482
- * Install or update global CLAUDE.md configuration
893
+ * Install or update global AI agent configuration (CLAUDE.md / GEMINI.md)
483
894
  */
484
895
  async installGlobalConfig() {
485
- return installGlobalConfig(this.claudeConfigPath, () => this.detectClaude());
896
+ return installGlobalConfig();
486
897
  }
487
898
  /**
488
899
  * Install documentation files to ~/.prjct-cli/docs/
@@ -492,17 +903,17 @@ var CommandInstaller = class {
492
903
  }
493
904
  };
494
905
  function getProviderPaths() {
495
- const homeDir = import_os.default.homedir();
906
+ const homeDir = import_os2.default.homedir();
496
907
  return {
497
908
  claude: {
498
- commands: import_path2.default.join(homeDir, ".claude", "commands", "p"),
499
- config: import_path2.default.join(homeDir, ".claude"),
500
- router: import_path2.default.join(homeDir, ".claude", "commands", "p.md")
909
+ commands: import_path3.default.join(homeDir, ".claude", "commands", "p"),
910
+ config: import_path3.default.join(homeDir, ".claude"),
911
+ router: import_path3.default.join(homeDir, ".claude", "commands", "p.md")
501
912
  },
502
913
  gemini: {
503
- commands: import_path2.default.join(homeDir, ".gemini", "commands"),
504
- config: import_path2.default.join(homeDir, ".gemini"),
505
- router: import_path2.default.join(homeDir, ".gemini", "commands", "p.toml")
914
+ commands: import_path3.default.join(homeDir, ".gemini", "commands"),
915
+ config: import_path3.default.join(homeDir, ".gemini"),
916
+ router: import_path3.default.join(homeDir, ".gemini", "commands", "p.toml")
506
917
  }
507
918
  };
508
919
  }