prjct-cli 0.60.2 → 0.62.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.
@@ -16,10 +16,10 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
16
16
  if (typeof require !== "undefined") return require.apply(this, arguments);
17
17
  throw Error('Dynamic require of "' + x + '" is not supported');
18
18
  });
19
- var __glob = (map) => (path58) => {
20
- var fn = map[path58];
19
+ var __glob = (map) => (path59) => {
20
+ var fn = map[path59];
21
21
  if (fn) return fn();
22
- throw new Error("Module not found in bundle: " + path58);
22
+ throw new Error("Module not found in bundle: " + path59);
23
23
  };
24
24
  var __esm = (fn, res) => function __init() {
25
25
  return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
@@ -4019,8 +4019,8 @@ function tryResolve(basePath, projectPath) {
4019
4019
  for (const ext of extensions) {
4020
4020
  const fullPath = basePath + ext;
4021
4021
  try {
4022
- const fs49 = __require("node:fs");
4023
- if (fs49.existsSync(fullPath) && fs49.statSync(fullPath).isFile()) {
4022
+ const fs50 = __require("node:fs");
4023
+ if (fs50.existsSync(fullPath) && fs50.statSync(fullPath).isFile()) {
4024
4024
  return path12.relative(projectPath, fullPath);
4025
4025
  }
4026
4026
  } catch {
@@ -5203,11 +5203,11 @@ async function runSignaturesTool(args2, projectPath) {
5203
5203
  }
5204
5204
  };
5205
5205
  }
5206
- const fs49 = await import("node:fs/promises");
5207
- const path58 = await import("node:path");
5208
- const fullPath = path58.isAbsolute(filePath) ? filePath : path58.join(projectPath, filePath);
5206
+ const fs50 = await import("node:fs/promises");
5207
+ const path59 = await import("node:path");
5208
+ const fullPath = path59.isAbsolute(filePath) ? filePath : path59.join(projectPath, filePath);
5209
5209
  try {
5210
- const stat = await fs49.stat(fullPath);
5210
+ const stat = await fs50.stat(fullPath);
5211
5211
  if (stat.isDirectory()) {
5212
5212
  const results = await extractDirectorySignatures(filePath, projectPath, {
5213
5213
  recursive: args2.includes("--recursive") || args2.includes("-r")
@@ -5274,11 +5274,11 @@ async function runSummaryTool(args2, projectPath) {
5274
5274
  }
5275
5275
  };
5276
5276
  }
5277
- const fs49 = await import("node:fs/promises");
5278
- const path58 = await import("node:path");
5279
- const fullPath = path58.isAbsolute(targetPath) ? targetPath : path58.join(projectPath, targetPath);
5277
+ const fs50 = await import("node:fs/promises");
5278
+ const path59 = await import("node:path");
5279
+ const fullPath = path59.isAbsolute(targetPath) ? targetPath : path59.join(projectPath, targetPath);
5280
5280
  try {
5281
- const stat = await fs49.stat(fullPath);
5281
+ const stat = await fs50.stat(fullPath);
5282
5282
  if (stat.isDirectory()) {
5283
5283
  const results = await summarizeDirectory(targetPath, projectPath, {
5284
5284
  recursive: args2.includes("--recursive") || args2.includes("-r")
@@ -15594,6 +15594,249 @@ var init_file_scorer = __esm({
15594
15594
  }
15595
15595
  });
15596
15596
 
15597
+ // core/services/dependency-validator.ts
15598
+ import { execSync as execSync4 } from "node:child_process";
15599
+ var TOOLS, DependencyValidator, DependencyError, dependencyValidator;
15600
+ var init_dependency_validator = __esm({
15601
+ "core/services/dependency-validator.ts"() {
15602
+ "use strict";
15603
+ init_error_messages();
15604
+ TOOLS = {
15605
+ git: {
15606
+ name: "git",
15607
+ command: "git --version",
15608
+ versionRegex: /git version ([\d.]+)/,
15609
+ required: true,
15610
+ installHint: "Install Git: https://git-scm.com/downloads",
15611
+ docs: "https://git-scm.com/doc"
15612
+ },
15613
+ node: {
15614
+ name: "node",
15615
+ command: "node --version",
15616
+ versionRegex: /v([\d.]+)/,
15617
+ required: true,
15618
+ installHint: "Install Node.js: https://nodejs.org",
15619
+ docs: "https://nodejs.org/docs"
15620
+ },
15621
+ bun: {
15622
+ name: "bun",
15623
+ command: "bun --version",
15624
+ versionRegex: /([\d.]+)/,
15625
+ required: false,
15626
+ installHint: "Install Bun: curl -fsSL https://bun.sh/install | bash",
15627
+ docs: "https://bun.sh/docs"
15628
+ },
15629
+ gh: {
15630
+ name: "gh",
15631
+ command: "gh --version",
15632
+ versionRegex: /gh version ([\d.]+)/,
15633
+ required: false,
15634
+ installHint: "Install GitHub CLI: https://cli.github.com",
15635
+ docs: "https://cli.github.com/manual"
15636
+ },
15637
+ npm: {
15638
+ name: "npm",
15639
+ command: "npm --version",
15640
+ versionRegex: /([\d.]+)/,
15641
+ required: false,
15642
+ installHint: "npm comes with Node.js: https://nodejs.org"
15643
+ },
15644
+ claude: {
15645
+ name: "claude",
15646
+ command: "claude --version",
15647
+ versionRegex: /claude ([\d.]+)/,
15648
+ required: false,
15649
+ installHint: "Install Claude Code: npm install -g @anthropic-ai/claude-code",
15650
+ docs: "https://docs.anthropic.com/claude-code"
15651
+ },
15652
+ gemini: {
15653
+ name: "gemini",
15654
+ command: "gemini --version",
15655
+ versionRegex: /gemini ([\d.]+)/,
15656
+ required: false,
15657
+ installHint: "Install Gemini CLI: npm install -g @google/gemini-cli",
15658
+ docs: "https://ai.google.dev/gemini-api/docs"
15659
+ }
15660
+ };
15661
+ DependencyValidator = class {
15662
+ static {
15663
+ __name(this, "DependencyValidator");
15664
+ }
15665
+ cache = /* @__PURE__ */ new Map();
15666
+ cacheTimeout = 6e4;
15667
+ // 1 minute cache
15668
+ cacheTimestamps = /* @__PURE__ */ new Map();
15669
+ /**
15670
+ * Check if a tool is available
15671
+ * Uses caching to avoid repeated execSync calls
15672
+ */
15673
+ checkTool(toolName) {
15674
+ const cached = this.getCached(toolName);
15675
+ if (cached) return cached;
15676
+ const definition = TOOLS[toolName];
15677
+ if (!definition) {
15678
+ return this.checkUnknownTool(toolName);
15679
+ }
15680
+ const status = this.executeCheck(definition);
15681
+ this.setCache(toolName, status);
15682
+ return status;
15683
+ }
15684
+ /**
15685
+ * Ensure a tool is available, throw helpful error if not
15686
+ * Use this before operations that require a specific tool
15687
+ */
15688
+ ensureTool(toolName) {
15689
+ const status = this.checkTool(toolName);
15690
+ if (!status.available) {
15691
+ const definition = TOOLS[toolName];
15692
+ const error = status.error || {
15693
+ message: `${toolName} is not available`,
15694
+ hint: definition?.installHint || `Install ${toolName} and try again`,
15695
+ docs: definition?.docs
15696
+ };
15697
+ throw new DependencyError(error);
15698
+ }
15699
+ }
15700
+ /**
15701
+ * Ensure multiple tools are available
15702
+ */
15703
+ ensureTools(toolNames) {
15704
+ const missing = [];
15705
+ for (const name of toolNames) {
15706
+ const status = this.checkTool(name);
15707
+ if (!status.available) {
15708
+ missing.push(name);
15709
+ }
15710
+ }
15711
+ if (missing.length > 0) {
15712
+ const hints = missing.map((name) => {
15713
+ const def = TOOLS[name];
15714
+ return def ? ` ${name}: ${def.installHint}` : ` ${name}: Install and try again`;
15715
+ }).join("\n");
15716
+ throw new DependencyError({
15717
+ message: `Missing required tools: ${missing.join(", ")}`,
15718
+ hint: `Install the following:
15719
+ ${hints}`
15720
+ });
15721
+ }
15722
+ }
15723
+ /**
15724
+ * Check if tool is available (boolean convenience method)
15725
+ */
15726
+ isAvailable(toolName) {
15727
+ return this.checkTool(toolName).available;
15728
+ }
15729
+ /**
15730
+ * Get tool version if available
15731
+ */
15732
+ getVersion(toolName) {
15733
+ return this.checkTool(toolName).version;
15734
+ }
15735
+ /**
15736
+ * Check multiple tools and return summary
15737
+ */
15738
+ checkAll(toolNames) {
15739
+ const names = toolNames || Object.keys(TOOLS);
15740
+ const results = /* @__PURE__ */ new Map();
15741
+ for (const name of names) {
15742
+ results.set(name, this.checkTool(name));
15743
+ }
15744
+ return results;
15745
+ }
15746
+ /**
15747
+ * Clear the cache (useful for tests or after installations)
15748
+ */
15749
+ clearCache() {
15750
+ this.cache.clear();
15751
+ this.cacheTimestamps.clear();
15752
+ }
15753
+ // ==========================================================================
15754
+ // PRIVATE METHODS
15755
+ // ==========================================================================
15756
+ executeCheck(definition) {
15757
+ try {
15758
+ const output = execSync4(definition.command, {
15759
+ encoding: "utf-8",
15760
+ stdio: ["pipe", "pipe", "pipe"],
15761
+ timeout: 5e3
15762
+ // 5 second timeout
15763
+ });
15764
+ let version;
15765
+ if (definition.versionRegex) {
15766
+ const match = output.match(definition.versionRegex);
15767
+ version = match ? match[1] : void 0;
15768
+ }
15769
+ return { available: true, version };
15770
+ } catch {
15771
+ return {
15772
+ available: false,
15773
+ error: createError(
15774
+ `${definition.name} is not installed or not in PATH`,
15775
+ definition.installHint,
15776
+ { docs: definition.docs }
15777
+ )
15778
+ };
15779
+ }
15780
+ }
15781
+ checkUnknownTool(toolName) {
15782
+ try {
15783
+ execSync4(`${toolName} --version`, {
15784
+ encoding: "utf-8",
15785
+ stdio: ["pipe", "pipe", "pipe"],
15786
+ timeout: 5e3
15787
+ });
15788
+ return { available: true };
15789
+ } catch {
15790
+ try {
15791
+ execSync4(`${toolName} -v`, {
15792
+ encoding: "utf-8",
15793
+ stdio: ["pipe", "pipe", "pipe"],
15794
+ timeout: 5e3
15795
+ });
15796
+ return { available: true };
15797
+ } catch {
15798
+ return {
15799
+ available: false,
15800
+ error: createError(
15801
+ `${toolName} is not installed or not in PATH`,
15802
+ `Install ${toolName} and try again`
15803
+ )
15804
+ };
15805
+ }
15806
+ }
15807
+ }
15808
+ getCached(toolName) {
15809
+ const timestamp = this.cacheTimestamps.get(toolName);
15810
+ if (!timestamp) return null;
15811
+ if (Date.now() - timestamp > this.cacheTimeout) {
15812
+ this.cache.delete(toolName);
15813
+ this.cacheTimestamps.delete(toolName);
15814
+ return null;
15815
+ }
15816
+ return this.cache.get(toolName) || null;
15817
+ }
15818
+ setCache(toolName, status) {
15819
+ this.cache.set(toolName, status);
15820
+ this.cacheTimestamps.set(toolName, Date.now());
15821
+ }
15822
+ };
15823
+ DependencyError = class extends Error {
15824
+ static {
15825
+ __name(this, "DependencyError");
15826
+ }
15827
+ hint;
15828
+ docs;
15829
+ constructor(error) {
15830
+ super(error.message);
15831
+ this.name = "DependencyError";
15832
+ this.hint = error.hint;
15833
+ this.docs = error.docs;
15834
+ }
15835
+ };
15836
+ dependencyValidator = new DependencyValidator();
15837
+ }
15838
+ });
15839
+
15597
15840
  // core/services/git-analyzer.ts
15598
15841
  import { exec as exec6 } from "node:child_process";
15599
15842
  import { promisify as promisify6 } from "node:util";
@@ -15601,6 +15844,7 @@ var execAsync2;
15601
15844
  var init_git_analyzer = __esm({
15602
15845
  "core/services/git-analyzer.ts"() {
15603
15846
  "use strict";
15847
+ init_dependency_validator();
15604
15848
  execAsync2 = promisify6(exec6);
15605
15849
  }
15606
15850
  });
@@ -16758,16 +17002,16 @@ var init_onboarding = __esm({
16758
17002
  * Detect project type from file system
16759
17003
  */
16760
17004
  async detectProjectType() {
16761
- const fs49 = await import("node:fs/promises");
16762
- const path58 = await import("node:path");
17005
+ const fs50 = await import("node:fs/promises");
17006
+ const path59 = await import("node:path");
16763
17007
  try {
16764
- const files = await fs49.readdir(this.projectPath);
17008
+ const files = await fs50.readdir(this.projectPath);
16765
17009
  if (files.includes("turbo.json") || files.includes("lerna.json") || files.includes("nx.json")) {
16766
17010
  return "monorepo";
16767
17011
  }
16768
17012
  if (files.includes("package.json")) {
16769
- const pkgPath = path58.join(this.projectPath, "package.json");
16770
- const pkgContent = await fs49.readFile(pkgPath, "utf-8");
17013
+ const pkgPath = path59.join(this.projectPath, "package.json");
17014
+ const pkgContent = await fs50.readFile(pkgPath, "utf-8");
16771
17015
  const pkg = JSON.parse(pkgContent);
16772
17016
  const deps = { ...pkg.dependencies, ...pkg.devDependencies };
16773
17017
  if (pkg.bin) return "cli-tool";
@@ -16803,32 +17047,32 @@ var init_onboarding = __esm({
16803
17047
  * Detect installed AI agents from config files
16804
17048
  */
16805
17049
  async detectInstalledAgents() {
16806
- const fs49 = await import("node:fs/promises");
16807
- const path58 = await import("node:path");
17050
+ const fs50 = await import("node:fs/promises");
17051
+ const path59 = await import("node:path");
16808
17052
  const os17 = await import("node:os");
16809
17053
  const agents = [];
16810
17054
  try {
16811
- await fs49.access(path58.join(os17.homedir(), ".claude"));
17055
+ await fs50.access(path59.join(os17.homedir(), ".claude"));
16812
17056
  agents.push("claude");
16813
17057
  } catch {
16814
17058
  }
16815
17059
  try {
16816
- await fs49.access(path58.join(this.projectPath, ".cursorrules"));
17060
+ await fs50.access(path59.join(this.projectPath, ".cursorrules"));
16817
17061
  agents.push("cursor");
16818
17062
  } catch {
16819
17063
  }
16820
17064
  try {
16821
- await fs49.access(path58.join(this.projectPath, ".windsurfrules"));
17065
+ await fs50.access(path59.join(this.projectPath, ".windsurfrules"));
16822
17066
  agents.push("windsurf");
16823
17067
  } catch {
16824
17068
  }
16825
17069
  try {
16826
- await fs49.access(path58.join(this.projectPath, ".github", "copilot-instructions.md"));
17070
+ await fs50.access(path59.join(this.projectPath, ".github", "copilot-instructions.md"));
16827
17071
  agents.push("copilot");
16828
17072
  } catch {
16829
17073
  }
16830
17074
  try {
16831
- await fs49.access(path58.join(os17.homedir(), ".gemini"));
17075
+ await fs50.access(path59.join(os17.homedir(), ".gemini"));
16832
17076
  agents.push("gemini");
16833
17077
  } catch {
16834
17078
  }
@@ -16838,17 +17082,17 @@ var init_onboarding = __esm({
16838
17082
  * Detect tech stack from project files
16839
17083
  */
16840
17084
  async detectStack() {
16841
- const fs49 = await import("node:fs/promises");
16842
- const path58 = await import("node:path");
17085
+ const fs50 = await import("node:fs/promises");
17086
+ const path59 = await import("node:path");
16843
17087
  const stack = {
16844
17088
  language: "Unknown",
16845
17089
  technologies: []
16846
17090
  };
16847
17091
  try {
16848
- const files = await fs49.readdir(this.projectPath);
17092
+ const files = await fs50.readdir(this.projectPath);
16849
17093
  if (files.includes("package.json")) {
16850
- const pkgPath = path58.join(this.projectPath, "package.json");
16851
- const pkgContent = await fs49.readFile(pkgPath, "utf-8");
17094
+ const pkgPath = path59.join(this.projectPath, "package.json");
17095
+ const pkgContent = await fs50.readFile(pkgPath, "utf-8");
16852
17096
  const pkg = JSON.parse(pkgContent);
16853
17097
  const deps = { ...pkg.dependencies, ...pkg.devDependencies };
16854
17098
  stack.language = deps.typescript ? "TypeScript" : "JavaScript";
@@ -18944,8 +19188,8 @@ Generated: ${(/* @__PURE__ */ new Date()).toLocaleString()}
18944
19188
  const globalPath2 = path_manager_default.getGlobalProjectPath(projectId);
18945
19189
  const specsPath2 = path37.join(globalPath2, "planning", "specs");
18946
19190
  try {
18947
- const fs49 = await import("node:fs/promises");
18948
- const files = await fs49.readdir(specsPath2);
19191
+ const fs50 = await import("node:fs/promises");
19192
+ const files = await fs50.readdir(specsPath2);
18949
19193
  const specs = files.filter((f) => f.endsWith(".md") && f !== ".gitkeep");
18950
19194
  if (specs.length === 0) {
18951
19195
  output_default.warn("no specs yet");
@@ -19567,7 +19811,7 @@ var init_formatters = __esm({
19567
19811
  });
19568
19812
 
19569
19813
  // core/ai-tools/registry.ts
19570
- import { execSync as execSync4 } from "node:child_process";
19814
+ import { execSync as execSync5 } from "node:child_process";
19571
19815
  import fs37 from "node:fs";
19572
19816
  import os11 from "node:os";
19573
19817
  import path39 from "node:path";
@@ -19576,7 +19820,7 @@ function getAIToolConfig(id) {
19576
19820
  }
19577
19821
  function commandExists(cmd) {
19578
19822
  try {
19579
- execSync4(`which ${cmd}`, { stdio: "ignore" });
19823
+ execSync5(`which ${cmd}`, { stdio: "ignore" });
19580
19824
  return true;
19581
19825
  } catch {
19582
19826
  return false;
@@ -20088,9 +20332,125 @@ Load from \`~/.prjct-cli/projects/${this.config.projectId}/agents/\`:
20088
20332
  }
20089
20333
  });
20090
20334
 
20091
- // core/services/stack-detector.ts
20335
+ // core/services/local-state-generator.ts
20092
20336
  import fs40 from "node:fs/promises";
20093
20337
  import path42 from "node:path";
20338
+ var LOCAL_STATE_FILENAME, LocalStateGenerator, localStateGenerator;
20339
+ var init_local_state_generator = __esm({
20340
+ "core/services/local-state-generator.ts"() {
20341
+ "use strict";
20342
+ init_fs();
20343
+ LOCAL_STATE_FILENAME = ".prjct-state.md";
20344
+ LocalStateGenerator = class {
20345
+ static {
20346
+ __name(this, "LocalStateGenerator");
20347
+ }
20348
+ /**
20349
+ * Generate .prjct-state.md in the project root
20350
+ */
20351
+ async generate(projectPath, state) {
20352
+ const filePath = path42.join(projectPath, LOCAL_STATE_FILENAME);
20353
+ const content = this.toMarkdown(state);
20354
+ await fs40.writeFile(filePath, content, "utf-8");
20355
+ }
20356
+ /**
20357
+ * Remove local state file
20358
+ */
20359
+ async remove(projectPath) {
20360
+ const filePath = path42.join(projectPath, LOCAL_STATE_FILENAME);
20361
+ try {
20362
+ await fs40.unlink(filePath);
20363
+ } catch (error) {
20364
+ if (!isNotFoundError(error)) throw error;
20365
+ }
20366
+ }
20367
+ /**
20368
+ * Check if local state file exists
20369
+ */
20370
+ async exists(projectPath) {
20371
+ const filePath = path42.join(projectPath, LOCAL_STATE_FILENAME);
20372
+ try {
20373
+ await fs40.access(filePath);
20374
+ return true;
20375
+ } catch {
20376
+ return false;
20377
+ }
20378
+ }
20379
+ /**
20380
+ * Convert state to markdown format
20381
+ * Note: Uses runtime types since state.json has fields not in strict Zod schema
20382
+ */
20383
+ toMarkdown(state) {
20384
+ const lines = [
20385
+ "<!-- Auto-generated by prjct - DO NOT EDIT -->",
20386
+ "<!-- This file provides local state persistence for AI tools -->",
20387
+ "",
20388
+ "# prjct State",
20389
+ ""
20390
+ ];
20391
+ if (state.currentTask) {
20392
+ const task = state.currentTask;
20393
+ lines.push("## Current Task");
20394
+ lines.push("");
20395
+ lines.push(`**${task.description}**`);
20396
+ lines.push("");
20397
+ lines.push(`- Started: ${task.startedAt}`);
20398
+ if (task.linearId) {
20399
+ lines.push(`- Linear: ${task.linearId}`);
20400
+ }
20401
+ if (task.branch) {
20402
+ lines.push(`- Branch: ${task.branch}`);
20403
+ }
20404
+ lines.push(`- Status: ${task.status || "active"}`);
20405
+ lines.push("");
20406
+ if (task.subtasks && task.subtasks.length > 0) {
20407
+ lines.push("### Subtasks");
20408
+ lines.push("");
20409
+ task.subtasks.forEach((subtask, index) => {
20410
+ const statusIcon = subtask.status === "completed" ? "\u2705" : subtask.status === "in_progress" ? "\u25B6\uFE0F" : "\u23F3";
20411
+ const isActive = index === task.currentSubtaskIndex ? " \u2190 **Active**" : "";
20412
+ lines.push(`${index + 1}. ${statusIcon} ${subtask.description}${isActive}`);
20413
+ });
20414
+ lines.push("");
20415
+ const completed = task.subtasks.filter((s) => s.status === "completed").length;
20416
+ const total = task.subtasks.length;
20417
+ const percentage = Math.round(completed / total * 100);
20418
+ lines.push(`**Progress**: ${completed}/${total} (${percentage}%)`);
20419
+ lines.push("");
20420
+ }
20421
+ } else {
20422
+ lines.push("*No active task*");
20423
+ lines.push("");
20424
+ lines.push('Start a task with `p. task "description"`');
20425
+ lines.push("");
20426
+ }
20427
+ if (state.previousTask) {
20428
+ const prevTask = state.previousTask;
20429
+ lines.push("---");
20430
+ lines.push("");
20431
+ lines.push("## Previous Task");
20432
+ lines.push("");
20433
+ lines.push(`**${prevTask.description}**`);
20434
+ lines.push("");
20435
+ lines.push(`- Status: ${prevTask.status}`);
20436
+ if (prevTask.prUrl) {
20437
+ lines.push(`- PR: ${prevTask.prUrl}`);
20438
+ }
20439
+ lines.push("");
20440
+ }
20441
+ lines.push("---");
20442
+ lines.push(`*Last updated: ${state.lastUpdated || (/* @__PURE__ */ new Date()).toISOString()}*`);
20443
+ lines.push("");
20444
+ return lines.join("\n");
20445
+ }
20446
+ };
20447
+ localStateGenerator = new LocalStateGenerator();
20448
+ }
20449
+ });
20450
+
20451
+ // core/services/stack-detector.ts
20452
+ import fs41 from "node:fs/promises";
20453
+ import path43 from "node:path";
20094
20454
  var StackDetector;
20095
20455
  var init_stack_detector = __esm({
20096
20456
  "core/services/stack-detector.ts"() {
@@ -20249,8 +20609,8 @@ var init_stack_detector = __esm({
20249
20609
  */
20250
20610
  async readPackageJson() {
20251
20611
  try {
20252
- const pkgPath = path42.join(this.projectPath, "package.json");
20253
- const content = await fs40.readFile(pkgPath, "utf-8");
20612
+ const pkgPath = path43.join(this.projectPath, "package.json");
20613
+ const content = await fs41.readFile(pkgPath, "utf-8");
20254
20614
  return JSON.parse(content);
20255
20615
  } catch {
20256
20616
  return null;
@@ -20261,7 +20621,7 @@ var init_stack_detector = __esm({
20261
20621
  */
20262
20622
  async fileExists(filename) {
20263
20623
  try {
20264
- await fs40.access(path42.join(this.projectPath, filename));
20624
+ await fs41.access(path43.join(this.projectPath, filename));
20265
20625
  return true;
20266
20626
  } catch {
20267
20627
  return false;
@@ -20273,8 +20633,8 @@ var init_stack_detector = __esm({
20273
20633
 
20274
20634
  // core/services/sync-service.ts
20275
20635
  import { exec as exec11 } from "node:child_process";
20276
- import fs41 from "node:fs/promises";
20277
- import path43 from "node:path";
20636
+ import fs42 from "node:fs/promises";
20637
+ import path44 from "node:path";
20278
20638
  import { promisify as promisify11 } from "node:util";
20279
20639
  var execAsync6, SyncService, syncService;
20280
20640
  var init_sync_service = __esm({
@@ -20287,6 +20647,7 @@ var init_sync_service = __esm({
20287
20647
  init_metrics_storage();
20288
20648
  init_date_helper();
20289
20649
  init_context_generator();
20650
+ init_local_state_generator();
20290
20651
  init_stack_detector();
20291
20652
  execAsync6 = promisify11(exec11);
20292
20653
  SyncService = class {
@@ -20423,7 +20784,7 @@ var init_sync_service = __esm({
20423
20784
  async ensureDirectories() {
20424
20785
  const dirs = ["storage", "context", "agents", "memory", "analysis", "config", "sync"];
20425
20786
  await Promise.all(
20426
- dirs.map((dir) => fs41.mkdir(path43.join(this.globalPath, dir), { recursive: true }))
20787
+ dirs.map((dir) => fs42.mkdir(path44.join(this.globalPath, dir), { recursive: true }))
20427
20788
  );
20428
20789
  }
20429
20790
  // ==========================================================================
@@ -20493,7 +20854,7 @@ var init_sync_service = __esm({
20493
20854
  const stats = {
20494
20855
  fileCount: 0,
20495
20856
  version: "0.0.0",
20496
- name: path43.basename(this.projectPath),
20857
+ name: path44.basename(this.projectPath),
20497
20858
  ecosystem: "unknown",
20498
20859
  projectType: "simple",
20499
20860
  languages: [],
@@ -20509,8 +20870,8 @@ var init_sync_service = __esm({
20509
20870
  stats.fileCount = 0;
20510
20871
  }
20511
20872
  try {
20512
- const pkgPath = path43.join(this.projectPath, "package.json");
20513
- const pkg = JSON.parse(await fs41.readFile(pkgPath, "utf-8"));
20873
+ const pkgPath = path44.join(this.projectPath, "package.json");
20874
+ const pkg = JSON.parse(await fs42.readFile(pkgPath, "utf-8"));
20514
20875
  stats.version = pkg.version || "0.0.0";
20515
20876
  stats.name = pkg.name || stats.name;
20516
20877
  stats.ecosystem = "JavaScript";
@@ -20618,12 +20979,12 @@ var init_sync_service = __esm({
20618
20979
  // ==========================================================================
20619
20980
  async generateAgents(stack, stats) {
20620
20981
  const agents = [];
20621
- const agentsPath = path43.join(this.globalPath, "agents");
20982
+ const agentsPath = path44.join(this.globalPath, "agents");
20622
20983
  try {
20623
- const files = await fs41.readdir(agentsPath);
20984
+ const files = await fs42.readdir(agentsPath);
20624
20985
  for (const file of files) {
20625
20986
  if (file.endsWith(".md")) {
20626
- await fs41.unlink(path43.join(agentsPath, file));
20987
+ await fs42.unlink(path44.join(agentsPath, file));
20627
20988
  }
20628
20989
  }
20629
20990
  } catch {
@@ -20663,7 +21024,7 @@ var init_sync_service = __esm({
20663
21024
  async generateWorkflowAgent(name, agentsPath) {
20664
21025
  let content = "";
20665
21026
  try {
20666
- const templatePath = path43.join(
21027
+ const templatePath = path44.join(
20667
21028
  __dirname,
20668
21029
  "..",
20669
21030
  "..",
@@ -20672,16 +21033,16 @@ var init_sync_service = __esm({
20672
21033
  "workflow",
20673
21034
  `${name}.md`
20674
21035
  );
20675
- content = await fs41.readFile(templatePath, "utf-8");
21036
+ content = await fs42.readFile(templatePath, "utf-8");
20676
21037
  } catch {
20677
21038
  content = this.generateMinimalWorkflowAgent(name);
20678
21039
  }
20679
- await fs41.writeFile(path43.join(agentsPath, `${name}.md`), content, "utf-8");
21040
+ await fs42.writeFile(path44.join(agentsPath, `${name}.md`), content, "utf-8");
20680
21041
  }
20681
21042
  async generateDomainAgent(name, agentsPath, stats, stack) {
20682
21043
  let content = "";
20683
21044
  try {
20684
- const templatePath = path43.join(
21045
+ const templatePath = path44.join(
20685
21046
  __dirname,
20686
21047
  "..",
20687
21048
  "..",
@@ -20690,14 +21051,14 @@ var init_sync_service = __esm({
20690
21051
  "domain",
20691
21052
  `${name}.md`
20692
21053
  );
20693
- content = await fs41.readFile(templatePath, "utf-8");
21054
+ content = await fs42.readFile(templatePath, "utf-8");
20694
21055
  content = content.replace("{projectName}", stats.name);
20695
21056
  content = content.replace("{frameworks}", stack.frameworks.join(", ") || "None detected");
20696
21057
  content = content.replace("{ecosystem}", stats.ecosystem);
20697
21058
  } catch {
20698
21059
  content = this.generateMinimalDomainAgent(name, stats, stack);
20699
21060
  }
20700
- await fs41.writeFile(path43.join(agentsPath, `${name}.md`), content, "utf-8");
21061
+ await fs42.writeFile(path44.join(agentsPath, `${name}.md`), content, "utf-8");
20701
21062
  }
20702
21063
  generateMinimalWorkflowAgent(name) {
20703
21064
  const descriptions = {
@@ -20765,8 +21126,8 @@ You are the ${name} expert for this project. Apply best practices for the detect
20765
21126
  })),
20766
21127
  agentSkillMap: Object.fromEntries(skills.map((s) => [s.agent, s.skill]))
20767
21128
  };
20768
- fs41.writeFile(
20769
- path43.join(this.globalPath, "config", "skills.json"),
21129
+ fs42.writeFile(
21130
+ path44.join(this.globalPath, "config", "skills.json"),
20770
21131
  JSON.stringify(skillsConfig, null, 2),
20771
21132
  "utf-8"
20772
21133
  ).catch(() => {
@@ -20788,10 +21149,10 @@ You are the ${name} expert for this project. Apply best practices for the detect
20788
21149
  // PROJECT.JSON UPDATE
20789
21150
  // ==========================================================================
20790
21151
  async updateProjectJson(git, stats) {
20791
- const projectJsonPath = path43.join(this.globalPath, "project.json");
21152
+ const projectJsonPath = path44.join(this.globalPath, "project.json");
20792
21153
  let existing = {};
20793
21154
  try {
20794
- existing = JSON.parse(await fs41.readFile(projectJsonPath, "utf-8"));
21155
+ existing = JSON.parse(await fs42.readFile(projectJsonPath, "utf-8"));
20795
21156
  } catch {
20796
21157
  }
20797
21158
  const updated = {
@@ -20813,16 +21174,16 @@ You are the ${name} expert for this project. Apply best practices for the detect
20813
21174
  lastSyncCommit: git.recentCommits[0]?.hash || null,
20814
21175
  lastSyncBranch: git.branch
20815
21176
  };
20816
- await fs41.writeFile(projectJsonPath, JSON.stringify(updated, null, 2), "utf-8");
21177
+ await fs42.writeFile(projectJsonPath, JSON.stringify(updated, null, 2), "utf-8");
20817
21178
  }
20818
21179
  // ==========================================================================
20819
21180
  // STATE.JSON UPDATE
20820
21181
  // ==========================================================================
20821
21182
  async updateStateJson(stats, stack) {
20822
- const statePath = path43.join(this.globalPath, "storage", "state.json");
21183
+ const statePath = path44.join(this.globalPath, "storage", "state.json");
20823
21184
  let state = {};
20824
21185
  try {
20825
- state = JSON.parse(await fs41.readFile(statePath, "utf-8"));
21186
+ state = JSON.parse(await fs42.readFile(statePath, "utf-8"));
20826
21187
  } catch {
20827
21188
  }
20828
21189
  state.projectId = this.projectId;
@@ -20849,13 +21210,20 @@ You are the ${name} expert for this project. Apply best practices for the detect
20849
21210
  lastAction: "Synced project",
20850
21211
  nextAction: 'Run `p. task "description"` to start working'
20851
21212
  };
20852
- await fs41.writeFile(statePath, JSON.stringify(state, null, 2), "utf-8");
21213
+ await fs42.writeFile(statePath, JSON.stringify(state, null, 2), "utf-8");
21214
+ try {
21215
+ await localStateGenerator.generate(
21216
+ this.projectPath,
21217
+ state
21218
+ );
21219
+ } catch {
21220
+ }
20853
21221
  }
20854
21222
  // ==========================================================================
20855
21223
  // MEMORY LOGGING
20856
21224
  // ==========================================================================
20857
21225
  async logToMemory(git, stats) {
20858
- const memoryPath = path43.join(this.globalPath, "memory", "events.jsonl");
21226
+ const memoryPath = path44.join(this.globalPath, "memory", "events.jsonl");
20859
21227
  const event = {
20860
21228
  ts: date_helper_default.getTimestamp(),
20861
21229
  action: "sync",
@@ -20864,7 +21232,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
20864
21232
  fileCount: stats.fileCount,
20865
21233
  commitCount: git.commits
20866
21234
  };
20867
- await fs41.appendFile(memoryPath, `${JSON.stringify(event)}
21235
+ await fs42.appendFile(memoryPath, `${JSON.stringify(event)}
20868
21236
  `, "utf-8");
20869
21237
  }
20870
21238
  // ==========================================================================
@@ -20884,16 +21252,16 @@ You are the ${name} expert for this project. Apply best practices for the detect
20884
21252
  let filteredChars = 0;
20885
21253
  for (const file of contextFiles) {
20886
21254
  try {
20887
- const filePath = path43.join(this.globalPath, file);
20888
- const content = await fs41.readFile(filePath, "utf-8");
21255
+ const filePath = path44.join(this.globalPath, file);
21256
+ const content = await fs42.readFile(filePath, "utf-8");
20889
21257
  filteredChars += content.length;
20890
21258
  } catch {
20891
21259
  }
20892
21260
  }
20893
21261
  for (const agent of agents) {
20894
21262
  try {
20895
- const agentPath = path43.join(this.globalPath, "agents", `${agent.name}.md`);
20896
- const content = await fs41.readFile(agentPath, "utf-8");
21263
+ const agentPath = path44.join(this.globalPath, "agents", `${agent.name}.md`);
21264
+ const content = await fs42.readFile(agentPath, "utf-8");
20897
21265
  filteredChars += content.length;
20898
21266
  } catch {
20899
21267
  }
@@ -20925,7 +21293,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
20925
21293
  // ==========================================================================
20926
21294
  async fileExists(filename) {
20927
21295
  try {
20928
- await fs41.access(path43.join(this.projectPath, filename));
21296
+ await fs42.access(path44.join(this.projectPath, filename));
20929
21297
  return true;
20930
21298
  } catch {
20931
21299
  return false;
@@ -20933,8 +21301,8 @@ You are the ${name} expert for this project. Apply best practices for the detect
20933
21301
  }
20934
21302
  async getCliVersion() {
20935
21303
  try {
20936
- const pkgPath = path43.join(__dirname, "..", "..", "package.json");
20937
- const pkg = JSON.parse(await fs41.readFile(pkgPath, "utf-8"));
21304
+ const pkgPath = path44.join(__dirname, "..", "..", "package.json");
21305
+ const pkg = JSON.parse(await fs42.readFile(pkgPath, "utf-8"));
20938
21306
  return pkg.version || "0.0.0";
20939
21307
  } catch {
20940
21308
  return "0.0.0";
@@ -21093,24 +21461,24 @@ __export(uninstall_exports, {
21093
21461
  UninstallCommands: () => UninstallCommands,
21094
21462
  uninstall: () => uninstall
21095
21463
  });
21096
- import { execSync as execSync5 } from "node:child_process";
21464
+ import { execSync as execSync6 } from "node:child_process";
21097
21465
  import fsSync2 from "node:fs";
21098
- import fs42 from "node:fs/promises";
21466
+ import fs43 from "node:fs/promises";
21099
21467
  import os12 from "node:os";
21100
- import path44 from "node:path";
21468
+ import path45 from "node:path";
21101
21469
  import readline2 from "node:readline";
21102
21470
  import chalk9 from "chalk";
21103
21471
  async function getDirectorySize(dirPath) {
21104
21472
  let totalSize = 0;
21105
21473
  try {
21106
- const entries = await fs42.readdir(dirPath, { withFileTypes: true });
21474
+ const entries = await fs43.readdir(dirPath, { withFileTypes: true });
21107
21475
  for (const entry of entries) {
21108
- const entryPath = path44.join(dirPath, entry.name);
21476
+ const entryPath = path45.join(dirPath, entry.name);
21109
21477
  if (entry.isDirectory()) {
21110
21478
  totalSize += await getDirectorySize(entryPath);
21111
21479
  } else {
21112
21480
  try {
21113
- const stats = await fs42.stat(entryPath);
21481
+ const stats = await fs43.stat(entryPath);
21114
21482
  totalSize += stats.size;
21115
21483
  } catch {
21116
21484
  }
@@ -21129,7 +21497,7 @@ function formatSize(bytes) {
21129
21497
  }
21130
21498
  async function countDirectoryItems(dirPath) {
21131
21499
  try {
21132
- const entries = await fs42.readdir(dirPath, { withFileTypes: true });
21500
+ const entries = await fs43.readdir(dirPath, { withFileTypes: true });
21133
21501
  return entries.filter((e) => e.isDirectory()).length;
21134
21502
  } catch {
21135
21503
  return 0;
@@ -21141,7 +21509,7 @@ function detectInstallation() {
21141
21509
  npm: false
21142
21510
  };
21143
21511
  try {
21144
- const result = execSync5("brew list prjct-cli 2>/dev/null", { encoding: "utf-8" });
21512
+ const result = execSync6("brew list prjct-cli 2>/dev/null", { encoding: "utf-8" });
21145
21513
  if (result) {
21146
21514
  info.homebrew = true;
21147
21515
  info.homebrewFormula = "prjct-cli";
@@ -21149,7 +21517,7 @@ function detectInstallation() {
21149
21517
  } catch {
21150
21518
  }
21151
21519
  try {
21152
- const result = execSync5("npm list -g prjct-cli --depth=0 2>/dev/null", { encoding: "utf-8" });
21520
+ const result = execSync6("npm list -g prjct-cli --depth=0 2>/dev/null", { encoding: "utf-8" });
21153
21521
  if (result.includes("prjct-cli")) {
21154
21522
  info.npm = true;
21155
21523
  }
@@ -21162,7 +21530,7 @@ async function gatherUninstallItems() {
21162
21530
  const providerPaths = getProviderPaths();
21163
21531
  const prjctCliPath = path_manager_default.getGlobalBasePath();
21164
21532
  const prjctCliExists = fsSync2.existsSync(prjctCliPath);
21165
- const projectCount = prjctCliExists ? await countDirectoryItems(path44.join(prjctCliPath, "projects")) : 0;
21533
+ const projectCount = prjctCliExists ? await countDirectoryItems(path45.join(prjctCliPath, "projects")) : 0;
21166
21534
  const prjctCliSize = prjctCliExists ? await getDirectorySize(prjctCliPath) : 0;
21167
21535
  items.push({
21168
21536
  path: prjctCliPath,
@@ -21172,7 +21540,7 @@ async function gatherUninstallItems() {
21172
21540
  count: projectCount,
21173
21541
  exists: prjctCliExists
21174
21542
  });
21175
- const claudeMdPath = path44.join(providerPaths.claude.config, "CLAUDE.md");
21543
+ const claudeMdPath = path45.join(providerPaths.claude.config, "CLAUDE.md");
21176
21544
  const claudeMdExists = fsSync2.existsSync(claudeMdPath);
21177
21545
  let hasPrjctSection = false;
21178
21546
  if (claudeMdExists) {
@@ -21206,7 +21574,7 @@ async function gatherUninstallItems() {
21206
21574
  description: "Claude router",
21207
21575
  exists: claudeRouterExists
21208
21576
  });
21209
- const statusLinePath = path44.join(providerPaths.claude.config, "prjct-statusline.sh");
21577
+ const statusLinePath = path45.join(providerPaths.claude.config, "prjct-statusline.sh");
21210
21578
  const statusLineExists = fsSync2.existsSync(statusLinePath);
21211
21579
  items.push({
21212
21580
  path: statusLinePath,
@@ -21222,7 +21590,7 @@ async function gatherUninstallItems() {
21222
21590
  description: "Gemini router",
21223
21591
  exists: geminiRouterExists
21224
21592
  });
21225
- const geminiMdPath = path44.join(providerPaths.gemini.config, "GEMINI.md");
21593
+ const geminiMdPath = path45.join(providerPaths.gemini.config, "GEMINI.md");
21226
21594
  const geminiMdExists = fsSync2.existsSync(geminiMdPath);
21227
21595
  let hasGeminiPrjctSection = false;
21228
21596
  if (geminiMdExists) {
@@ -21244,7 +21612,7 @@ async function gatherUninstallItems() {
21244
21612
  }
21245
21613
  async function removePrjctSection(filePath) {
21246
21614
  try {
21247
- const content = await fs42.readFile(filePath, "utf-8");
21615
+ const content = await fs43.readFile(filePath, "utf-8");
21248
21616
  if (!content.includes(PRJCT_START_MARKER) || !content.includes(PRJCT_END_MARKER)) {
21249
21617
  return false;
21250
21618
  }
@@ -21253,9 +21621,9 @@ async function removePrjctSection(filePath) {
21253
21621
  let newContent = content.substring(0, startIndex) + content.substring(endIndex);
21254
21622
  newContent = newContent.replace(/\n{3,}/g, "\n\n").trim();
21255
21623
  if (!newContent || newContent.trim().length === 0) {
21256
- await fs42.unlink(filePath);
21624
+ await fs43.unlink(filePath);
21257
21625
  } else {
21258
- await fs42.writeFile(filePath, `${newContent}
21626
+ await fs43.writeFile(filePath, `${newContent}
21259
21627
  `, "utf-8");
21260
21628
  }
21261
21629
  return true;
@@ -21266,12 +21634,12 @@ async function removePrjctSection(filePath) {
21266
21634
  async function createBackup() {
21267
21635
  const homeDir = os12.homedir();
21268
21636
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").substring(0, 19);
21269
- const backupDir = path44.join(homeDir, `.prjct-backup-${timestamp}`);
21637
+ const backupDir = path45.join(homeDir, `.prjct-backup-${timestamp}`);
21270
21638
  try {
21271
- await fs42.mkdir(backupDir, { recursive: true });
21639
+ await fs43.mkdir(backupDir, { recursive: true });
21272
21640
  const prjctCliPath = path_manager_default.getGlobalBasePath();
21273
21641
  if (fsSync2.existsSync(prjctCliPath)) {
21274
- await copyDirectory(prjctCliPath, path44.join(backupDir, ".prjct-cli"));
21642
+ await copyDirectory(prjctCliPath, path45.join(backupDir, ".prjct-cli"));
21275
21643
  }
21276
21644
  return backupDir;
21277
21645
  } catch {
@@ -21279,15 +21647,15 @@ async function createBackup() {
21279
21647
  }
21280
21648
  }
21281
21649
  async function copyDirectory(src, dest) {
21282
- await fs42.mkdir(dest, { recursive: true });
21283
- const entries = await fs42.readdir(src, { withFileTypes: true });
21650
+ await fs43.mkdir(dest, { recursive: true });
21651
+ const entries = await fs43.readdir(src, { withFileTypes: true });
21284
21652
  for (const entry of entries) {
21285
- const srcPath = path44.join(src, entry.name);
21286
- const destPath = path44.join(dest, entry.name);
21653
+ const srcPath = path45.join(src, entry.name);
21654
+ const destPath = path45.join(dest, entry.name);
21287
21655
  if (entry.isDirectory()) {
21288
21656
  await copyDirectory(srcPath, destPath);
21289
21657
  } else {
21290
- await fs42.copyFile(srcPath, destPath);
21658
+ await fs43.copyFile(srcPath, destPath);
21291
21659
  }
21292
21660
  }
21293
21661
  }
@@ -21303,10 +21671,10 @@ async function performUninstall(items, installation, options) {
21303
21671
  deleted.push(item.path);
21304
21672
  }
21305
21673
  } else if (item.type === "directory") {
21306
- await fs42.rm(item.path, { recursive: true, force: true });
21674
+ await fs43.rm(item.path, { recursive: true, force: true });
21307
21675
  deleted.push(item.path);
21308
21676
  } else if (item.type === "file") {
21309
- await fs42.unlink(item.path);
21677
+ await fs43.unlink(item.path);
21310
21678
  deleted.push(item.path);
21311
21679
  }
21312
21680
  } catch (error) {
@@ -21317,7 +21685,7 @@ async function performUninstall(items, installation, options) {
21317
21685
  if (installation.homebrew && installation.homebrewFormula) {
21318
21686
  try {
21319
21687
  if (!options.dryRun) {
21320
- execSync5(`brew uninstall ${installation.homebrewFormula}`, { stdio: "pipe" });
21688
+ execSync6(`brew uninstall ${installation.homebrewFormula}`, { stdio: "pipe" });
21321
21689
  }
21322
21690
  deleted.push("Homebrew: prjct-cli");
21323
21691
  } catch (error) {
@@ -21327,7 +21695,7 @@ async function performUninstall(items, installation, options) {
21327
21695
  if (installation.npm) {
21328
21696
  try {
21329
21697
  if (!options.dryRun) {
21330
- execSync5("npm uninstall -g prjct-cli", { stdio: "pipe" });
21698
+ execSync6("npm uninstall -g prjct-cli", { stdio: "pipe" });
21331
21699
  }
21332
21700
  deleted.push("npm: prjct-cli");
21333
21701
  } catch (error) {
@@ -21481,7 +21849,7 @@ __export(watch_service_exports, {
21481
21849
  WatchService: () => WatchService,
21482
21850
  watchService: () => watchService
21483
21851
  });
21484
- import path45 from "node:path";
21852
+ import path46 from "node:path";
21485
21853
  import chalk10 from "chalk";
21486
21854
  import chokidar from "chokidar";
21487
21855
  var TRIGGER_PATTERNS, IGNORE_PATTERNS2, WatchService, watchService;
@@ -21686,7 +22054,7 @@ ${chalk10.dim(`[${timestamp}]`)} ${chalk10.cyan("\u27F3")} ${filesSummary} chang
21686
22054
  printStartup() {
21687
22055
  console.log("");
21688
22056
  console.log(chalk10.cyan("\u{1F441}\uFE0F Watching for changes..."));
21689
- console.log(chalk10.dim(` Project: ${path45.basename(this.projectPath)}`));
22057
+ console.log(chalk10.dim(` Project: ${path46.basename(this.projectPath)}`));
21690
22058
  console.log(chalk10.dim(` Debounce: ${this.options.debounceMs}ms`));
21691
22059
  console.log(chalk10.dim(` Min interval: ${this.options.minIntervalMs / 1e3}s`));
21692
22060
  console.log("");
@@ -22358,16 +22726,28 @@ __export(setup_exports, {
22358
22726
  needsWindsurfRegeneration: () => needsWindsurfRegeneration,
22359
22727
  run: () => run
22360
22728
  });
22361
- import { execSync as execSync6 } from "node:child_process";
22362
- import fs43 from "node:fs";
22729
+ import { execSync as execSync7 } from "node:child_process";
22730
+ import fs44 from "node:fs";
22363
22731
  import os13 from "node:os";
22364
- import path46 from "node:path";
22732
+ import path47 from "node:path";
22365
22733
  async function installAICLI(provider) {
22366
22734
  const packageName = provider.name === "claude" ? "@anthropic-ai/claude-code" : "@google/gemini-cli";
22735
+ if (!dependencyValidator.isAvailable("npm")) {
22736
+ console.log(`${YELLOW4}\u26A0\uFE0F npm is not available${NC}`);
22737
+ console.log("");
22738
+ console.log(`${DIM4}Install ${provider.displayName} using one of:${NC}`);
22739
+ console.log(`${DIM4} \u2022 Install Node.js: https://nodejs.org${NC}`);
22740
+ console.log(
22741
+ `${DIM4} \u2022 Use Homebrew: brew install ${provider.name === "claude" ? "claude" : "gemini"}${NC}`
22742
+ );
22743
+ console.log(`${DIM4} \u2022 Use npx directly: npx ${packageName}${NC}`);
22744
+ console.log("");
22745
+ return false;
22746
+ }
22367
22747
  try {
22368
22748
  console.log(`${YELLOW4}\u{1F4E6} ${provider.displayName} not found. Installing...${NC}`);
22369
22749
  console.log("");
22370
- execSync6(`npm install -g ${packageName}`, { stdio: "inherit" });
22750
+ execSync7(`npm install -g ${packageName}`, { stdio: "inherit" });
22371
22751
  console.log("");
22372
22752
  console.log(`${GREEN4}\u2713${NC} ${provider.displayName} installed successfully`);
22373
22753
  console.log("");
@@ -22376,7 +22756,14 @@ async function installAICLI(provider) {
22376
22756
  console.log(
22377
22757
  `${YELLOW4}\u26A0\uFE0F Failed to install ${provider.displayName}: ${error.message}${NC}`
22378
22758
  );
22379
- console.log(`${DIM4}Please install manually: npm install -g ${packageName}${NC}`);
22759
+ console.log("");
22760
+ console.log(`${DIM4}Alternative installation methods:${NC}`);
22761
+ console.log(`${DIM4} \u2022 npm: npm install -g ${packageName}${NC}`);
22762
+ console.log(`${DIM4} \u2022 yarn: yarn global add ${packageName}${NC}`);
22763
+ console.log(`${DIM4} \u2022 pnpm: pnpm add -g ${packageName}${NC}`);
22764
+ console.log(
22765
+ `${DIM4} \u2022 brew: brew install ${provider.name === "claude" ? "claude" : "gemini"}${NC}`
22766
+ );
22380
22767
  console.log("");
22381
22768
  return false;
22382
22769
  }
@@ -22467,12 +22854,12 @@ async function run() {
22467
22854
  }
22468
22855
  async function installGeminiRouter() {
22469
22856
  try {
22470
- const geminiCommandsDir = path46.join(os13.homedir(), ".gemini", "commands");
22471
- const routerSource = path46.join(getPackageRoot(), "templates", "commands", "p.toml");
22472
- const routerDest = path46.join(geminiCommandsDir, "p.toml");
22473
- fs43.mkdirSync(geminiCommandsDir, { recursive: true });
22474
- if (fs43.existsSync(routerSource)) {
22475
- fs43.copyFileSync(routerSource, routerDest);
22857
+ const geminiCommandsDir = path47.join(os13.homedir(), ".gemini", "commands");
22858
+ const routerSource = path47.join(getPackageRoot(), "templates", "commands", "p.toml");
22859
+ const routerDest = path47.join(geminiCommandsDir, "p.toml");
22860
+ fs44.mkdirSync(geminiCommandsDir, { recursive: true });
22861
+ if (fs44.existsSync(routerSource)) {
22862
+ fs44.copyFileSync(routerSource, routerDest);
22476
22863
  return true;
22477
22864
  }
22478
22865
  return false;
@@ -22483,15 +22870,15 @@ async function installGeminiRouter() {
22483
22870
  }
22484
22871
  async function installGeminiGlobalConfig() {
22485
22872
  try {
22486
- const geminiDir = path46.join(os13.homedir(), ".gemini");
22487
- const globalConfigPath = path46.join(geminiDir, "GEMINI.md");
22488
- const templatePath = path46.join(getPackageRoot(), "templates", "global", "GEMINI.md");
22489
- fs43.mkdirSync(geminiDir, { recursive: true });
22490
- const templateContent = fs43.readFileSync(templatePath, "utf-8");
22873
+ const geminiDir = path47.join(os13.homedir(), ".gemini");
22874
+ const globalConfigPath = path47.join(geminiDir, "GEMINI.md");
22875
+ const templatePath = path47.join(getPackageRoot(), "templates", "global", "GEMINI.md");
22876
+ fs44.mkdirSync(geminiDir, { recursive: true });
22877
+ const templateContent = fs44.readFileSync(templatePath, "utf-8");
22491
22878
  let existingContent = "";
22492
22879
  let fileExists2 = false;
22493
22880
  try {
22494
- existingContent = fs43.readFileSync(globalConfigPath, "utf-8");
22881
+ existingContent = fs44.readFileSync(globalConfigPath, "utf-8");
22495
22882
  fileExists2 = true;
22496
22883
  } catch (error) {
22497
22884
  if (isNotFoundError(error)) {
@@ -22501,7 +22888,7 @@ async function installGeminiGlobalConfig() {
22501
22888
  }
22502
22889
  }
22503
22890
  if (!fileExists2) {
22504
- fs43.writeFileSync(globalConfigPath, templateContent, "utf-8");
22891
+ fs44.writeFileSync(globalConfigPath, templateContent, "utf-8");
22505
22892
  return { success: true, action: "created" };
22506
22893
  }
22507
22894
  const startMarker = "<!-- prjct:start - DO NOT REMOVE THIS MARKER -->";
@@ -22511,7 +22898,7 @@ async function installGeminiGlobalConfig() {
22511
22898
  const updatedContent2 = `${existingContent}
22512
22899
 
22513
22900
  ${templateContent}`;
22514
- fs43.writeFileSync(globalConfigPath, updatedContent2, "utf-8");
22901
+ fs44.writeFileSync(globalConfigPath, updatedContent2, "utf-8");
22515
22902
  return { success: true, action: "appended" };
22516
22903
  }
22517
22904
  const beforeMarker = existingContent.substring(0, existingContent.indexOf(startMarker));
@@ -22523,7 +22910,7 @@ ${templateContent}`;
22523
22910
  templateContent.indexOf(endMarker) + endMarker.length
22524
22911
  );
22525
22912
  const updatedContent = beforeMarker + prjctSection + afterMarker;
22526
- fs43.writeFileSync(globalConfigPath, updatedContent, "utf-8");
22913
+ fs44.writeFileSync(globalConfigPath, updatedContent, "utf-8");
22527
22914
  return { success: true, action: "updated" };
22528
22915
  } catch (error) {
22529
22916
  console.error(`Gemini config warning: ${error.message}`);
@@ -22532,18 +22919,18 @@ ${templateContent}`;
22532
22919
  }
22533
22920
  async function installAntigravitySkill() {
22534
22921
  try {
22535
- const antigravitySkillsDir = path46.join(os13.homedir(), ".gemini", "antigravity", "skills");
22536
- const prjctSkillDir = path46.join(antigravitySkillsDir, "prjct");
22537
- const skillMdPath = path46.join(prjctSkillDir, "SKILL.md");
22538
- const templatePath = path46.join(getPackageRoot(), "templates", "antigravity", "SKILL.md");
22539
- fs43.mkdirSync(prjctSkillDir, { recursive: true });
22540
- const fileExists2 = fs43.existsSync(skillMdPath);
22541
- if (!fs43.existsSync(templatePath)) {
22922
+ const antigravitySkillsDir = path47.join(os13.homedir(), ".gemini", "antigravity", "skills");
22923
+ const prjctSkillDir = path47.join(antigravitySkillsDir, "prjct");
22924
+ const skillMdPath = path47.join(prjctSkillDir, "SKILL.md");
22925
+ const templatePath = path47.join(getPackageRoot(), "templates", "antigravity", "SKILL.md");
22926
+ fs44.mkdirSync(prjctSkillDir, { recursive: true });
22927
+ const fileExists2 = fs44.existsSync(skillMdPath);
22928
+ if (!fs44.existsSync(templatePath)) {
22542
22929
  console.error("Antigravity SKILL.md template not found");
22543
22930
  return { success: false, action: null };
22544
22931
  }
22545
- const templateContent = fs43.readFileSync(templatePath, "utf-8");
22546
- fs43.writeFileSync(skillMdPath, templateContent, "utf-8");
22932
+ const templateContent = fs44.readFileSync(templatePath, "utf-8");
22933
+ fs44.writeFileSync(skillMdPath, templateContent, "utf-8");
22547
22934
  return { success: true, action: fileExists2 ? "updated" : "created" };
22548
22935
  } catch (error) {
22549
22936
  console.error(`Antigravity skill warning: ${error.message}`);
@@ -22562,24 +22949,24 @@ async function installCursorProject(projectRoot) {
22562
22949
  gitignoreUpdated: false
22563
22950
  };
22564
22951
  try {
22565
- const cursorDir = path46.join(projectRoot, ".cursor");
22566
- const rulesDir = path46.join(cursorDir, "rules");
22567
- const commandsDir = path46.join(cursorDir, "commands");
22568
- const routerMdcDest = path46.join(rulesDir, "prjct.mdc");
22569
- const routerMdcSource = path46.join(getPackageRoot(), "templates", "cursor", "router.mdc");
22570
- const cursorCommandsSource = path46.join(getPackageRoot(), "templates", "cursor", "commands");
22571
- fs43.mkdirSync(rulesDir, { recursive: true });
22572
- fs43.mkdirSync(commandsDir, { recursive: true });
22573
- if (fs43.existsSync(routerMdcSource)) {
22574
- fs43.copyFileSync(routerMdcSource, routerMdcDest);
22952
+ const cursorDir = path47.join(projectRoot, ".cursor");
22953
+ const rulesDir = path47.join(cursorDir, "rules");
22954
+ const commandsDir = path47.join(cursorDir, "commands");
22955
+ const routerMdcDest = path47.join(rulesDir, "prjct.mdc");
22956
+ const routerMdcSource = path47.join(getPackageRoot(), "templates", "cursor", "router.mdc");
22957
+ const cursorCommandsSource = path47.join(getPackageRoot(), "templates", "cursor", "commands");
22958
+ fs44.mkdirSync(rulesDir, { recursive: true });
22959
+ fs44.mkdirSync(commandsDir, { recursive: true });
22960
+ if (fs44.existsSync(routerMdcSource)) {
22961
+ fs44.copyFileSync(routerMdcSource, routerMdcDest);
22575
22962
  result.rulesCreated = true;
22576
22963
  }
22577
- if (fs43.existsSync(cursorCommandsSource)) {
22578
- const commandFiles = fs43.readdirSync(cursorCommandsSource).filter((f) => f.endsWith(".md"));
22964
+ if (fs44.existsSync(cursorCommandsSource)) {
22965
+ const commandFiles = fs44.readdirSync(cursorCommandsSource).filter((f) => f.endsWith(".md"));
22579
22966
  for (const file of commandFiles) {
22580
- const src = path46.join(cursorCommandsSource, file);
22581
- const dest = path46.join(commandsDir, file);
22582
- fs43.copyFileSync(src, dest);
22967
+ const src = path47.join(cursorCommandsSource, file);
22968
+ const dest = path47.join(commandsDir, file);
22969
+ fs44.copyFileSync(src, dest);
22583
22970
  }
22584
22971
  result.commandsCreated = commandFiles.length > 0;
22585
22972
  }
@@ -22593,7 +22980,7 @@ async function installCursorProject(projectRoot) {
22593
22980
  }
22594
22981
  async function addCursorToGitignore(projectRoot) {
22595
22982
  try {
22596
- const gitignorePath = path46.join(projectRoot, ".gitignore");
22983
+ const gitignorePath = path47.join(projectRoot, ".gitignore");
22597
22984
  const entriesToAdd = [
22598
22985
  "# prjct Cursor routers (regenerated per-developer)",
22599
22986
  ".cursor/rules/prjct.mdc",
@@ -22608,7 +22995,7 @@ async function addCursorToGitignore(projectRoot) {
22608
22995
  let content = "";
22609
22996
  let fileExists2 = false;
22610
22997
  try {
22611
- content = fs43.readFileSync(gitignorePath, "utf-8");
22998
+ content = fs44.readFileSync(gitignorePath, "utf-8");
22612
22999
  fileExists2 = true;
22613
23000
  } catch (error) {
22614
23001
  if (!isNotFoundError(error)) {
@@ -22623,7 +23010,7 @@ async function addCursorToGitignore(projectRoot) {
22623
23010
  ${entriesToAdd.join("\n")}
22624
23011
  ` : `${entriesToAdd.join("\n")}
22625
23012
  `;
22626
- fs43.writeFileSync(gitignorePath, newContent, "utf-8");
23013
+ fs44.writeFileSync(gitignorePath, newContent, "utf-8");
22627
23014
  return true;
22628
23015
  } catch (error) {
22629
23016
  console.error(`Gitignore update warning: ${error.message}`);
@@ -22631,12 +23018,12 @@ ${entriesToAdd.join("\n")}
22631
23018
  }
22632
23019
  }
22633
23020
  function hasCursorProject(projectRoot) {
22634
- return fs43.existsSync(path46.join(projectRoot, ".cursor"));
23021
+ return fs44.existsSync(path47.join(projectRoot, ".cursor"));
22635
23022
  }
22636
23023
  function needsCursorRegeneration(projectRoot) {
22637
- const cursorDir = path46.join(projectRoot, ".cursor");
22638
- const routerPath = path46.join(cursorDir, "rules", "prjct.mdc");
22639
- return fs43.existsSync(cursorDir) && !fs43.existsSync(routerPath);
23024
+ const cursorDir = path47.join(projectRoot, ".cursor");
23025
+ const routerPath = path47.join(cursorDir, "rules", "prjct.mdc");
23026
+ return fs44.existsSync(cursorDir) && !fs44.existsSync(routerPath);
22640
23027
  }
22641
23028
  async function installWindsurfProject(projectRoot) {
22642
23029
  const result = {
@@ -22646,29 +23033,29 @@ async function installWindsurfProject(projectRoot) {
22646
23033
  gitignoreUpdated: false
22647
23034
  };
22648
23035
  try {
22649
- const windsurfDir = path46.join(projectRoot, ".windsurf");
22650
- const rulesDir = path46.join(windsurfDir, "rules");
22651
- const workflowsDir = path46.join(windsurfDir, "workflows");
22652
- const routerDest = path46.join(rulesDir, "prjct.md");
22653
- const routerSource = path46.join(getPackageRoot(), "templates", "windsurf", "router.md");
22654
- const windsurfWorkflowsSource = path46.join(
23036
+ const windsurfDir = path47.join(projectRoot, ".windsurf");
23037
+ const rulesDir = path47.join(windsurfDir, "rules");
23038
+ const workflowsDir = path47.join(windsurfDir, "workflows");
23039
+ const routerDest = path47.join(rulesDir, "prjct.md");
23040
+ const routerSource = path47.join(getPackageRoot(), "templates", "windsurf", "router.md");
23041
+ const windsurfWorkflowsSource = path47.join(
22655
23042
  getPackageRoot(),
22656
23043
  "templates",
22657
23044
  "windsurf",
22658
23045
  "workflows"
22659
23046
  );
22660
- fs43.mkdirSync(rulesDir, { recursive: true });
22661
- fs43.mkdirSync(workflowsDir, { recursive: true });
22662
- if (fs43.existsSync(routerSource)) {
22663
- fs43.copyFileSync(routerSource, routerDest);
23047
+ fs44.mkdirSync(rulesDir, { recursive: true });
23048
+ fs44.mkdirSync(workflowsDir, { recursive: true });
23049
+ if (fs44.existsSync(routerSource)) {
23050
+ fs44.copyFileSync(routerSource, routerDest);
22664
23051
  result.rulesCreated = true;
22665
23052
  }
22666
- if (fs43.existsSync(windsurfWorkflowsSource)) {
22667
- const workflowFiles = fs43.readdirSync(windsurfWorkflowsSource).filter((f) => f.endsWith(".md"));
23053
+ if (fs44.existsSync(windsurfWorkflowsSource)) {
23054
+ const workflowFiles = fs44.readdirSync(windsurfWorkflowsSource).filter((f) => f.endsWith(".md"));
22668
23055
  for (const file of workflowFiles) {
22669
- const src = path46.join(windsurfWorkflowsSource, file);
22670
- const dest = path46.join(workflowsDir, file);
22671
- fs43.copyFileSync(src, dest);
23056
+ const src = path47.join(windsurfWorkflowsSource, file);
23057
+ const dest = path47.join(workflowsDir, file);
23058
+ fs44.copyFileSync(src, dest);
22672
23059
  }
22673
23060
  result.workflowsCreated = workflowFiles.length > 0;
22674
23061
  }
@@ -22682,7 +23069,7 @@ async function installWindsurfProject(projectRoot) {
22682
23069
  }
22683
23070
  async function addWindsurfToGitignore(projectRoot) {
22684
23071
  try {
22685
- const gitignorePath = path46.join(projectRoot, ".gitignore");
23072
+ const gitignorePath = path47.join(projectRoot, ".gitignore");
22686
23073
  const entriesToAdd = [
22687
23074
  "# prjct Windsurf routers (regenerated per-developer)",
22688
23075
  ".windsurf/rules/prjct.md",
@@ -22697,7 +23084,7 @@ async function addWindsurfToGitignore(projectRoot) {
22697
23084
  let content = "";
22698
23085
  let fileExists2 = false;
22699
23086
  try {
22700
- content = fs43.readFileSync(gitignorePath, "utf-8");
23087
+ content = fs44.readFileSync(gitignorePath, "utf-8");
22701
23088
  fileExists2 = true;
22702
23089
  } catch (error) {
22703
23090
  if (!isNotFoundError(error)) {
@@ -22712,7 +23099,7 @@ async function addWindsurfToGitignore(projectRoot) {
22712
23099
  ${entriesToAdd.join("\n")}
22713
23100
  ` : `${entriesToAdd.join("\n")}
22714
23101
  `;
22715
- fs43.writeFileSync(gitignorePath, newContent, "utf-8");
23102
+ fs44.writeFileSync(gitignorePath, newContent, "utf-8");
22716
23103
  return true;
22717
23104
  } catch (error) {
22718
23105
  console.error(`Gitignore update warning: ${error.message}`);
@@ -22720,32 +23107,32 @@ ${entriesToAdd.join("\n")}
22720
23107
  }
22721
23108
  }
22722
23109
  function hasWindsurfProject(projectRoot) {
22723
- return fs43.existsSync(path46.join(projectRoot, ".windsurf"));
23110
+ return fs44.existsSync(path47.join(projectRoot, ".windsurf"));
22724
23111
  }
22725
23112
  function needsWindsurfRegeneration(projectRoot) {
22726
- const windsurfDir = path46.join(projectRoot, ".windsurf");
22727
- const routerPath = path46.join(windsurfDir, "rules", "prjct.md");
22728
- return fs43.existsSync(windsurfDir) && !fs43.existsSync(routerPath);
23113
+ const windsurfDir = path47.join(projectRoot, ".windsurf");
23114
+ const routerPath = path47.join(windsurfDir, "rules", "prjct.md");
23115
+ return fs44.existsSync(windsurfDir) && !fs44.existsSync(routerPath);
22729
23116
  }
22730
23117
  async function migrateProjectsCliVersion() {
22731
23118
  try {
22732
- const projectsDir = path46.join(os13.homedir(), ".prjct-cli", "projects");
22733
- if (!fs43.existsSync(projectsDir)) {
23119
+ const projectsDir = path47.join(os13.homedir(), ".prjct-cli", "projects");
23120
+ if (!fs44.existsSync(projectsDir)) {
22734
23121
  return;
22735
23122
  }
22736
- const projectDirs = fs43.readdirSync(projectsDir, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
23123
+ const projectDirs = fs44.readdirSync(projectsDir, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
22737
23124
  let migrated = 0;
22738
23125
  for (const projectId of projectDirs) {
22739
- const projectJsonPath = path46.join(projectsDir, projectId, "project.json");
22740
- if (!fs43.existsSync(projectJsonPath)) {
23126
+ const projectJsonPath = path47.join(projectsDir, projectId, "project.json");
23127
+ if (!fs44.existsSync(projectJsonPath)) {
22741
23128
  continue;
22742
23129
  }
22743
23130
  try {
22744
- const content = fs43.readFileSync(projectJsonPath, "utf8");
23131
+ const content = fs44.readFileSync(projectJsonPath, "utf8");
22745
23132
  const project = JSON.parse(content);
22746
23133
  if (project.cliVersion !== VERSION) {
22747
23134
  project.cliVersion = VERSION;
22748
- fs43.writeFileSync(projectJsonPath, JSON.stringify(project, null, 2));
23135
+ fs44.writeFileSync(projectJsonPath, JSON.stringify(project, null, 2));
22749
23136
  migrated++;
22750
23137
  }
22751
23138
  } catch (error) {
@@ -22765,9 +23152,9 @@ async function migrateProjectsCliVersion() {
22765
23152
  }
22766
23153
  function ensureStatusLineSettings(settingsPath, statusLinePath) {
22767
23154
  let settings = {};
22768
- if (fs43.existsSync(settingsPath)) {
23155
+ if (fs44.existsSync(settingsPath)) {
22769
23156
  try {
22770
- settings = JSON.parse(fs43.readFileSync(settingsPath, "utf8"));
23157
+ settings = JSON.parse(fs44.readFileSync(settingsPath, "utf8"));
22771
23158
  } catch (error) {
22772
23159
  if (!(error instanceof SyntaxError)) {
22773
23160
  throw error;
@@ -22775,42 +23162,42 @@ function ensureStatusLineSettings(settingsPath, statusLinePath) {
22775
23162
  }
22776
23163
  }
22777
23164
  settings.statusLine = { type: "command", command: statusLinePath };
22778
- fs43.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
23165
+ fs44.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
22779
23166
  }
22780
23167
  async function installStatusLine() {
22781
23168
  try {
22782
- const claudeDir = path46.join(os13.homedir(), ".claude");
22783
- const settingsPath = path46.join(claudeDir, "settings.json");
22784
- const claudeStatusLinePath = path46.join(claudeDir, "prjct-statusline.sh");
22785
- const prjctStatusLineDir = path46.join(os13.homedir(), ".prjct-cli", "statusline");
22786
- const prjctStatusLinePath = path46.join(prjctStatusLineDir, "statusline.sh");
22787
- const prjctThemesDir = path46.join(prjctStatusLineDir, "themes");
22788
- const prjctLibDir = path46.join(prjctStatusLineDir, "lib");
22789
- const prjctComponentsDir = path46.join(prjctStatusLineDir, "components");
22790
- const prjctConfigPath = path46.join(prjctStatusLineDir, "config.json");
22791
- const assetsDir = path46.join(getPackageRoot(), "assets", "statusline");
22792
- const sourceScript = path46.join(assetsDir, "statusline.sh");
22793
- const sourceThemeDir = path46.join(assetsDir, "themes");
22794
- const sourceLibDir = path46.join(assetsDir, "lib");
22795
- const sourceComponentsDir = path46.join(assetsDir, "components");
22796
- const sourceConfigPath = path46.join(assetsDir, "default-config.json");
22797
- if (!fs43.existsSync(claudeDir)) {
22798
- fs43.mkdirSync(claudeDir, { recursive: true });
23169
+ const claudeDir = path47.join(os13.homedir(), ".claude");
23170
+ const settingsPath = path47.join(claudeDir, "settings.json");
23171
+ const claudeStatusLinePath = path47.join(claudeDir, "prjct-statusline.sh");
23172
+ const prjctStatusLineDir = path47.join(os13.homedir(), ".prjct-cli", "statusline");
23173
+ const prjctStatusLinePath = path47.join(prjctStatusLineDir, "statusline.sh");
23174
+ const prjctThemesDir = path47.join(prjctStatusLineDir, "themes");
23175
+ const prjctLibDir = path47.join(prjctStatusLineDir, "lib");
23176
+ const prjctComponentsDir = path47.join(prjctStatusLineDir, "components");
23177
+ const prjctConfigPath = path47.join(prjctStatusLineDir, "config.json");
23178
+ const assetsDir = path47.join(getPackageRoot(), "assets", "statusline");
23179
+ const sourceScript = path47.join(assetsDir, "statusline.sh");
23180
+ const sourceThemeDir = path47.join(assetsDir, "themes");
23181
+ const sourceLibDir = path47.join(assetsDir, "lib");
23182
+ const sourceComponentsDir = path47.join(assetsDir, "components");
23183
+ const sourceConfigPath = path47.join(assetsDir, "default-config.json");
23184
+ if (!fs44.existsSync(claudeDir)) {
23185
+ fs44.mkdirSync(claudeDir, { recursive: true });
22799
23186
  }
22800
- if (!fs43.existsSync(prjctStatusLineDir)) {
22801
- fs43.mkdirSync(prjctStatusLineDir, { recursive: true });
23187
+ if (!fs44.existsSync(prjctStatusLineDir)) {
23188
+ fs44.mkdirSync(prjctStatusLineDir, { recursive: true });
22802
23189
  }
22803
- if (!fs43.existsSync(prjctThemesDir)) {
22804
- fs43.mkdirSync(prjctThemesDir, { recursive: true });
23190
+ if (!fs44.existsSync(prjctThemesDir)) {
23191
+ fs44.mkdirSync(prjctThemesDir, { recursive: true });
22805
23192
  }
22806
- if (!fs43.existsSync(prjctLibDir)) {
22807
- fs43.mkdirSync(prjctLibDir, { recursive: true });
23193
+ if (!fs44.existsSync(prjctLibDir)) {
23194
+ fs44.mkdirSync(prjctLibDir, { recursive: true });
22808
23195
  }
22809
- if (!fs43.existsSync(prjctComponentsDir)) {
22810
- fs43.mkdirSync(prjctComponentsDir, { recursive: true });
23196
+ if (!fs44.existsSync(prjctComponentsDir)) {
23197
+ fs44.mkdirSync(prjctComponentsDir, { recursive: true });
22811
23198
  }
22812
- if (fs43.existsSync(prjctStatusLinePath)) {
22813
- const existingContent = fs43.readFileSync(prjctStatusLinePath, "utf8");
23199
+ if (fs44.existsSync(prjctStatusLinePath)) {
23200
+ const existingContent = fs44.readFileSync(prjctStatusLinePath, "utf8");
22814
23201
  if (existingContent.includes("CLI_VERSION=")) {
22815
23202
  const versionMatch = existingContent.match(/CLI_VERSION="([^"]*)"/);
22816
23203
  if (versionMatch && versionMatch[1] !== VERSION) {
@@ -22818,7 +23205,7 @@ async function installStatusLine() {
22818
23205
  /CLI_VERSION="[^"]*"/,
22819
23206
  `CLI_VERSION="${VERSION}"`
22820
23207
  );
22821
- fs43.writeFileSync(prjctStatusLinePath, updatedContent, { mode: 493 });
23208
+ fs44.writeFileSync(prjctStatusLinePath, updatedContent, { mode: 493 });
22822
23209
  }
22823
23210
  installStatusLineModules(sourceLibDir, prjctLibDir);
22824
23211
  installStatusLineModules(sourceComponentsDir, prjctComponentsDir);
@@ -22827,22 +23214,22 @@ async function installStatusLine() {
22827
23214
  return;
22828
23215
  }
22829
23216
  }
22830
- if (fs43.existsSync(sourceScript)) {
22831
- let scriptContent = fs43.readFileSync(sourceScript, "utf8");
23217
+ if (fs44.existsSync(sourceScript)) {
23218
+ let scriptContent = fs44.readFileSync(sourceScript, "utf8");
22832
23219
  scriptContent = scriptContent.replace(/CLI_VERSION="[^"]*"/, `CLI_VERSION="${VERSION}"`);
22833
- fs43.writeFileSync(prjctStatusLinePath, scriptContent, { mode: 493 });
23220
+ fs44.writeFileSync(prjctStatusLinePath, scriptContent, { mode: 493 });
22834
23221
  installStatusLineModules(sourceLibDir, prjctLibDir);
22835
23222
  installStatusLineModules(sourceComponentsDir, prjctComponentsDir);
22836
- if (fs43.existsSync(sourceThemeDir)) {
22837
- const themes = fs43.readdirSync(sourceThemeDir);
23223
+ if (fs44.existsSync(sourceThemeDir)) {
23224
+ const themes = fs44.readdirSync(sourceThemeDir);
22838
23225
  for (const theme of themes) {
22839
- const src = path46.join(sourceThemeDir, theme);
22840
- const dest = path46.join(prjctThemesDir, theme);
22841
- fs43.copyFileSync(src, dest);
23226
+ const src = path47.join(sourceThemeDir, theme);
23227
+ const dest = path47.join(prjctThemesDir, theme);
23228
+ fs44.copyFileSync(src, dest);
22842
23229
  }
22843
23230
  }
22844
- if (!fs43.existsSync(prjctConfigPath) && fs43.existsSync(sourceConfigPath)) {
22845
- fs43.copyFileSync(sourceConfigPath, prjctConfigPath);
23231
+ if (!fs44.existsSync(prjctConfigPath) && fs44.existsSync(sourceConfigPath)) {
23232
+ fs44.copyFileSync(sourceConfigPath, prjctConfigPath);
22846
23233
  }
22847
23234
  } else {
22848
23235
  const scriptContent = `#!/bin/bash
@@ -22877,7 +23264,7 @@ if [ -f "$CONFIG" ]; then
22877
23264
  fi
22878
23265
  echo "prjct"
22879
23266
  `;
22880
- fs43.writeFileSync(prjctStatusLinePath, scriptContent, { mode: 493 });
23267
+ fs44.writeFileSync(prjctStatusLinePath, scriptContent, { mode: 493 });
22881
23268
  }
22882
23269
  ensureStatusLineSymlink(claudeStatusLinePath, prjctStatusLinePath);
22883
23270
  ensureStatusLineSettings(settingsPath, claudeStatusLinePath);
@@ -22889,10 +23276,10 @@ echo "prjct"
22889
23276
  }
22890
23277
  async function installContext7MCP() {
22891
23278
  try {
22892
- const claudeDir = path46.join(os13.homedir(), ".claude");
22893
- const mcpConfigPath = path46.join(claudeDir, "mcp.json");
22894
- if (!fs43.existsSync(claudeDir)) {
22895
- fs43.mkdirSync(claudeDir, { recursive: true });
23279
+ const claudeDir = path47.join(os13.homedir(), ".claude");
23280
+ const mcpConfigPath = path47.join(claudeDir, "mcp.json");
23281
+ if (!fs44.existsSync(claudeDir)) {
23282
+ fs44.mkdirSync(claudeDir, { recursive: true });
22896
23283
  }
22897
23284
  const context7Config = {
22898
23285
  mcpServers: {
@@ -22902,54 +23289,54 @@ async function installContext7MCP() {
22902
23289
  }
22903
23290
  }
22904
23291
  };
22905
- if (fs43.existsSync(mcpConfigPath)) {
22906
- const existingContent = fs43.readFileSync(mcpConfigPath, "utf-8");
23292
+ if (fs44.existsSync(mcpConfigPath)) {
23293
+ const existingContent = fs44.readFileSync(mcpConfigPath, "utf-8");
22907
23294
  const existingConfig = JSON.parse(existingContent);
22908
23295
  if (existingConfig.mcpServers?.context7) {
22909
23296
  return;
22910
23297
  }
22911
23298
  existingConfig.mcpServers = existingConfig.mcpServers || {};
22912
23299
  existingConfig.mcpServers.context7 = context7Config.mcpServers.context7;
22913
- fs43.writeFileSync(mcpConfigPath, JSON.stringify(existingConfig, null, 2), "utf-8");
23300
+ fs44.writeFileSync(mcpConfigPath, JSON.stringify(existingConfig, null, 2), "utf-8");
22914
23301
  } else {
22915
- fs43.writeFileSync(mcpConfigPath, JSON.stringify(context7Config, null, 2), "utf-8");
23302
+ fs44.writeFileSync(mcpConfigPath, JSON.stringify(context7Config, null, 2), "utf-8");
22916
23303
  }
22917
23304
  } catch (error) {
22918
23305
  console.error(`Context7 MCP setup warning: ${error.message}`);
22919
23306
  }
22920
23307
  }
22921
23308
  function installStatusLineModules(sourceDir, destDir) {
22922
- if (!fs43.existsSync(sourceDir)) {
23309
+ if (!fs44.existsSync(sourceDir)) {
22923
23310
  return;
22924
23311
  }
22925
- const files = fs43.readdirSync(sourceDir);
23312
+ const files = fs44.readdirSync(sourceDir);
22926
23313
  for (const file of files) {
22927
23314
  if (file.endsWith(".sh")) {
22928
- const src = path46.join(sourceDir, file);
22929
- const dest = path46.join(destDir, file);
22930
- fs43.copyFileSync(src, dest);
22931
- fs43.chmodSync(dest, 493);
23315
+ const src = path47.join(sourceDir, file);
23316
+ const dest = path47.join(destDir, file);
23317
+ fs44.copyFileSync(src, dest);
23318
+ fs44.chmodSync(dest, 493);
22932
23319
  }
22933
23320
  }
22934
23321
  }
22935
23322
  function ensureStatusLineSymlink(linkPath, targetPath) {
22936
23323
  try {
22937
- if (fs43.existsSync(linkPath)) {
22938
- const stats = fs43.lstatSync(linkPath);
23324
+ if (fs44.existsSync(linkPath)) {
23325
+ const stats = fs44.lstatSync(linkPath);
22939
23326
  if (stats.isSymbolicLink()) {
22940
- const existingTarget = fs43.readlinkSync(linkPath);
23327
+ const existingTarget = fs44.readlinkSync(linkPath);
22941
23328
  if (existingTarget === targetPath) {
22942
23329
  return;
22943
23330
  }
22944
23331
  }
22945
- fs43.unlinkSync(linkPath);
23332
+ fs44.unlinkSync(linkPath);
22946
23333
  }
22947
- fs43.symlinkSync(targetPath, linkPath);
23334
+ fs44.symlinkSync(targetPath, linkPath);
22948
23335
  } catch (_error) {
22949
23336
  try {
22950
- if (fs43.existsSync(targetPath)) {
22951
- fs43.copyFileSync(targetPath, linkPath);
22952
- fs43.chmodSync(linkPath, 493);
23337
+ if (fs44.existsSync(targetPath)) {
23338
+ fs44.copyFileSync(targetPath, linkPath);
23339
+ fs44.chmodSync(linkPath, 493);
22953
23340
  }
22954
23341
  } catch (copyError) {
22955
23342
  if (!isNotFoundError(copyError)) {
@@ -22987,6 +23374,7 @@ var GREEN4, YELLOW4, DIM4, NC, setup_default, isDirectRun;
22987
23374
  var init_setup = __esm({
22988
23375
  "core/infrastructure/setup.ts"() {
22989
23376
  "use strict";
23377
+ init_dependency_validator();
22990
23378
  init_fs();
22991
23379
  init_version();
22992
23380
  init_ai_provider();
@@ -23364,7 +23752,7 @@ var init_registry2 = __esm({
23364
23752
  });
23365
23753
 
23366
23754
  // core/commands/analytics.ts
23367
- import path47 from "node:path";
23755
+ import path48 from "node:path";
23368
23756
  var AnalyticsCommands;
23369
23757
  var init_analytics = __esm({
23370
23758
  "core/commands/analytics.ts"() {
@@ -23390,7 +23778,7 @@ var init_analytics = __esm({
23390
23778
  output_default.failWithHint("NO_PROJECT_ID");
23391
23779
  return { success: false, error: "No project ID found" };
23392
23780
  }
23393
- const projectName = path47.basename(projectPath);
23781
+ const projectName = path48.basename(projectPath);
23394
23782
  const currentTask = await stateStorage.getCurrentTask(projectId);
23395
23783
  const queueTasks = await queueStorage.getActiveTasks(projectId);
23396
23784
  const shipped = await shippedStorage.getRecent(projectId, 5);
@@ -23642,8 +24030,8 @@ ${"\u2550".repeat(50)}
23642
24030
  });
23643
24031
 
23644
24032
  // core/commands/context.ts
23645
- import fs44 from "node:fs/promises";
23646
- import path48 from "node:path";
24033
+ import fs45 from "node:fs/promises";
24034
+ import path49 from "node:path";
23647
24035
  var ContextCommands, contextCommands;
23648
24036
  var init_context = __esm({
23649
24037
  "core/commands/context.ts"() {
@@ -23769,8 +24157,8 @@ var init_context = __esm({
23769
24157
  */
23770
24158
  async loadRepoAnalysis(globalPath) {
23771
24159
  try {
23772
- const analysisPath = path48.join(globalPath, "analysis", "repo-analysis.json");
23773
- const content = await fs44.readFile(analysisPath, "utf-8");
24160
+ const analysisPath = path49.join(globalPath, "analysis", "repo-analysis.json");
24161
+ const content = await fs45.readFile(analysisPath, "utf-8");
23774
24162
  const data = JSON.parse(content);
23775
24163
  return {
23776
24164
  ecosystem: data.ecosystem || "unknown",
@@ -23789,7 +24177,7 @@ var init_context = __esm({
23789
24177
  });
23790
24178
 
23791
24179
  // core/commands/cleanup.ts
23792
- import path49 from "node:path";
24180
+ import path50 from "node:path";
23793
24181
  async function cleanupMemory(projectPath) {
23794
24182
  const projectId = await config_manager_default.getProjectId(projectPath);
23795
24183
  const results = { rotated: [], totalSize: 0, freedSpace: 0 };
@@ -23805,7 +24193,7 @@ async function cleanupMemory(projectPath) {
23805
24193
  results.totalSize += sizeMB;
23806
24194
  const rotated = await jsonl_helper_default.rotateJsonLinesIfNeeded(filePath, 10);
23807
24195
  if (rotated) {
23808
- results.rotated.push(path49.basename(filePath));
24196
+ results.rotated.push(path50.basename(filePath));
23809
24197
  results.freedSpace += sizeMB;
23810
24198
  }
23811
24199
  }
@@ -23912,7 +24300,7 @@ var init_cleanup = __esm({
23912
24300
  });
23913
24301
 
23914
24302
  // core/commands/design.ts
23915
- import path50 from "node:path";
24303
+ import path51 from "node:path";
23916
24304
  async function design(target = null, options = {}, projectPath = process.cwd()) {
23917
24305
  try {
23918
24306
  const designType = options.type || "architecture";
@@ -23924,7 +24312,7 @@ async function design(target = null, options = {}, projectPath = process.cwd())
23924
24312
  const designTarget = target || "system";
23925
24313
  output_default.spin(`designing ${designType}...`);
23926
24314
  const projectId = await config_manager_default.getProjectId(projectPath);
23927
- const designsPath = path50.join(
24315
+ const designsPath = path51.join(
23928
24316
  path_manager_default.getGlobalProjectPath(projectId),
23929
24317
  "planning",
23930
24318
  "designs"
@@ -23964,7 +24352,7 @@ async function design(target = null, options = {}, projectPath = process.cwd())
23964
24352
  break;
23965
24353
  }
23966
24354
  const designFileName = `${designType}-${designTarget.toLowerCase().replace(/\s+/g, "-")}.md`;
23967
- const designFilePath = path50.join(designsPath, designFileName);
24355
+ const designFilePath = path51.join(designsPath, designFileName);
23968
24356
  await file_helper_exports.writeFile(designFilePath, designContent);
23969
24357
  await memoryService.log(projectPath, "design_created", {
23970
24358
  type: designType,
@@ -23988,7 +24376,7 @@ var init_design = __esm({
23988
24376
  });
23989
24377
 
23990
24378
  // core/commands/snapshots.ts
23991
- import path51 from "node:path";
24379
+ import path52 from "node:path";
23992
24380
  async function recover(projectPath = process.cwd()) {
23993
24381
  try {
23994
24382
  const projectId = await config_manager_default.getProjectId(projectPath);
@@ -24040,11 +24428,11 @@ async function undo(projectPath = process.cwd()) {
24040
24428
  output_default.failWithHint("NO_PROJECT_ID");
24041
24429
  return { success: false, error: "No project ID found" };
24042
24430
  }
24043
- const snapshotsPath = path51.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
24431
+ const snapshotsPath = path52.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
24044
24432
  await file_helper_exports.ensureDir(snapshotsPath);
24045
- const { execSync: execSync7 } = await import("node:child_process");
24433
+ const { execSync: execSync8 } = await import("node:child_process");
24046
24434
  try {
24047
- const status = execSync7("git status --porcelain", {
24435
+ const status = execSync8("git status --porcelain", {
24048
24436
  cwd: projectPath,
24049
24437
  encoding: "utf-8"
24050
24438
  }).trim();
@@ -24054,11 +24442,11 @@ async function undo(projectPath = process.cwd()) {
24054
24442
  }
24055
24443
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
24056
24444
  const stashMessage = `prjct-undo-${timestamp}`;
24057
- execSync7(`git stash push -m "${stashMessage}"`, {
24445
+ execSync8(`git stash push -m "${stashMessage}"`, {
24058
24446
  cwd: projectPath,
24059
24447
  encoding: "utf-8"
24060
24448
  });
24061
- const snapshotFile = path51.join(snapshotsPath, "history.json");
24449
+ const snapshotFile = path52.join(snapshotsPath, "history.json");
24062
24450
  let history2 = { snapshots: [], current: -1 };
24063
24451
  try {
24064
24452
  const content = await file_helper_exports.readFile(snapshotFile);
@@ -24098,8 +24486,8 @@ async function redo(projectPath = process.cwd()) {
24098
24486
  output_default.failWithHint("NO_PROJECT_ID");
24099
24487
  return { success: false, error: "No project ID found" };
24100
24488
  }
24101
- const snapshotsPath = path51.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
24102
- const snapshotFile = path51.join(snapshotsPath, "history.json");
24489
+ const snapshotsPath = path52.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
24490
+ const snapshotFile = path52.join(snapshotsPath, "history.json");
24103
24491
  let history2;
24104
24492
  try {
24105
24493
  const content = await file_helper_exports.readFile(snapshotFile);
@@ -24115,9 +24503,9 @@ async function redo(projectPath = process.cwd()) {
24115
24503
  output_default.warn("nothing to redo");
24116
24504
  return { success: false, message: "Nothing to redo" };
24117
24505
  }
24118
- const { execSync: execSync7 } = await import("node:child_process");
24506
+ const { execSync: execSync8 } = await import("node:child_process");
24119
24507
  try {
24120
- const stashList = execSync7("git stash list", {
24508
+ const stashList = execSync8("git stash list", {
24121
24509
  cwd: projectPath,
24122
24510
  encoding: "utf-8"
24123
24511
  }).trim();
@@ -24130,7 +24518,7 @@ async function redo(projectPath = process.cwd()) {
24130
24518
  output_default.warn("no prjct undo point found");
24131
24519
  return { success: false, message: "No prjct undo point found" };
24132
24520
  }
24133
- execSync7("git stash pop", {
24521
+ execSync8("git stash pop", {
24134
24522
  cwd: projectPath,
24135
24523
  encoding: "utf-8"
24136
24524
  });
@@ -24158,8 +24546,8 @@ async function history(projectPath = process.cwd()) {
24158
24546
  output_default.failWithHint("NO_PROJECT_ID");
24159
24547
  return { success: false, error: "No project ID found" };
24160
24548
  }
24161
- const snapshotsPath = path51.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
24162
- const snapshotFile = path51.join(snapshotsPath, "history.json");
24549
+ const snapshotsPath = path52.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
24550
+ const snapshotFile = path52.join(snapshotsPath, "history.json");
24163
24551
  let snapshotHistory;
24164
24552
  try {
24165
24553
  const content = await file_helper_exports.readFile(snapshotFile);
@@ -24266,8 +24654,8 @@ var init_maintenance = __esm({
24266
24654
  });
24267
24655
 
24268
24656
  // core/commands/setup.ts
24269
- import fs45 from "node:fs";
24270
- import path52 from "node:path";
24657
+ import fs46 from "node:fs";
24658
+ import path53 from "node:path";
24271
24659
  import chalk11 from "chalk";
24272
24660
  var SetupCommands;
24273
24661
  var init_setup2 = __esm({
@@ -24394,7 +24782,7 @@ Please install it first:
24394
24782
  try {
24395
24783
  const claudeDir = path_manager_default.getClaudeDir();
24396
24784
  const settingsPath = path_manager_default.getClaudeSettingsPath();
24397
- const statusLinePath = path52.join(claudeDir, "prjct-statusline.sh");
24785
+ const statusLinePath = path53.join(claudeDir, "prjct-statusline.sh");
24398
24786
  const scriptContent = `#!/bin/bash
24399
24787
  # prjct Status Line for Claude Code
24400
24788
  # Shows version update notifications and current task
@@ -24452,11 +24840,11 @@ fi
24452
24840
  # Default: show prjct branding
24453
24841
  echo "\u26A1 prjct"
24454
24842
  `;
24455
- fs45.writeFileSync(statusLinePath, scriptContent, { mode: 493 });
24843
+ fs46.writeFileSync(statusLinePath, scriptContent, { mode: 493 });
24456
24844
  let settings = {};
24457
- if (fs45.existsSync(settingsPath)) {
24845
+ if (fs46.existsSync(settingsPath)) {
24458
24846
  try {
24459
- settings = JSON.parse(fs45.readFileSync(settingsPath, "utf8"));
24847
+ settings = JSON.parse(fs46.readFileSync(settingsPath, "utf8"));
24460
24848
  } catch (_error) {
24461
24849
  }
24462
24850
  }
@@ -24464,7 +24852,7 @@ echo "\u26A1 prjct"
24464
24852
  type: "command",
24465
24853
  command: statusLinePath
24466
24854
  };
24467
- fs45.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
24855
+ fs46.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
24468
24856
  return { success: true };
24469
24857
  } catch (error) {
24470
24858
  return { success: false, error: error.message };
@@ -24520,18 +24908,18 @@ echo "\u26A1 prjct"
24520
24908
  });
24521
24909
 
24522
24910
  // core/utils/project-commands.ts
24523
- import path53 from "node:path";
24911
+ import path54 from "node:path";
24524
24912
  async function detectPackageManager(projectPath, pkg) {
24525
24913
  const declared = pkg?.packageManager?.trim().toLowerCase();
24526
24914
  if (declared?.startsWith("pnpm@")) return "pnpm";
24527
24915
  if (declared?.startsWith("yarn@")) return "yarn";
24528
24916
  if (declared?.startsWith("bun@")) return "bun";
24529
24917
  if (declared?.startsWith("npm@")) return "npm";
24530
- if (await fileExists(path53.join(projectPath, "pnpm-lock.yaml"))) return "pnpm";
24531
- if (await fileExists(path53.join(projectPath, "yarn.lock"))) return "yarn";
24532
- if (await fileExists(path53.join(projectPath, "bun.lockb"))) return "bun";
24533
- if (await fileExists(path53.join(projectPath, "bun.lock"))) return "bun";
24534
- if (await fileExists(path53.join(projectPath, "package-lock.json"))) return "npm";
24918
+ if (await fileExists(path54.join(projectPath, "pnpm-lock.yaml"))) return "pnpm";
24919
+ if (await fileExists(path54.join(projectPath, "yarn.lock"))) return "yarn";
24920
+ if (await fileExists(path54.join(projectPath, "bun.lockb"))) return "bun";
24921
+ if (await fileExists(path54.join(projectPath, "bun.lock"))) return "bun";
24922
+ if (await fileExists(path54.join(projectPath, "package-lock.json"))) return "npm";
24535
24923
  return "npm";
24536
24924
  }
24537
24925
  function pmRun(pm, scriptName) {
@@ -24547,7 +24935,7 @@ function pmTest(pm) {
24547
24935
  return "npm test";
24548
24936
  }
24549
24937
  async function detectProjectCommands(projectPath) {
24550
- const pkgPath = path53.join(projectPath, "package.json");
24938
+ const pkgPath = path54.join(projectPath, "package.json");
24551
24939
  const pkg = await readJson(pkgPath, null);
24552
24940
  if (pkg) {
24553
24941
  const pm = await detectPackageManager(projectPath, pkg);
@@ -24564,27 +24952,27 @@ async function detectProjectCommands(projectPath) {
24564
24952
  }
24565
24953
  return result;
24566
24954
  }
24567
- if (await fileExists(path53.join(projectPath, "pytest.ini"))) {
24955
+ if (await fileExists(path54.join(projectPath, "pytest.ini"))) {
24568
24956
  return { stack: "python", test: { tool: "pytest", command: "pytest" } };
24569
24957
  }
24570
- const pyproject = await readFile(path53.join(projectPath, "pyproject.toml"), "");
24958
+ const pyproject = await readFile(path54.join(projectPath, "pyproject.toml"), "");
24571
24959
  if (pyproject.includes("[tool.pytest") || pyproject.includes("pytest")) {
24572
24960
  return { stack: "python", test: { tool: "pytest", command: "pytest" } };
24573
24961
  }
24574
- if (await fileExists(path53.join(projectPath, "Cargo.toml"))) {
24962
+ if (await fileExists(path54.join(projectPath, "Cargo.toml"))) {
24575
24963
  return { stack: "rust", test: { tool: "cargo", command: "cargo test" } };
24576
24964
  }
24577
- if (await fileExists(path53.join(projectPath, "go.mod"))) {
24965
+ if (await fileExists(path54.join(projectPath, "go.mod"))) {
24578
24966
  return { stack: "go", test: { tool: "go", command: "go test ./..." } };
24579
24967
  }
24580
24968
  const files = await listFiles(projectPath);
24581
24969
  if (files.some((f) => f.endsWith(".sln") || f.endsWith(".csproj") || f.endsWith(".fsproj"))) {
24582
24970
  return { stack: "dotnet", test: { tool: "dotnet", command: "dotnet test" } };
24583
24971
  }
24584
- if (await fileExists(path53.join(projectPath, "pom.xml"))) {
24972
+ if (await fileExists(path54.join(projectPath, "pom.xml"))) {
24585
24973
  return { stack: "java", test: { tool: "maven", command: "mvn test" } };
24586
24974
  }
24587
- if (await fileExists(path53.join(projectPath, "gradlew")) && (await fileExists(path53.join(projectPath, "build.gradle")) || await fileExists(path53.join(projectPath, "build.gradle.kts")))) {
24975
+ if (await fileExists(path54.join(projectPath, "gradlew")) && (await fileExists(path54.join(projectPath, "build.gradle")) || await fileExists(path54.join(projectPath, "build.gradle.kts")))) {
24588
24976
  return { stack: "java", test: { tool: "gradle", command: "./gradlew test" } };
24589
24977
  }
24590
24978
  return { stack: "unknown" };
@@ -24761,7 +25149,7 @@ var init_workflow_preferences = __esm({
24761
25149
  });
24762
25150
 
24763
25151
  // core/commands/shipping.ts
24764
- import path54 from "node:path";
25152
+ import path55 from "node:path";
24765
25153
  var ShippingCommands;
24766
25154
  var init_shipping = __esm({
24767
25155
  "core/commands/shipping.ts"() {
@@ -24907,7 +25295,7 @@ ${result.stderr}`.trim();
24907
25295
  */
24908
25296
  async _bumpVersion(projectPath) {
24909
25297
  try {
24910
- const pkgPath = path54.join(projectPath, "package.json");
25298
+ const pkgPath = path55.join(projectPath, "package.json");
24911
25299
  const pkg = await file_helper_exports.readJson(pkgPath, { version: "0.0.0" });
24912
25300
  const oldVersion = pkg?.version || "0.0.0";
24913
25301
  const [major, minor, patch] = oldVersion.split(".").map(Number);
@@ -24929,7 +25317,7 @@ ${result.stderr}`.trim();
24929
25317
  */
24930
25318
  async _updateChangelog(feature, version, projectPath) {
24931
25319
  try {
24932
- const changelogPath = path54.join(projectPath, "CHANGELOG.md");
25320
+ const changelogPath = path55.join(projectPath, "CHANGELOG.md");
24933
25321
  const changelog = await file_helper_exports.readFile(changelogPath, "# Changelog\n\n");
24934
25322
  const entry = `## [${version}] - ${date_helper_default.formatDate(/* @__PURE__ */ new Date())}
24935
25323
 
@@ -25821,19 +26209,19 @@ var init_linear = __esm({
25821
26209
  });
25822
26210
 
25823
26211
  // core/utils/project-credentials.ts
25824
- import fs46 from "node:fs";
26212
+ import fs47 from "node:fs";
25825
26213
  import os14 from "node:os";
25826
- import path55 from "node:path";
26214
+ import path56 from "node:path";
25827
26215
  function getCredentialsPath(projectId) {
25828
- return path55.join(os14.homedir(), ".prjct-cli", "projects", projectId, "config", "credentials.json");
26216
+ return path56.join(os14.homedir(), ".prjct-cli", "projects", projectId, "config", "credentials.json");
25829
26217
  }
25830
26218
  async function getProjectCredentials(projectId) {
25831
26219
  const credPath = getCredentialsPath(projectId);
25832
- if (!fs46.existsSync(credPath)) {
26220
+ if (!fs47.existsSync(credPath)) {
25833
26221
  return {};
25834
26222
  }
25835
26223
  try {
25836
- return JSON.parse(fs46.readFileSync(credPath, "utf-8"));
26224
+ return JSON.parse(fs47.readFileSync(credPath, "utf-8"));
25837
26225
  } catch (error) {
25838
26226
  console.error("[project-credentials] Failed to read credentials:", error.message);
25839
26227
  return {};
@@ -26410,7 +26798,7 @@ var require_package = __commonJS({
26410
26798
  "package.json"(exports, module) {
26411
26799
  module.exports = {
26412
26800
  name: "prjct-cli",
26413
- version: "0.60.2",
26801
+ version: "0.62.0",
26414
26802
  description: "Context layer for AI agents. Project context for Claude Code, Gemini CLI, and more.",
26415
26803
  main: "core/index.ts",
26416
26804
  bin: {
@@ -26517,9 +26905,9 @@ var require_package = __commonJS({
26517
26905
 
26518
26906
  // core/index.ts
26519
26907
  var core_exports = {};
26520
- import fs47 from "node:fs";
26908
+ import fs48 from "node:fs";
26521
26909
  import os15 from "node:os";
26522
- import path56 from "node:path";
26910
+ import path57 from "node:path";
26523
26911
  async function main() {
26524
26912
  const [commandName, ...rawArgs] = process.argv.slice(2);
26525
26913
  if (["-v", "--version", "version"].includes(commandName)) {
@@ -26651,12 +27039,12 @@ function parseCommandArgs(_cmd, rawArgs) {
26651
27039
  }
26652
27040
  function displayVersion(version) {
26653
27041
  const detection = detectAllProviders();
26654
- const claudeCommandPath = path56.join(os15.homedir(), ".claude", "commands", "p.md");
26655
- const geminiCommandPath = path56.join(os15.homedir(), ".gemini", "commands", "p.toml");
26656
- const claudeConfigured = fs47.existsSync(claudeCommandPath);
26657
- const geminiConfigured = fs47.existsSync(geminiCommandPath);
26658
- const cursorConfigured = fs47.existsSync(path56.join(process.cwd(), ".cursor", "commands", "sync.md"));
26659
- const cursorExists = fs47.existsSync(path56.join(process.cwd(), ".cursor"));
27042
+ const claudeCommandPath = path57.join(os15.homedir(), ".claude", "commands", "p.md");
27043
+ const geminiCommandPath = path57.join(os15.homedir(), ".gemini", "commands", "p.toml");
27044
+ const claudeConfigured = fs48.existsSync(claudeCommandPath);
27045
+ const geminiConfigured = fs48.existsSync(geminiCommandPath);
27046
+ const cursorConfigured = fs48.existsSync(path57.join(process.cwd(), ".cursor", "commands", "sync.md"));
27047
+ const cursorExists = fs48.existsSync(path57.join(process.cwd(), ".cursor"));
26660
27048
  console.log(`
26661
27049
  ${CYAN3}p/${RESET5} prjct v${version}
26662
27050
  ${DIM6}Context layer for AI coding agents${RESET5}
@@ -26789,9 +27177,9 @@ var init_core = __esm({
26789
27177
  init_ai_provider();
26790
27178
  init_config_manager();
26791
27179
  init_editors_config();
26792
- import fs48 from "node:fs";
27180
+ import fs49 from "node:fs";
26793
27181
  import os16 from "node:os";
26794
- import path57 from "node:path";
27182
+ import path58 from "node:path";
26795
27183
 
26796
27184
  // core/server/server.ts
26797
27185
  import { Hono as Hono3 } from "hono";
@@ -27533,14 +27921,14 @@ function checkRoutersInstalled() {
27533
27921
  const home = os16.homedir();
27534
27922
  const detection = detectAllProviders();
27535
27923
  if (detection.claude.installed) {
27536
- const claudeRouter = path57.join(home, ".claude", "commands", "p.md");
27537
- if (!fs48.existsSync(claudeRouter)) {
27924
+ const claudeRouter = path58.join(home, ".claude", "commands", "p.md");
27925
+ if (!fs49.existsSync(claudeRouter)) {
27538
27926
  return false;
27539
27927
  }
27540
27928
  }
27541
27929
  if (detection.gemini.installed) {
27542
- const geminiRouter = path57.join(home, ".gemini", "commands", "p.toml");
27543
- if (!fs48.existsSync(geminiRouter)) {
27930
+ const geminiRouter = path58.join(home, ".gemini", "commands", "p.toml");
27931
+ if (!fs49.existsSync(geminiRouter)) {
27544
27932
  return false;
27545
27933
  }
27546
27934
  }
@@ -27641,7 +28029,7 @@ if (args[0] === "start" || args[0] === "setup") {
27641
28029
  console.error('No prjct project found. Run "prjct init" first.');
27642
28030
  process.exitCode = 1;
27643
28031
  } else {
27644
- const linearCliPath = path57.join(__dirname, "..", "core", "cli", "linear.ts");
28032
+ const linearCliPath = path58.join(__dirname, "..", "core", "cli", "linear.ts");
27645
28033
  const linearArgs = ["--project", projectId, ...args.slice(1)];
27646
28034
  const child = spawn("bun", [linearCliPath, ...linearArgs], {
27647
28035
  stdio: "inherit",
@@ -27660,12 +28048,12 @@ if (args[0] === "start" || args[0] === "setup") {
27660
28048
  const detection = detectAllProviders();
27661
28049
  const home = os16.homedir();
27662
28050
  const cwd = process.cwd();
27663
- const claudeConfigured = fs48.existsSync(path57.join(home, ".claude", "commands", "p.md"));
27664
- const geminiConfigured = fs48.existsSync(path57.join(home, ".gemini", "commands", "p.toml"));
27665
- const cursorDetected = fs48.existsSync(path57.join(cwd, ".cursor"));
27666
- const cursorConfigured = fs48.existsSync(path57.join(cwd, ".cursor", "rules", "prjct.mdc"));
27667
- const windsurfDetected = fs48.existsSync(path57.join(cwd, ".windsurf"));
27668
- const windsurfConfigured = fs48.existsSync(path57.join(cwd, ".windsurf", "rules", "prjct.md"));
28051
+ const claudeConfigured = fs49.existsSync(path58.join(home, ".claude", "commands", "p.md"));
28052
+ const geminiConfigured = fs49.existsSync(path58.join(home, ".gemini", "commands", "p.toml"));
28053
+ const cursorDetected = fs49.existsSync(path58.join(cwd, ".cursor"));
28054
+ const cursorConfigured = fs49.existsSync(path58.join(cwd, ".cursor", "rules", "prjct.mdc"));
28055
+ const windsurfDetected = fs49.existsSync(path58.join(cwd, ".windsurf"));
28056
+ const windsurfConfigured = fs49.existsSync(path58.join(cwd, ".windsurf", "rules", "prjct.md"));
27669
28057
  const GREEN7 = "\x1B[32m";
27670
28058
  console.log(`
27671
28059
  ${CYAN4}p/${RESET6} prjct v${VERSION}
@@ -27704,9 +28092,9 @@ ${DIM7}Run 'prjct init' to configure (Cursor/Windsurf IDE)${RESET6}
27704
28092
  ${CYAN4}https://prjct.app${RESET6}
27705
28093
  `);
27706
28094
  } else {
27707
- const configPath = path57.join(os16.homedir(), ".prjct-cli", "config", "installed-editors.json");
28095
+ const configPath = path58.join(os16.homedir(), ".prjct-cli", "config", "installed-editors.json");
27708
28096
  const routersInstalled = checkRoutersInstalled();
27709
- if (!fs48.existsSync(configPath) || !routersInstalled) {
28097
+ if (!fs49.existsSync(configPath) || !routersInstalled) {
27710
28098
  console.log(`
27711
28099
  ${CYAN4}${BOLD4} Welcome to prjct!${RESET6}
27712
28100