prjct-cli 0.56.1 → 0.58.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +29 -5
- package/core/commands/analysis.ts +46 -1
- package/core/commands/command-data.ts +6 -1
- package/core/commands/commands.ts +7 -1
- package/core/index.ts +1 -0
- package/core/infrastructure/path-manager.ts +219 -0
- package/core/services/context-generator.ts +131 -0
- package/core/services/index.ts +3 -0
- package/core/services/nested-context-resolver.ts +378 -0
- package/core/services/sync-service.ts +2 -0
- package/dist/bin/prjct.mjs +935 -390
- package/package.json +1 -1
- package/templates/commands/done.md +20 -7
- package/templates/commands/merge.md +51 -4
- package/templates/commands/ship.md +247 -29
- package/templates/commands/task.md +3 -3
package/dist/bin/prjct.mjs
CHANGED
|
@@ -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) => (
|
|
20
|
-
var fn = map[
|
|
19
|
+
var __glob = (map) => (path57) => {
|
|
20
|
+
var fn = map[path57];
|
|
21
21
|
if (fn) return fn();
|
|
22
|
-
throw new Error("Module not found in bundle: " +
|
|
22
|
+
throw new Error("Module not found in bundle: " + path57);
|
|
23
23
|
};
|
|
24
24
|
var __esm = (fn, res) => function __init() {
|
|
25
25
|
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
@@ -1178,6 +1178,7 @@ import crypto2 from "node:crypto";
|
|
|
1178
1178
|
import fs4 from "node:fs/promises";
|
|
1179
1179
|
import os2 from "node:os";
|
|
1180
1180
|
import path4 from "node:path";
|
|
1181
|
+
import { globSync } from "glob";
|
|
1181
1182
|
var PathManager, pathManager, path_manager_default;
|
|
1182
1183
|
var init_path_manager = __esm({
|
|
1183
1184
|
"core/infrastructure/path-manager.ts"() {
|
|
@@ -1470,6 +1471,158 @@ var init_path_manager = __esm({
|
|
|
1470
1471
|
getContextPath(projectId) {
|
|
1471
1472
|
return path4.join(this.getGlobalProjectPath(projectId), "context");
|
|
1472
1473
|
}
|
|
1474
|
+
// ===========================================================================
|
|
1475
|
+
// Monorepo Detection
|
|
1476
|
+
// ===========================================================================
|
|
1477
|
+
/**
|
|
1478
|
+
* Detect if a project is a monorepo and get package information
|
|
1479
|
+
*/
|
|
1480
|
+
async detectMonorepo(projectPath) {
|
|
1481
|
+
const result = {
|
|
1482
|
+
isMonorepo: false,
|
|
1483
|
+
type: null,
|
|
1484
|
+
rootPath: projectPath,
|
|
1485
|
+
packages: []
|
|
1486
|
+
};
|
|
1487
|
+
const checks = [
|
|
1488
|
+
{ file: "pnpm-workspace.yaml", type: "pnpm" },
|
|
1489
|
+
{ file: "lerna.json", type: "lerna" },
|
|
1490
|
+
{ file: "nx.json", type: "nx" },
|
|
1491
|
+
{ file: "rush.json", type: "rush" },
|
|
1492
|
+
{ file: "turbo.json", type: "turborepo" }
|
|
1493
|
+
];
|
|
1494
|
+
for (const check of checks) {
|
|
1495
|
+
const filePath = path4.join(projectPath, check.file);
|
|
1496
|
+
if (await fileExists(filePath)) {
|
|
1497
|
+
result.isMonorepo = true;
|
|
1498
|
+
result.type = check.type;
|
|
1499
|
+
break;
|
|
1500
|
+
}
|
|
1501
|
+
}
|
|
1502
|
+
if (!result.isMonorepo) {
|
|
1503
|
+
const packageJsonPath = path4.join(projectPath, "package.json");
|
|
1504
|
+
if (await fileExists(packageJsonPath)) {
|
|
1505
|
+
try {
|
|
1506
|
+
const content = await fs4.readFile(packageJsonPath, "utf-8");
|
|
1507
|
+
const pkg = JSON.parse(content);
|
|
1508
|
+
if (pkg.workspaces) {
|
|
1509
|
+
result.isMonorepo = true;
|
|
1510
|
+
result.type = "npm";
|
|
1511
|
+
}
|
|
1512
|
+
} catch {
|
|
1513
|
+
}
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1516
|
+
if (result.isMonorepo) {
|
|
1517
|
+
result.packages = await this.discoverMonorepoPackages(projectPath, result.type);
|
|
1518
|
+
}
|
|
1519
|
+
return result;
|
|
1520
|
+
}
|
|
1521
|
+
/**
|
|
1522
|
+
* Discover all packages in a monorepo
|
|
1523
|
+
*/
|
|
1524
|
+
async discoverMonorepoPackages(rootPath, type) {
|
|
1525
|
+
const packages = [];
|
|
1526
|
+
let patterns = [];
|
|
1527
|
+
try {
|
|
1528
|
+
if (type === "pnpm") {
|
|
1529
|
+
const yaml = await fs4.readFile(path4.join(rootPath, "pnpm-workspace.yaml"), "utf-8");
|
|
1530
|
+
const match = yaml.match(/packages:\s*\n((?:\s*-\s*.+\n?)+)/);
|
|
1531
|
+
if (match) {
|
|
1532
|
+
patterns = match[1].split("\n").map((line) => line.replace(/^\s*-\s*['"]?|['"]?\s*$/g, "")).filter(Boolean);
|
|
1533
|
+
}
|
|
1534
|
+
} else if (type === "npm" || type === "lerna") {
|
|
1535
|
+
const packageJsonPath = path4.join(rootPath, "package.json");
|
|
1536
|
+
const content = await fs4.readFile(packageJsonPath, "utf-8");
|
|
1537
|
+
const pkg = JSON.parse(content);
|
|
1538
|
+
if (Array.isArray(pkg.workspaces)) {
|
|
1539
|
+
patterns = pkg.workspaces;
|
|
1540
|
+
} else if (pkg.workspaces?.packages) {
|
|
1541
|
+
patterns = pkg.workspaces.packages;
|
|
1542
|
+
}
|
|
1543
|
+
if (type === "lerna") {
|
|
1544
|
+
const lernaPath = path4.join(rootPath, "lerna.json");
|
|
1545
|
+
if (await fileExists(lernaPath)) {
|
|
1546
|
+
const lernaContent = await fs4.readFile(lernaPath, "utf-8");
|
|
1547
|
+
const lerna = JSON.parse(lernaContent);
|
|
1548
|
+
if (lerna.packages) {
|
|
1549
|
+
patterns = lerna.packages;
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
} else if (type === "nx") {
|
|
1554
|
+
patterns = ["apps/*", "libs/*", "packages/*"];
|
|
1555
|
+
} else if (type === "turborepo") {
|
|
1556
|
+
const packageJsonPath = path4.join(rootPath, "package.json");
|
|
1557
|
+
const content = await fs4.readFile(packageJsonPath, "utf-8");
|
|
1558
|
+
const pkg = JSON.parse(content);
|
|
1559
|
+
if (Array.isArray(pkg.workspaces)) {
|
|
1560
|
+
patterns = pkg.workspaces;
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
if (patterns.length === 0) {
|
|
1564
|
+
patterns = ["packages/*", "apps/*", "libs/*"];
|
|
1565
|
+
}
|
|
1566
|
+
for (const pattern of patterns) {
|
|
1567
|
+
if (pattern.startsWith("!")) continue;
|
|
1568
|
+
const matches = globSync(pattern, {
|
|
1569
|
+
cwd: rootPath,
|
|
1570
|
+
absolute: false
|
|
1571
|
+
});
|
|
1572
|
+
for (const match of matches) {
|
|
1573
|
+
const packagePath = path4.join(rootPath, match);
|
|
1574
|
+
const packageJsonPath = path4.join(packagePath, "package.json");
|
|
1575
|
+
if (await fileExists(packageJsonPath)) {
|
|
1576
|
+
try {
|
|
1577
|
+
const content = await fs4.readFile(packageJsonPath, "utf-8");
|
|
1578
|
+
const pkg = JSON.parse(content);
|
|
1579
|
+
const prjctMdPath = path4.join(packagePath, "PRJCT.md");
|
|
1580
|
+
packages.push({
|
|
1581
|
+
name: pkg.name || path4.basename(match),
|
|
1582
|
+
path: packagePath,
|
|
1583
|
+
relativePath: match,
|
|
1584
|
+
hasPrjctMd: await fileExists(prjctMdPath)
|
|
1585
|
+
});
|
|
1586
|
+
} catch {
|
|
1587
|
+
}
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1590
|
+
}
|
|
1591
|
+
} catch {
|
|
1592
|
+
}
|
|
1593
|
+
return packages;
|
|
1594
|
+
}
|
|
1595
|
+
/**
|
|
1596
|
+
* Check if current path is within a monorepo package
|
|
1597
|
+
* Returns the package info if found, null otherwise
|
|
1598
|
+
*/
|
|
1599
|
+
async findContainingPackage(currentPath, monoInfo) {
|
|
1600
|
+
if (!monoInfo.isMonorepo) return null;
|
|
1601
|
+
const normalizedCurrent = path4.resolve(currentPath);
|
|
1602
|
+
for (const pkg of monoInfo.packages) {
|
|
1603
|
+
const normalizedPkg = path4.resolve(pkg.path);
|
|
1604
|
+
if (normalizedCurrent.startsWith(normalizedPkg)) {
|
|
1605
|
+
return pkg;
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
return null;
|
|
1609
|
+
}
|
|
1610
|
+
/**
|
|
1611
|
+
* Find monorepo root from any subdirectory
|
|
1612
|
+
* Walks up the directory tree looking for monorepo markers
|
|
1613
|
+
*/
|
|
1614
|
+
async findMonorepoRoot(startPath) {
|
|
1615
|
+
let currentPath = path4.resolve(startPath);
|
|
1616
|
+
const root = path4.parse(currentPath).root;
|
|
1617
|
+
while (currentPath !== root) {
|
|
1618
|
+
const monoInfo = await this.detectMonorepo(currentPath);
|
|
1619
|
+
if (monoInfo.isMonorepo) {
|
|
1620
|
+
return currentPath;
|
|
1621
|
+
}
|
|
1622
|
+
currentPath = path4.dirname(currentPath);
|
|
1623
|
+
}
|
|
1624
|
+
return null;
|
|
1625
|
+
}
|
|
1473
1626
|
};
|
|
1474
1627
|
pathManager = new PathManager();
|
|
1475
1628
|
path_manager_default = pathManager;
|
|
@@ -3866,8 +4019,8 @@ function tryResolve(basePath, projectPath) {
|
|
|
3866
4019
|
for (const ext of extensions) {
|
|
3867
4020
|
const fullPath = basePath + ext;
|
|
3868
4021
|
try {
|
|
3869
|
-
const
|
|
3870
|
-
if (
|
|
4022
|
+
const fs48 = __require("node:fs");
|
|
4023
|
+
if (fs48.existsSync(fullPath) && fs48.statSync(fullPath).isFile()) {
|
|
3871
4024
|
return path12.relative(projectPath, fullPath);
|
|
3872
4025
|
}
|
|
3873
4026
|
} catch {
|
|
@@ -5050,11 +5203,11 @@ async function runSignaturesTool(args2, projectPath) {
|
|
|
5050
5203
|
}
|
|
5051
5204
|
};
|
|
5052
5205
|
}
|
|
5053
|
-
const
|
|
5054
|
-
const
|
|
5055
|
-
const fullPath =
|
|
5206
|
+
const fs48 = await import("node:fs/promises");
|
|
5207
|
+
const path57 = await import("node:path");
|
|
5208
|
+
const fullPath = path57.isAbsolute(filePath) ? filePath : path57.join(projectPath, filePath);
|
|
5056
5209
|
try {
|
|
5057
|
-
const stat = await
|
|
5210
|
+
const stat = await fs48.stat(fullPath);
|
|
5058
5211
|
if (stat.isDirectory()) {
|
|
5059
5212
|
const results = await extractDirectorySignatures(filePath, projectPath, {
|
|
5060
5213
|
recursive: args2.includes("--recursive") || args2.includes("-r")
|
|
@@ -5121,11 +5274,11 @@ async function runSummaryTool(args2, projectPath) {
|
|
|
5121
5274
|
}
|
|
5122
5275
|
};
|
|
5123
5276
|
}
|
|
5124
|
-
const
|
|
5125
|
-
const
|
|
5126
|
-
const fullPath =
|
|
5277
|
+
const fs48 = await import("node:fs/promises");
|
|
5278
|
+
const path57 = await import("node:path");
|
|
5279
|
+
const fullPath = path57.isAbsolute(targetPath) ? targetPath : path57.join(projectPath, targetPath);
|
|
5127
5280
|
try {
|
|
5128
|
-
const stat = await
|
|
5281
|
+
const stat = await fs48.stat(fullPath);
|
|
5129
5282
|
if (stat.isDirectory()) {
|
|
5130
5283
|
const results = await summarizeDirectory(targetPath, projectPath, {
|
|
5131
5284
|
recursive: args2.includes("--recursive") || args2.includes("-r")
|
|
@@ -15556,6 +15709,254 @@ var init_memory_service = __esm({
|
|
|
15556
15709
|
}
|
|
15557
15710
|
});
|
|
15558
15711
|
|
|
15712
|
+
// core/services/nested-context-resolver.ts
|
|
15713
|
+
import fs32 from "node:fs/promises";
|
|
15714
|
+
import path33 from "node:path";
|
|
15715
|
+
var NestedContextResolver;
|
|
15716
|
+
var init_nested_context_resolver = __esm({
|
|
15717
|
+
"core/services/nested-context-resolver.ts"() {
|
|
15718
|
+
"use strict";
|
|
15719
|
+
init_path_manager();
|
|
15720
|
+
init_file_helper();
|
|
15721
|
+
NestedContextResolver = class {
|
|
15722
|
+
static {
|
|
15723
|
+
__name(this, "NestedContextResolver");
|
|
15724
|
+
}
|
|
15725
|
+
rootPath;
|
|
15726
|
+
monoInfo = null;
|
|
15727
|
+
constructor(rootPath) {
|
|
15728
|
+
this.rootPath = path33.resolve(rootPath);
|
|
15729
|
+
}
|
|
15730
|
+
/**
|
|
15731
|
+
* Initialize the resolver with monorepo detection
|
|
15732
|
+
*/
|
|
15733
|
+
async initialize() {
|
|
15734
|
+
this.monoInfo = await path_manager_default.detectMonorepo(this.rootPath);
|
|
15735
|
+
}
|
|
15736
|
+
/**
|
|
15737
|
+
* Discover all PRJCT.md files in the project/monorepo
|
|
15738
|
+
*/
|
|
15739
|
+
async discoverContextFiles() {
|
|
15740
|
+
const contexts = [];
|
|
15741
|
+
const rootPrjctPath = path33.join(this.rootPath, "PRJCT.md");
|
|
15742
|
+
if (await fileExists(rootPrjctPath)) {
|
|
15743
|
+
const rootContext = await this.loadContext(rootPrjctPath, null);
|
|
15744
|
+
contexts.push(rootContext);
|
|
15745
|
+
}
|
|
15746
|
+
if (this.monoInfo?.isMonorepo) {
|
|
15747
|
+
for (const pkg of this.monoInfo.packages) {
|
|
15748
|
+
const pkgPrjctPath = path33.join(pkg.path, "PRJCT.md");
|
|
15749
|
+
if (await fileExists(pkgPrjctPath)) {
|
|
15750
|
+
const parentContext = contexts.find((c) => c.depth === 0) || null;
|
|
15751
|
+
const pkgContext = await this.loadContext(pkgPrjctPath, parentContext, pkg);
|
|
15752
|
+
contexts.push(pkgContext);
|
|
15753
|
+
if (parentContext) {
|
|
15754
|
+
parentContext.children.push(pkgContext);
|
|
15755
|
+
}
|
|
15756
|
+
}
|
|
15757
|
+
}
|
|
15758
|
+
}
|
|
15759
|
+
const additionalContexts = await this.scanForNestedContexts(this.rootPath, contexts);
|
|
15760
|
+
contexts.push(...additionalContexts);
|
|
15761
|
+
return contexts;
|
|
15762
|
+
}
|
|
15763
|
+
/**
|
|
15764
|
+
* Load a single PRJCT.md file into a NestedContext
|
|
15765
|
+
*/
|
|
15766
|
+
async loadContext(filePath, parent, pkg = null) {
|
|
15767
|
+
const content = await fs32.readFile(filePath, "utf-8");
|
|
15768
|
+
const relativePath = path33.relative(this.rootPath, filePath);
|
|
15769
|
+
const depth = relativePath.split(path33.sep).length - 1;
|
|
15770
|
+
return {
|
|
15771
|
+
path: filePath,
|
|
15772
|
+
relativePath,
|
|
15773
|
+
depth,
|
|
15774
|
+
parent,
|
|
15775
|
+
children: [],
|
|
15776
|
+
content,
|
|
15777
|
+
sections: this.parseSections(content),
|
|
15778
|
+
package: pkg
|
|
15779
|
+
};
|
|
15780
|
+
}
|
|
15781
|
+
/**
|
|
15782
|
+
* Parse PRJCT.md content into sections
|
|
15783
|
+
*/
|
|
15784
|
+
parseSections(content) {
|
|
15785
|
+
const sections = [];
|
|
15786
|
+
const lines = content.split("\n");
|
|
15787
|
+
let currentSection = null;
|
|
15788
|
+
let currentContent = [];
|
|
15789
|
+
for (const line of lines) {
|
|
15790
|
+
const headerMatch = line.match(/^##\s+(.+)$/);
|
|
15791
|
+
if (headerMatch) {
|
|
15792
|
+
if (currentSection) {
|
|
15793
|
+
currentSection.content = currentContent.join("\n").trim();
|
|
15794
|
+
sections.push(currentSection);
|
|
15795
|
+
}
|
|
15796
|
+
const sectionName = headerMatch[1];
|
|
15797
|
+
const override = sectionName.includes("@override") || sectionName.includes("(override)");
|
|
15798
|
+
currentSection = {
|
|
15799
|
+
name: sectionName.replace(/@override|\(override\)/gi, "").trim(),
|
|
15800
|
+
content: "",
|
|
15801
|
+
override
|
|
15802
|
+
};
|
|
15803
|
+
currentContent = [];
|
|
15804
|
+
} else if (currentSection) {
|
|
15805
|
+
currentContent.push(line);
|
|
15806
|
+
}
|
|
15807
|
+
}
|
|
15808
|
+
if (currentSection) {
|
|
15809
|
+
currentSection.content = currentContent.join("\n").trim();
|
|
15810
|
+
sections.push(currentSection);
|
|
15811
|
+
}
|
|
15812
|
+
return sections;
|
|
15813
|
+
}
|
|
15814
|
+
/**
|
|
15815
|
+
* Scan for additional nested PRJCT.md files not in packages
|
|
15816
|
+
*/
|
|
15817
|
+
async scanForNestedContexts(dir, existing) {
|
|
15818
|
+
const found = [];
|
|
15819
|
+
const existingPaths = new Set(existing.map((c) => c.path));
|
|
15820
|
+
const scan = /* @__PURE__ */ __name(async (currentDir, depth) => {
|
|
15821
|
+
if (depth > 5) return;
|
|
15822
|
+
try {
|
|
15823
|
+
const entries = await fs32.readdir(currentDir, { withFileTypes: true });
|
|
15824
|
+
for (const entry of entries) {
|
|
15825
|
+
if (entry.name.startsWith(".") || entry.name === "node_modules" || entry.name === "dist" || entry.name === "build" || entry.name === "coverage") {
|
|
15826
|
+
continue;
|
|
15827
|
+
}
|
|
15828
|
+
if (entry.isDirectory()) {
|
|
15829
|
+
const subDir = path33.join(currentDir, entry.name);
|
|
15830
|
+
const prjctPath = path33.join(subDir, "PRJCT.md");
|
|
15831
|
+
if (await fileExists(prjctPath) && !existingPaths.has(prjctPath)) {
|
|
15832
|
+
const parent = this.findParentContext(prjctPath, existing.concat(found));
|
|
15833
|
+
const context2 = await this.loadContext(prjctPath, parent);
|
|
15834
|
+
found.push(context2);
|
|
15835
|
+
existingPaths.add(prjctPath);
|
|
15836
|
+
if (parent) {
|
|
15837
|
+
parent.children.push(context2);
|
|
15838
|
+
}
|
|
15839
|
+
}
|
|
15840
|
+
await scan(subDir, depth + 1);
|
|
15841
|
+
}
|
|
15842
|
+
}
|
|
15843
|
+
} catch {
|
|
15844
|
+
}
|
|
15845
|
+
}, "scan");
|
|
15846
|
+
await scan(dir, 0);
|
|
15847
|
+
return found;
|
|
15848
|
+
}
|
|
15849
|
+
/**
|
|
15850
|
+
* Find the parent context for a given path
|
|
15851
|
+
*/
|
|
15852
|
+
findParentContext(filePath, contexts) {
|
|
15853
|
+
const fileDir = path33.dirname(filePath);
|
|
15854
|
+
const sorted = [...contexts].sort((a, b) => b.depth - a.depth);
|
|
15855
|
+
for (const ctx of sorted) {
|
|
15856
|
+
const ctxDir = path33.dirname(ctx.path);
|
|
15857
|
+
if (fileDir.startsWith(ctxDir) && fileDir !== ctxDir) {
|
|
15858
|
+
return ctx;
|
|
15859
|
+
}
|
|
15860
|
+
}
|
|
15861
|
+
return null;
|
|
15862
|
+
}
|
|
15863
|
+
/**
|
|
15864
|
+
* Resolve context for a specific path by merging parent contexts
|
|
15865
|
+
* Deeper files take precedence (can override parent sections)
|
|
15866
|
+
*/
|
|
15867
|
+
async resolveContextForPath(targetPath) {
|
|
15868
|
+
const contexts = await this.discoverContextFiles();
|
|
15869
|
+
const targetDir = path33.resolve(targetPath);
|
|
15870
|
+
let bestMatch = null;
|
|
15871
|
+
for (const ctx of contexts) {
|
|
15872
|
+
const ctxDir = path33.dirname(ctx.path);
|
|
15873
|
+
if (targetDir.startsWith(ctxDir)) {
|
|
15874
|
+
if (!bestMatch || ctx.depth > bestMatch.depth) {
|
|
15875
|
+
bestMatch = ctx;
|
|
15876
|
+
}
|
|
15877
|
+
}
|
|
15878
|
+
}
|
|
15879
|
+
if (!bestMatch) {
|
|
15880
|
+
return {
|
|
15881
|
+
content: "",
|
|
15882
|
+
sources: [],
|
|
15883
|
+
overrides: []
|
|
15884
|
+
};
|
|
15885
|
+
}
|
|
15886
|
+
const chain = [];
|
|
15887
|
+
let current = bestMatch;
|
|
15888
|
+
while (current) {
|
|
15889
|
+
chain.unshift(current);
|
|
15890
|
+
current = current.parent;
|
|
15891
|
+
}
|
|
15892
|
+
return this.mergeContextChain(chain);
|
|
15893
|
+
}
|
|
15894
|
+
/**
|
|
15895
|
+
* Merge a chain of contexts following inheritance rules
|
|
15896
|
+
*/
|
|
15897
|
+
mergeContextChain(chain) {
|
|
15898
|
+
const mergedSections = /* @__PURE__ */ new Map();
|
|
15899
|
+
const sources = [];
|
|
15900
|
+
const overrides = [];
|
|
15901
|
+
for (const ctx of chain) {
|
|
15902
|
+
sources.push(ctx.relativePath);
|
|
15903
|
+
for (const section of ctx.sections) {
|
|
15904
|
+
if (section.override || !mergedSections.has(section.name)) {
|
|
15905
|
+
mergedSections.set(section.name, section.content);
|
|
15906
|
+
if (section.override) {
|
|
15907
|
+
overrides.push(`${ctx.relativePath}:${section.name}`);
|
|
15908
|
+
}
|
|
15909
|
+
} else {
|
|
15910
|
+
const existing = mergedSections.get(section.name) || "";
|
|
15911
|
+
mergedSections.set(section.name, `${existing}
|
|
15912
|
+
|
|
15913
|
+
${section.content}`);
|
|
15914
|
+
}
|
|
15915
|
+
}
|
|
15916
|
+
}
|
|
15917
|
+
const parts = [];
|
|
15918
|
+
for (const [name, content] of mergedSections) {
|
|
15919
|
+
parts.push(`## ${name}
|
|
15920
|
+
|
|
15921
|
+
${content}`);
|
|
15922
|
+
}
|
|
15923
|
+
return {
|
|
15924
|
+
content: parts.join("\n\n---\n\n"),
|
|
15925
|
+
sources,
|
|
15926
|
+
overrides
|
|
15927
|
+
};
|
|
15928
|
+
}
|
|
15929
|
+
/**
|
|
15930
|
+
* Get context for a specific monorepo package
|
|
15931
|
+
*/
|
|
15932
|
+
async getPackageContext(packageName) {
|
|
15933
|
+
if (!this.monoInfo?.isMonorepo) {
|
|
15934
|
+
return null;
|
|
15935
|
+
}
|
|
15936
|
+
const pkg = this.monoInfo.packages.find((p) => p.name === packageName);
|
|
15937
|
+
if (!pkg) {
|
|
15938
|
+
return null;
|
|
15939
|
+
}
|
|
15940
|
+
return this.resolveContextForPath(pkg.path);
|
|
15941
|
+
}
|
|
15942
|
+
/**
|
|
15943
|
+
* Get all package contexts in the monorepo
|
|
15944
|
+
*/
|
|
15945
|
+
async getAllPackageContexts() {
|
|
15946
|
+
const results = /* @__PURE__ */ new Map();
|
|
15947
|
+
if (!this.monoInfo?.isMonorepo) {
|
|
15948
|
+
return results;
|
|
15949
|
+
}
|
|
15950
|
+
for (const pkg of this.monoInfo.packages) {
|
|
15951
|
+
const ctx = await this.resolveContextForPath(pkg.path);
|
|
15952
|
+
results.set(pkg.name, ctx);
|
|
15953
|
+
}
|
|
15954
|
+
return results;
|
|
15955
|
+
}
|
|
15956
|
+
};
|
|
15957
|
+
}
|
|
15958
|
+
});
|
|
15959
|
+
|
|
15559
15960
|
// core/services/project-index.ts
|
|
15560
15961
|
import { exec as exec7 } from "node:child_process";
|
|
15561
15962
|
import { promisify as promisify7 } from "node:util";
|
|
@@ -16039,16 +16440,16 @@ var init_onboarding = __esm({
|
|
|
16039
16440
|
* Detect project type from file system
|
|
16040
16441
|
*/
|
|
16041
16442
|
async detectProjectType() {
|
|
16042
|
-
const
|
|
16043
|
-
const
|
|
16443
|
+
const fs48 = await import("node:fs/promises");
|
|
16444
|
+
const path57 = await import("node:path");
|
|
16044
16445
|
try {
|
|
16045
|
-
const files = await
|
|
16446
|
+
const files = await fs48.readdir(this.projectPath);
|
|
16046
16447
|
if (files.includes("turbo.json") || files.includes("lerna.json") || files.includes("nx.json")) {
|
|
16047
16448
|
return "monorepo";
|
|
16048
16449
|
}
|
|
16049
16450
|
if (files.includes("package.json")) {
|
|
16050
|
-
const pkgPath =
|
|
16051
|
-
const pkgContent = await
|
|
16451
|
+
const pkgPath = path57.join(this.projectPath, "package.json");
|
|
16452
|
+
const pkgContent = await fs48.readFile(pkgPath, "utf-8");
|
|
16052
16453
|
const pkg = JSON.parse(pkgContent);
|
|
16053
16454
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
16054
16455
|
if (pkg.bin) return "cli-tool";
|
|
@@ -16084,32 +16485,32 @@ var init_onboarding = __esm({
|
|
|
16084
16485
|
* Detect installed AI agents from config files
|
|
16085
16486
|
*/
|
|
16086
16487
|
async detectInstalledAgents() {
|
|
16087
|
-
const
|
|
16088
|
-
const
|
|
16488
|
+
const fs48 = await import("node:fs/promises");
|
|
16489
|
+
const path57 = await import("node:path");
|
|
16089
16490
|
const os17 = await import("node:os");
|
|
16090
16491
|
const agents = [];
|
|
16091
16492
|
try {
|
|
16092
|
-
await
|
|
16493
|
+
await fs48.access(path57.join(os17.homedir(), ".claude"));
|
|
16093
16494
|
agents.push("claude");
|
|
16094
16495
|
} catch {
|
|
16095
16496
|
}
|
|
16096
16497
|
try {
|
|
16097
|
-
await
|
|
16498
|
+
await fs48.access(path57.join(this.projectPath, ".cursorrules"));
|
|
16098
16499
|
agents.push("cursor");
|
|
16099
16500
|
} catch {
|
|
16100
16501
|
}
|
|
16101
16502
|
try {
|
|
16102
|
-
await
|
|
16503
|
+
await fs48.access(path57.join(this.projectPath, ".windsurfrules"));
|
|
16103
16504
|
agents.push("windsurf");
|
|
16104
16505
|
} catch {
|
|
16105
16506
|
}
|
|
16106
16507
|
try {
|
|
16107
|
-
await
|
|
16508
|
+
await fs48.access(path57.join(this.projectPath, ".github", "copilot-instructions.md"));
|
|
16108
16509
|
agents.push("copilot");
|
|
16109
16510
|
} catch {
|
|
16110
16511
|
}
|
|
16111
16512
|
try {
|
|
16112
|
-
await
|
|
16513
|
+
await fs48.access(path57.join(os17.homedir(), ".gemini"));
|
|
16113
16514
|
agents.push("gemini");
|
|
16114
16515
|
} catch {
|
|
16115
16516
|
}
|
|
@@ -16119,17 +16520,17 @@ var init_onboarding = __esm({
|
|
|
16119
16520
|
* Detect tech stack from project files
|
|
16120
16521
|
*/
|
|
16121
16522
|
async detectStack() {
|
|
16122
|
-
const
|
|
16123
|
-
const
|
|
16523
|
+
const fs48 = await import("node:fs/promises");
|
|
16524
|
+
const path57 = await import("node:path");
|
|
16124
16525
|
const stack = {
|
|
16125
16526
|
language: "Unknown",
|
|
16126
16527
|
technologies: []
|
|
16127
16528
|
};
|
|
16128
16529
|
try {
|
|
16129
|
-
const files = await
|
|
16530
|
+
const files = await fs48.readdir(this.projectPath);
|
|
16130
16531
|
if (files.includes("package.json")) {
|
|
16131
|
-
const pkgPath =
|
|
16132
|
-
const pkgContent = await
|
|
16532
|
+
const pkgPath = path57.join(this.projectPath, "package.json");
|
|
16533
|
+
const pkgContent = await fs48.readFile(pkgPath, "utf-8");
|
|
16133
16534
|
const pkg = JSON.parse(pkgContent);
|
|
16134
16535
|
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
16135
16536
|
stack.language = deps.typescript ? "TypeScript" : "JavaScript";
|
|
@@ -16236,14 +16637,14 @@ var init_wizard = __esm({
|
|
|
16236
16637
|
|
|
16237
16638
|
// core/context/generator.ts
|
|
16238
16639
|
import { exec as exec8 } from "node:child_process";
|
|
16239
|
-
import
|
|
16240
|
-
import
|
|
16640
|
+
import fs33 from "node:fs/promises";
|
|
16641
|
+
import path34 from "node:path";
|
|
16241
16642
|
import { promisify as promisify8 } from "node:util";
|
|
16242
16643
|
async function generateContext(projectId, repoPath) {
|
|
16243
16644
|
const _globalPath = path_manager_default.getGlobalProjectPath(projectId);
|
|
16244
16645
|
const contextPath = path_manager_default.getContextPath(projectId);
|
|
16245
16646
|
const storage = getStorage(projectId);
|
|
16246
|
-
await
|
|
16647
|
+
await fs33.mkdir(contextPath, { recursive: true });
|
|
16247
16648
|
const project = await storage.read(["project"]) || {};
|
|
16248
16649
|
const taskPaths = await storage.list(["task"]);
|
|
16249
16650
|
const featurePaths = await storage.list(["feature"]);
|
|
@@ -16325,8 +16726,8 @@ async function getPackageData(repoPath) {
|
|
|
16325
16726
|
scripts: {}
|
|
16326
16727
|
};
|
|
16327
16728
|
try {
|
|
16328
|
-
const pkgPath =
|
|
16329
|
-
const pkg = JSON.parse(await
|
|
16729
|
+
const pkgPath = path34.join(repoPath, "package.json");
|
|
16730
|
+
const pkg = JSON.parse(await fs33.readFile(pkgPath, "utf-8"));
|
|
16330
16731
|
data.dependencies = pkg.dependencies || {};
|
|
16331
16732
|
data.devDependencies = pkg.devDependencies || {};
|
|
16332
16733
|
data.scripts = pkg.scripts || {};
|
|
@@ -16335,7 +16736,7 @@ async function getPackageData(repoPath) {
|
|
|
16335
16736
|
return data;
|
|
16336
16737
|
}
|
|
16337
16738
|
async function generateClaudeMd(contextPath, projectId, project, tasks, features, ideas, agents, gitData, pkgData, repoPath) {
|
|
16338
|
-
const projectName = project.name ||
|
|
16739
|
+
const projectName = project.name || path34.basename(repoPath);
|
|
16339
16740
|
const currentTask = tasks.find((t) => t.status === "in_progress");
|
|
16340
16741
|
const pendingTasks = tasks.filter((t) => t.status === "pending");
|
|
16341
16742
|
const activeFeatures = features.filter((f) => f.status === "in_progress" || f.status === "active");
|
|
@@ -16410,7 +16811,7 @@ ${agents.length > 0 ? agents.map((a) => `- **${a.name}**: ${a.role || "Specialis
|
|
|
16410
16811
|
\u2514\u2500\u2500 pending.json
|
|
16411
16812
|
\`\`\`
|
|
16412
16813
|
`;
|
|
16413
|
-
await
|
|
16814
|
+
await fs33.writeFile(path34.join(contextPath, "CLAUDE.md"), content, "utf-8");
|
|
16414
16815
|
}
|
|
16415
16816
|
async function generateNowMd(contextPath, tasks) {
|
|
16416
16817
|
const currentTask = tasks.find((t) => t.status === "in_progress");
|
|
@@ -16425,7 +16826,7 @@ async function generateNowMd(contextPath, tasks) {
|
|
|
16425
16826
|
|
|
16426
16827
|
_No active task. Use /p:now to start._
|
|
16427
16828
|
`;
|
|
16428
|
-
await
|
|
16829
|
+
await fs33.writeFile(path34.join(contextPath, "now.md"), content, "utf-8");
|
|
16429
16830
|
}
|
|
16430
16831
|
async function generateQueueMd(contextPath, tasks) {
|
|
16431
16832
|
const pendingTasks = tasks.filter((t) => t.status === "pending");
|
|
@@ -16433,7 +16834,7 @@ async function generateQueueMd(contextPath, tasks) {
|
|
|
16433
16834
|
|
|
16434
16835
|
${pendingTasks.length > 0 ? pendingTasks.map((t, i) => `${i + 1}. ${t.description}${t.priority ? ` [${t.priority}]` : ""}`).join("\n") : "_Empty queue. Use /p:next to add tasks._"}
|
|
16435
16836
|
`;
|
|
16436
|
-
await
|
|
16837
|
+
await fs33.writeFile(path34.join(contextPath, "queue.md"), content, "utf-8");
|
|
16437
16838
|
}
|
|
16438
16839
|
async function generateSummaryMd(contextPath, project, gitData, pkgData) {
|
|
16439
16840
|
const content = `# PROJECT SUMMARY
|
|
@@ -16453,7 +16854,7 @@ async function generateSummaryMd(contextPath, project, gitData, pkgData) {
|
|
|
16453
16854
|
- Production: ${Object.keys(pkgData.dependencies).length}
|
|
16454
16855
|
- Dev: ${Object.keys(pkgData.devDependencies).length}
|
|
16455
16856
|
`;
|
|
16456
|
-
await
|
|
16857
|
+
await fs33.writeFile(path34.join(contextPath, "summary.md"), content, "utf-8");
|
|
16457
16858
|
}
|
|
16458
16859
|
var execAsync4;
|
|
16459
16860
|
var init_generator = __esm({
|
|
@@ -16474,8 +16875,8 @@ var init_generator = __esm({
|
|
|
16474
16875
|
|
|
16475
16876
|
// core/domain/analyzer.ts
|
|
16476
16877
|
import { exec as execCallback5 } from "node:child_process";
|
|
16477
|
-
import
|
|
16478
|
-
import
|
|
16878
|
+
import fs34 from "node:fs/promises";
|
|
16879
|
+
import path35 from "node:path";
|
|
16479
16880
|
import { promisify as promisify9 } from "node:util";
|
|
16480
16881
|
var exec9, CodebaseAnalyzer, analyzer, analyzer_default2;
|
|
16481
16882
|
var init_analyzer2 = __esm({
|
|
@@ -16499,8 +16900,8 @@ var init_analyzer2 = __esm({
|
|
|
16499
16900
|
*/
|
|
16500
16901
|
async readPackageJson() {
|
|
16501
16902
|
try {
|
|
16502
|
-
const packagePath =
|
|
16503
|
-
const content = await
|
|
16903
|
+
const packagePath = path35.join(this.projectPath, "package.json");
|
|
16904
|
+
const content = await fs34.readFile(packagePath, "utf-8");
|
|
16504
16905
|
return JSON.parse(content);
|
|
16505
16906
|
} catch (error) {
|
|
16506
16907
|
if (isNotFoundError(error) || error instanceof SyntaxError) {
|
|
@@ -16514,8 +16915,8 @@ var init_analyzer2 = __esm({
|
|
|
16514
16915
|
*/
|
|
16515
16916
|
async readCargoToml() {
|
|
16516
16917
|
try {
|
|
16517
|
-
const cargoPath =
|
|
16518
|
-
return await
|
|
16918
|
+
const cargoPath = path35.join(this.projectPath, "Cargo.toml");
|
|
16919
|
+
return await fs34.readFile(cargoPath, "utf-8");
|
|
16519
16920
|
} catch (error) {
|
|
16520
16921
|
if (isNotFoundError(error)) {
|
|
16521
16922
|
return null;
|
|
@@ -16528,8 +16929,8 @@ var init_analyzer2 = __esm({
|
|
|
16528
16929
|
*/
|
|
16529
16930
|
async readRequirements() {
|
|
16530
16931
|
try {
|
|
16531
|
-
const reqPath =
|
|
16532
|
-
return await
|
|
16932
|
+
const reqPath = path35.join(this.projectPath, "requirements.txt");
|
|
16933
|
+
return await fs34.readFile(reqPath, "utf-8");
|
|
16533
16934
|
} catch (error) {
|
|
16534
16935
|
if (isNotFoundError(error)) {
|
|
16535
16936
|
return null;
|
|
@@ -16542,8 +16943,8 @@ var init_analyzer2 = __esm({
|
|
|
16542
16943
|
*/
|
|
16543
16944
|
async readGoMod() {
|
|
16544
16945
|
try {
|
|
16545
|
-
const goModPath =
|
|
16546
|
-
return await
|
|
16946
|
+
const goModPath = path35.join(this.projectPath, "go.mod");
|
|
16947
|
+
return await fs34.readFile(goModPath, "utf-8");
|
|
16547
16948
|
} catch (error) {
|
|
16548
16949
|
if (isNotFoundError(error)) {
|
|
16549
16950
|
return null;
|
|
@@ -16556,8 +16957,8 @@ var init_analyzer2 = __esm({
|
|
|
16556
16957
|
*/
|
|
16557
16958
|
async readGemfile() {
|
|
16558
16959
|
try {
|
|
16559
|
-
const gemfilePath =
|
|
16560
|
-
return await
|
|
16960
|
+
const gemfilePath = path35.join(this.projectPath, "Gemfile");
|
|
16961
|
+
return await fs34.readFile(gemfilePath, "utf-8");
|
|
16561
16962
|
} catch (error) {
|
|
16562
16963
|
if (isNotFoundError(error)) {
|
|
16563
16964
|
return null;
|
|
@@ -16570,8 +16971,8 @@ var init_analyzer2 = __esm({
|
|
|
16570
16971
|
*/
|
|
16571
16972
|
async readMixExs() {
|
|
16572
16973
|
try {
|
|
16573
|
-
const mixPath =
|
|
16574
|
-
return await
|
|
16974
|
+
const mixPath = path35.join(this.projectPath, "mix.exs");
|
|
16975
|
+
return await fs34.readFile(mixPath, "utf-8");
|
|
16575
16976
|
} catch (error) {
|
|
16576
16977
|
if (isNotFoundError(error)) {
|
|
16577
16978
|
return null;
|
|
@@ -16584,8 +16985,8 @@ var init_analyzer2 = __esm({
|
|
|
16584
16985
|
*/
|
|
16585
16986
|
async readPomXml() {
|
|
16586
16987
|
try {
|
|
16587
|
-
const pomPath =
|
|
16588
|
-
return await
|
|
16988
|
+
const pomPath = path35.join(this.projectPath, "pom.xml");
|
|
16989
|
+
return await fs34.readFile(pomPath, "utf-8");
|
|
16589
16990
|
} catch (error) {
|
|
16590
16991
|
if (isNotFoundError(error)) {
|
|
16591
16992
|
return null;
|
|
@@ -16598,8 +16999,8 @@ var init_analyzer2 = __esm({
|
|
|
16598
16999
|
*/
|
|
16599
17000
|
async readComposerJson() {
|
|
16600
17001
|
try {
|
|
16601
|
-
const composerPath =
|
|
16602
|
-
const content = await
|
|
17002
|
+
const composerPath = path35.join(this.projectPath, "composer.json");
|
|
17003
|
+
const content = await fs34.readFile(composerPath, "utf-8");
|
|
16603
17004
|
return JSON.parse(content);
|
|
16604
17005
|
} catch (error) {
|
|
16605
17006
|
if (isNotFoundError(error) || error instanceof SyntaxError) {
|
|
@@ -16613,8 +17014,8 @@ var init_analyzer2 = __esm({
|
|
|
16613
17014
|
*/
|
|
16614
17015
|
async readPyprojectToml() {
|
|
16615
17016
|
try {
|
|
16616
|
-
const pyprojectPath =
|
|
16617
|
-
return await
|
|
17017
|
+
const pyprojectPath = path35.join(this.projectPath, "pyproject.toml");
|
|
17018
|
+
return await fs34.readFile(pyprojectPath, "utf-8");
|
|
16618
17019
|
} catch (error) {
|
|
16619
17020
|
if (isNotFoundError(error)) {
|
|
16620
17021
|
return null;
|
|
@@ -16650,7 +17051,7 @@ var init_analyzer2 = __esm({
|
|
|
16650
17051
|
*/
|
|
16651
17052
|
async listConfigFiles() {
|
|
16652
17053
|
try {
|
|
16653
|
-
const entries = await
|
|
17054
|
+
const entries = await fs34.readdir(this.projectPath);
|
|
16654
17055
|
const configPatterns = [
|
|
16655
17056
|
/^package\.json$/,
|
|
16656
17057
|
/^Cargo\.toml$/,
|
|
@@ -16680,7 +17081,7 @@ var init_analyzer2 = __esm({
|
|
|
16680
17081
|
*/
|
|
16681
17082
|
async listDirectories() {
|
|
16682
17083
|
try {
|
|
16683
|
-
const entries = await
|
|
17084
|
+
const entries = await fs34.readdir(this.projectPath, { withFileTypes: true });
|
|
16684
17085
|
return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name).filter((name) => !name.startsWith(".") && name !== "node_modules");
|
|
16685
17086
|
} catch (error) {
|
|
16686
17087
|
if (isNotFoundError(error)) {
|
|
@@ -16751,7 +17152,7 @@ var init_analyzer2 = __esm({
|
|
|
16751
17152
|
*/
|
|
16752
17153
|
async fileExists(filename) {
|
|
16753
17154
|
try {
|
|
16754
|
-
await
|
|
17155
|
+
await fs34.access(path35.join(this.projectPath, filename));
|
|
16755
17156
|
return true;
|
|
16756
17157
|
} catch (error) {
|
|
16757
17158
|
if (isNotFoundError(error)) {
|
|
@@ -16765,8 +17166,8 @@ var init_analyzer2 = __esm({
|
|
|
16765
17166
|
*/
|
|
16766
17167
|
async readFile(relativePath) {
|
|
16767
17168
|
try {
|
|
16768
|
-
const fullPath =
|
|
16769
|
-
return await
|
|
17169
|
+
const fullPath = path35.join(this.projectPath, relativePath);
|
|
17170
|
+
return await fs34.readFile(fullPath, "utf-8");
|
|
16770
17171
|
} catch (error) {
|
|
16771
17172
|
if (isNotFoundError(error)) {
|
|
16772
17173
|
return null;
|
|
@@ -17014,8 +17415,8 @@ var analysis_exports = {};
|
|
|
17014
17415
|
__export(analysis_exports, {
|
|
17015
17416
|
AnalysisCommands: () => AnalysisCommands
|
|
17016
17417
|
});
|
|
17017
|
-
import
|
|
17018
|
-
import
|
|
17418
|
+
import fs35 from "node:fs/promises";
|
|
17419
|
+
import path36 from "node:path";
|
|
17019
17420
|
import prompts2 from "prompts";
|
|
17020
17421
|
var AnalysisCommands;
|
|
17021
17422
|
var init_analysis2 = __esm({
|
|
@@ -17102,7 +17503,7 @@ var init_analysis2 = __esm({
|
|
|
17102
17503
|
lines.push("# Repository Analysis\n");
|
|
17103
17504
|
lines.push(`Generated: ${(/* @__PURE__ */ new Date()).toLocaleString()}
|
|
17104
17505
|
`);
|
|
17105
|
-
const projectName =
|
|
17506
|
+
const projectName = path36.basename(projectPath);
|
|
17106
17507
|
lines.push(`## Project: ${projectName}
|
|
17107
17508
|
`);
|
|
17108
17509
|
lines.push("## Stack Detected\n");
|
|
@@ -17210,10 +17611,42 @@ var init_analysis2 = __esm({
|
|
|
17210
17611
|
}
|
|
17211
17612
|
const globalPath = path_manager_default.getGlobalProjectPath(projectId);
|
|
17212
17613
|
const startTime = Date.now();
|
|
17213
|
-
|
|
17614
|
+
if (options.package) {
|
|
17615
|
+
const monoInfo = await path_manager_default.detectMonorepo(projectPath);
|
|
17616
|
+
if (!monoInfo.isMonorepo) {
|
|
17617
|
+
return {
|
|
17618
|
+
success: false,
|
|
17619
|
+
error: "Not a monorepo. --package flag only works in monorepos."
|
|
17620
|
+
};
|
|
17621
|
+
}
|
|
17622
|
+
const pkg = monoInfo.packages.find(
|
|
17623
|
+
(p) => p.name === options.package || p.relativePath === options.package
|
|
17624
|
+
);
|
|
17625
|
+
if (!pkg) {
|
|
17626
|
+
const available = monoInfo.packages.map((p) => p.name).join(", ");
|
|
17627
|
+
return {
|
|
17628
|
+
success: false,
|
|
17629
|
+
error: `Package "${options.package}" not found. Available: ${available}`
|
|
17630
|
+
};
|
|
17631
|
+
}
|
|
17632
|
+
const result2 = await syncService.sync(projectPath, {
|
|
17633
|
+
aiTools: options.aiTools,
|
|
17634
|
+
packagePath: pkg.path,
|
|
17635
|
+
packageName: pkg.name
|
|
17636
|
+
});
|
|
17637
|
+
if (options.json) {
|
|
17638
|
+
console.log(
|
|
17639
|
+
JSON.stringify({ success: result2.success, package: pkg.name, path: pkg.relativePath })
|
|
17640
|
+
);
|
|
17641
|
+
} else {
|
|
17642
|
+
output_default.done(`Synced package: ${pkg.name}`);
|
|
17643
|
+
}
|
|
17644
|
+
return { success: result2.success };
|
|
17645
|
+
}
|
|
17646
|
+
const claudeMdPath = path36.join(globalPath, "context", "CLAUDE.md");
|
|
17214
17647
|
let existingContent = null;
|
|
17215
17648
|
try {
|
|
17216
|
-
existingContent = await
|
|
17649
|
+
existingContent = await fs35.readFile(claudeMdPath, "utf-8");
|
|
17217
17650
|
} catch {
|
|
17218
17651
|
}
|
|
17219
17652
|
const isNonInteractive = !process.stdin.isTTY || options.json;
|
|
@@ -17232,7 +17665,7 @@ var init_analysis2 = __esm({
|
|
|
17232
17665
|
}
|
|
17233
17666
|
let newContent;
|
|
17234
17667
|
try {
|
|
17235
|
-
newContent = await
|
|
17668
|
+
newContent = await fs35.readFile(claudeMdPath, "utf-8");
|
|
17236
17669
|
} catch {
|
|
17237
17670
|
newContent = "";
|
|
17238
17671
|
}
|
|
@@ -17463,7 +17896,7 @@ ${formatFullDiff(diff)}`);
|
|
|
17463
17896
|
let projectName = "Unknown";
|
|
17464
17897
|
try {
|
|
17465
17898
|
const projectJson = JSON.parse(
|
|
17466
|
-
await
|
|
17899
|
+
await fs35.readFile(path36.join(globalPath, "project.json"), "utf-8")
|
|
17467
17900
|
);
|
|
17468
17901
|
projectName = projectJson.name || "Unknown";
|
|
17469
17902
|
} catch {
|
|
@@ -17714,7 +18147,7 @@ var planning_exports = {};
|
|
|
17714
18147
|
__export(planning_exports, {
|
|
17715
18148
|
PlanningCommands: () => PlanningCommands
|
|
17716
18149
|
});
|
|
17717
|
-
import
|
|
18150
|
+
import path37 from "node:path";
|
|
17718
18151
|
async function getAnalysisCommands() {
|
|
17719
18152
|
if (!_analysisCommands) {
|
|
17720
18153
|
const { AnalysisCommands: AnalysisCommands2 } = await Promise.resolve().then(() => (init_analysis2(), analysis_exports));
|
|
@@ -17821,7 +18254,7 @@ var init_planning = __esm({
|
|
|
17821
18254
|
);
|
|
17822
18255
|
}
|
|
17823
18256
|
for (const [filePath, content] of Object.entries(baseFiles)) {
|
|
17824
|
-
await tool_registry_default.get("Write")(
|
|
18257
|
+
await tool_registry_default.get("Write")(path37.join(globalPath, filePath), content);
|
|
17825
18258
|
}
|
|
17826
18259
|
const isEmpty = await this._detectEmptyDirectory(projectPath);
|
|
17827
18260
|
const hasCode = await this._detectExistingCode(projectPath);
|
|
@@ -17848,7 +18281,7 @@ var init_planning = __esm({
|
|
|
17848
18281
|
return { success: true, mode: "blank_no_idea", projectId, wizard: wizardResult };
|
|
17849
18282
|
}
|
|
17850
18283
|
output_default.spin("architect mode...");
|
|
17851
|
-
const sessionPath =
|
|
18284
|
+
const sessionPath = path37.join(globalPath, "planning", "architect-session.md");
|
|
17852
18285
|
const sessionContent = `# Architect Session
|
|
17853
18286
|
|
|
17854
18287
|
## Idea
|
|
@@ -18033,7 +18466,7 @@ Generated: ${(/* @__PURE__ */ new Date()).toLocaleString()}
|
|
|
18033
18466
|
if (!initResult.success) return initResult;
|
|
18034
18467
|
console.log("\u{1F3D7}\uFE0F Architect Mode - Code Generation\n");
|
|
18035
18468
|
const globalPath = await this.getGlobalProjectPath(projectPath);
|
|
18036
|
-
const planPath =
|
|
18469
|
+
const planPath = path37.join(globalPath, "planning", "architect-session.md");
|
|
18037
18470
|
let planContent;
|
|
18038
18471
|
try {
|
|
18039
18472
|
planContent = await file_helper_exports.readFile(planPath);
|
|
@@ -18108,7 +18541,7 @@ ${"=".repeat(60)}`);
|
|
|
18108
18541
|
if (isComplex) {
|
|
18109
18542
|
output_default.spin("analyzing idea...");
|
|
18110
18543
|
const globalPath = path_manager_default.getGlobalProjectPath(projectId);
|
|
18111
|
-
const sessionPath =
|
|
18544
|
+
const sessionPath = path37.join(globalPath, "planning", "architect-session.md");
|
|
18112
18545
|
const sessionContent = `# Architect Session
|
|
18113
18546
|
|
|
18114
18547
|
## Idea
|
|
@@ -18164,10 +18597,10 @@ Generated: ${(/* @__PURE__ */ new Date()).toLocaleString()}
|
|
|
18164
18597
|
if (!featureName) {
|
|
18165
18598
|
output_default.spin("loading specs...");
|
|
18166
18599
|
const globalPath2 = path_manager_default.getGlobalProjectPath(projectId);
|
|
18167
|
-
const specsPath2 =
|
|
18600
|
+
const specsPath2 = path37.join(globalPath2, "planning", "specs");
|
|
18168
18601
|
try {
|
|
18169
|
-
const
|
|
18170
|
-
const files = await
|
|
18602
|
+
const fs48 = await import("node:fs/promises");
|
|
18603
|
+
const files = await fs48.readdir(specsPath2);
|
|
18171
18604
|
const specs = files.filter((f) => f.endsWith(".md") && f !== ".gitkeep");
|
|
18172
18605
|
if (specs.length === 0) {
|
|
18173
18606
|
output_default.warn("no specs yet");
|
|
@@ -18190,10 +18623,10 @@ Generated: ${(/* @__PURE__ */ new Date()).toLocaleString()}
|
|
|
18190
18623
|
}
|
|
18191
18624
|
output_default.spin("creating spec...");
|
|
18192
18625
|
const globalPath = path_manager_default.getGlobalProjectPath(projectId);
|
|
18193
|
-
const specsPath =
|
|
18626
|
+
const specsPath = path37.join(globalPath, "planning", "specs");
|
|
18194
18627
|
await file_helper_exports.ensureDir(specsPath);
|
|
18195
18628
|
const slug = featureName.toLowerCase().replace(/\s+/g, "-");
|
|
18196
|
-
const specFile =
|
|
18629
|
+
const specFile = path37.join(specsPath, `${slug}.md`);
|
|
18197
18630
|
const specContent = `# Specification: ${featureName}
|
|
18198
18631
|
|
|
18199
18632
|
## Overview
|
|
@@ -18598,9 +19031,9 @@ var init_formatters = __esm({
|
|
|
18598
19031
|
|
|
18599
19032
|
// core/ai-tools/registry.ts
|
|
18600
19033
|
import { execSync as execSync4 } from "node:child_process";
|
|
18601
|
-
import
|
|
19034
|
+
import fs36 from "node:fs";
|
|
18602
19035
|
import os11 from "node:os";
|
|
18603
|
-
import
|
|
19036
|
+
import path38 from "node:path";
|
|
18604
19037
|
function getAIToolConfig(id) {
|
|
18605
19038
|
return AI_TOOLS[id] || null;
|
|
18606
19039
|
}
|
|
@@ -18617,16 +19050,16 @@ function detectInstalledTools(repoPath = process.cwd()) {
|
|
|
18617
19050
|
if (commandExists("claude")) {
|
|
18618
19051
|
detected.push("claude");
|
|
18619
19052
|
}
|
|
18620
|
-
if (commandExists("cursor") ||
|
|
19053
|
+
if (commandExists("cursor") || fs36.existsSync(path38.join(repoPath, ".cursor"))) {
|
|
18621
19054
|
detected.push("cursor");
|
|
18622
19055
|
}
|
|
18623
|
-
if (
|
|
19056
|
+
if (fs36.existsSync(path38.join(repoPath, ".github"))) {
|
|
18624
19057
|
detected.push("copilot");
|
|
18625
19058
|
}
|
|
18626
|
-
if (commandExists("windsurf") ||
|
|
19059
|
+
if (commandExists("windsurf") || fs36.existsSync(path38.join(repoPath, ".windsurf"))) {
|
|
18627
19060
|
detected.push("windsurf");
|
|
18628
19061
|
}
|
|
18629
|
-
if (
|
|
19062
|
+
if (fs36.existsSync(path38.join(repoPath, ".continue")) || fs36.existsSync(path38.join(os11.homedir(), ".continue"))) {
|
|
18630
19063
|
detected.push("continue");
|
|
18631
19064
|
}
|
|
18632
19065
|
return detected;
|
|
@@ -18702,8 +19135,8 @@ var init_registry = __esm({
|
|
|
18702
19135
|
});
|
|
18703
19136
|
|
|
18704
19137
|
// core/ai-tools/generator.ts
|
|
18705
|
-
import
|
|
18706
|
-
import
|
|
19138
|
+
import fs37 from "node:fs/promises";
|
|
19139
|
+
import path39 from "node:path";
|
|
18707
19140
|
async function generateAIToolContexts(context2, globalPath, repoPath, toolIds = DEFAULT_AI_TOOLS) {
|
|
18708
19141
|
const results = [];
|
|
18709
19142
|
for (const toolId of toolIds) {
|
|
@@ -18738,13 +19171,13 @@ async function generateForTool(context2, config, globalPath, repoPath) {
|
|
|
18738
19171
|
let content = formatter(context2, config);
|
|
18739
19172
|
let outputPath;
|
|
18740
19173
|
if (config.outputPath === "repo") {
|
|
18741
|
-
outputPath =
|
|
19174
|
+
outputPath = path39.join(repoPath, config.outputFile);
|
|
18742
19175
|
} else {
|
|
18743
|
-
outputPath =
|
|
19176
|
+
outputPath = path39.join(globalPath, "context", config.outputFile);
|
|
18744
19177
|
}
|
|
18745
|
-
await
|
|
19178
|
+
await fs37.mkdir(path39.dirname(outputPath), { recursive: true });
|
|
18746
19179
|
try {
|
|
18747
|
-
const existingContent = await
|
|
19180
|
+
const existingContent = await fs37.readFile(outputPath, "utf-8");
|
|
18748
19181
|
const validation = validatePreserveBlocks(existingContent);
|
|
18749
19182
|
if (!validation.valid) {
|
|
18750
19183
|
console.warn(`\u26A0\uFE0F ${config.outputFile} has invalid preserve blocks:`);
|
|
@@ -18755,7 +19188,7 @@ async function generateForTool(context2, config, globalPath, repoPath) {
|
|
|
18755
19188
|
content = mergePreservedSections(content, existingContent);
|
|
18756
19189
|
} catch {
|
|
18757
19190
|
}
|
|
18758
|
-
await
|
|
19191
|
+
await fs37.writeFile(outputPath, content, "utf-8");
|
|
18759
19192
|
return {
|
|
18760
19193
|
toolId: config.id,
|
|
18761
19194
|
outputFile: config.outputFile,
|
|
@@ -18794,14 +19227,16 @@ var init_ai_tools = __esm({
|
|
|
18794
19227
|
});
|
|
18795
19228
|
|
|
18796
19229
|
// core/services/context-generator.ts
|
|
18797
|
-
import
|
|
18798
|
-
import
|
|
19230
|
+
import fs38 from "node:fs/promises";
|
|
19231
|
+
import path40 from "node:path";
|
|
18799
19232
|
var ContextFileGenerator;
|
|
18800
19233
|
var init_context_generator = __esm({
|
|
18801
19234
|
"core/services/context-generator.ts"() {
|
|
18802
19235
|
"use strict";
|
|
19236
|
+
init_path_manager();
|
|
18803
19237
|
init_date_helper();
|
|
18804
19238
|
init_preserve_sections();
|
|
19239
|
+
init_nested_context_resolver();
|
|
18805
19240
|
ContextFileGenerator = class {
|
|
18806
19241
|
static {
|
|
18807
19242
|
__name(this, "ContextFileGenerator");
|
|
@@ -18817,10 +19252,10 @@ var init_context_generator = __esm({
|
|
|
18817
19252
|
async writeWithPreservation(filePath, content) {
|
|
18818
19253
|
let finalContent = content;
|
|
18819
19254
|
try {
|
|
18820
|
-
const existingContent = await
|
|
19255
|
+
const existingContent = await fs38.readFile(filePath, "utf-8");
|
|
18821
19256
|
const validation = validatePreserveBlocks(existingContent);
|
|
18822
19257
|
if (!validation.valid) {
|
|
18823
|
-
const filename =
|
|
19258
|
+
const filename = path40.basename(filePath);
|
|
18824
19259
|
console.warn(`\u26A0\uFE0F ${filename} has invalid preserve blocks:`);
|
|
18825
19260
|
for (const error of validation.errors) {
|
|
18826
19261
|
console.warn(` ${error}`);
|
|
@@ -18829,13 +19264,13 @@ var init_context_generator = __esm({
|
|
|
18829
19264
|
finalContent = mergePreservedSections(content, existingContent);
|
|
18830
19265
|
} catch {
|
|
18831
19266
|
}
|
|
18832
|
-
await
|
|
19267
|
+
await fs38.writeFile(filePath, finalContent, "utf-8");
|
|
18833
19268
|
}
|
|
18834
19269
|
/**
|
|
18835
19270
|
* Generate all context files in parallel
|
|
18836
19271
|
*/
|
|
18837
19272
|
async generate(git, stats, commands, agents) {
|
|
18838
|
-
const contextPath =
|
|
19273
|
+
const contextPath = path40.join(this.config.globalPath, "context");
|
|
18839
19274
|
await Promise.all([
|
|
18840
19275
|
this.generateClaudeMd(contextPath, git, stats, commands, agents),
|
|
18841
19276
|
this.generateNowMd(contextPath),
|
|
@@ -18929,7 +19364,7 @@ Load from \`~/.prjct-cli/projects/${this.config.projectId}/agents/\`:
|
|
|
18929
19364
|
**Workflow**: ${workflowAgents.join(", ")}
|
|
18930
19365
|
**Domain**: ${domainAgents.join(", ") || "none"}
|
|
18931
19366
|
`;
|
|
18932
|
-
const claudePath =
|
|
19367
|
+
const claudePath = path40.join(contextPath, "CLAUDE.md");
|
|
18933
19368
|
await this.writeWithPreservation(claudePath, content);
|
|
18934
19369
|
}
|
|
18935
19370
|
/**
|
|
@@ -18938,8 +19373,8 @@ Load from \`~/.prjct-cli/projects/${this.config.projectId}/agents/\`:
|
|
|
18938
19373
|
async generateNowMd(contextPath) {
|
|
18939
19374
|
let currentTask = null;
|
|
18940
19375
|
try {
|
|
18941
|
-
const statePath =
|
|
18942
|
-
const state = JSON.parse(await
|
|
19376
|
+
const statePath = path40.join(this.config.globalPath, "storage", "state.json");
|
|
19377
|
+
const state = JSON.parse(await fs38.readFile(statePath, "utf-8"));
|
|
18943
19378
|
currentTask = state.currentTask;
|
|
18944
19379
|
} catch {
|
|
18945
19380
|
}
|
|
@@ -18955,7 +19390,7 @@ _No active task_
|
|
|
18955
19390
|
|
|
18956
19391
|
Use \`p. task "description"\` to start working.
|
|
18957
19392
|
`;
|
|
18958
|
-
await this.writeWithPreservation(
|
|
19393
|
+
await this.writeWithPreservation(path40.join(contextPath, "now.md"), content);
|
|
18959
19394
|
}
|
|
18960
19395
|
/**
|
|
18961
19396
|
* Generate next.md - task queue
|
|
@@ -18963,15 +19398,15 @@ Use \`p. task "description"\` to start working.
|
|
|
18963
19398
|
async generateNextMd(contextPath) {
|
|
18964
19399
|
let queue = { tasks: [] };
|
|
18965
19400
|
try {
|
|
18966
|
-
const queuePath =
|
|
18967
|
-
queue = JSON.parse(await
|
|
19401
|
+
const queuePath = path40.join(this.config.globalPath, "storage", "queue.json");
|
|
19402
|
+
queue = JSON.parse(await fs38.readFile(queuePath, "utf-8"));
|
|
18968
19403
|
} catch {
|
|
18969
19404
|
}
|
|
18970
19405
|
const content = `# NEXT
|
|
18971
19406
|
|
|
18972
19407
|
${queue.tasks.length > 0 ? queue.tasks.map((t, i) => `${i + 1}. ${t.description}${t.priority ? ` [${t.priority}]` : ""}`).join("\n") : "_Empty queue_"}
|
|
18973
19408
|
`;
|
|
18974
|
-
await this.writeWithPreservation(
|
|
19409
|
+
await this.writeWithPreservation(path40.join(contextPath, "next.md"), content);
|
|
18975
19410
|
}
|
|
18976
19411
|
/**
|
|
18977
19412
|
* Generate ideas.md - captured ideas
|
|
@@ -18979,15 +19414,15 @@ ${queue.tasks.length > 0 ? queue.tasks.map((t, i) => `${i + 1}. ${t.description}
|
|
|
18979
19414
|
async generateIdeasMd(contextPath) {
|
|
18980
19415
|
let ideas = { ideas: [] };
|
|
18981
19416
|
try {
|
|
18982
|
-
const ideasPath =
|
|
18983
|
-
ideas = JSON.parse(await
|
|
19417
|
+
const ideasPath = path40.join(this.config.globalPath, "storage", "ideas.json");
|
|
19418
|
+
ideas = JSON.parse(await fs38.readFile(ideasPath, "utf-8"));
|
|
18984
19419
|
} catch {
|
|
18985
19420
|
}
|
|
18986
19421
|
const content = `# IDEAS
|
|
18987
19422
|
|
|
18988
19423
|
${ideas.ideas.length > 0 ? ideas.ideas.map((i) => `- ${i.text}${i.priority ? ` [${i.priority}]` : ""}`).join("\n") : "_No ideas captured yet_"}
|
|
18989
19424
|
`;
|
|
18990
|
-
await this.writeWithPreservation(
|
|
19425
|
+
await this.writeWithPreservation(path40.join(contextPath, "ideas.md"), content);
|
|
18991
19426
|
}
|
|
18992
19427
|
/**
|
|
18993
19428
|
* Generate shipped.md - completed features
|
|
@@ -18997,8 +19432,8 @@ ${ideas.ideas.length > 0 ? ideas.ideas.map((i) => `- ${i.text}${i.priority ? ` [
|
|
|
18997
19432
|
shipped: []
|
|
18998
19433
|
};
|
|
18999
19434
|
try {
|
|
19000
|
-
const shippedPath =
|
|
19001
|
-
shipped = JSON.parse(await
|
|
19435
|
+
const shippedPath = path40.join(this.config.globalPath, "storage", "shipped.json");
|
|
19436
|
+
shipped = JSON.parse(await fs38.readFile(shippedPath, "utf-8"));
|
|
19002
19437
|
} catch {
|
|
19003
19438
|
}
|
|
19004
19439
|
const content = `# SHIPPED \u{1F680}
|
|
@@ -19007,15 +19442,118 @@ ${shipped.shipped.length > 0 ? shipped.shipped.slice(-10).map((s) => `- **${s.na
|
|
|
19007
19442
|
|
|
19008
19443
|
**Total shipped:** ${shipped.shipped.length}
|
|
19009
19444
|
`;
|
|
19010
|
-
await this.writeWithPreservation(
|
|
19445
|
+
await this.writeWithPreservation(path40.join(contextPath, "shipped.md"), content);
|
|
19446
|
+
}
|
|
19447
|
+
// ==========================================================================
|
|
19448
|
+
// MONOREPO SUPPORT
|
|
19449
|
+
// ==========================================================================
|
|
19450
|
+
/**
|
|
19451
|
+
* Generate CLAUDE.md files for each package in a monorepo
|
|
19452
|
+
* Each package gets its own context file with inherited + package-specific rules
|
|
19453
|
+
*/
|
|
19454
|
+
async generateMonorepoContexts(git, stats, commands, agents) {
|
|
19455
|
+
const monoInfo = await path_manager_default.detectMonorepo(this.config.projectPath);
|
|
19456
|
+
if (!monoInfo.isMonorepo) {
|
|
19457
|
+
return [];
|
|
19458
|
+
}
|
|
19459
|
+
const generatedFiles = [];
|
|
19460
|
+
const resolver = new NestedContextResolver(this.config.projectPath);
|
|
19461
|
+
await resolver.initialize();
|
|
19462
|
+
for (const pkg of monoInfo.packages) {
|
|
19463
|
+
if (!pkg.hasPrjctMd) continue;
|
|
19464
|
+
const resolvedCtx = await resolver.getPackageContext(pkg.name);
|
|
19465
|
+
if (!resolvedCtx) continue;
|
|
19466
|
+
const content = await this.generatePackageClaudeMd(
|
|
19467
|
+
pkg,
|
|
19468
|
+
resolvedCtx,
|
|
19469
|
+
git,
|
|
19470
|
+
stats,
|
|
19471
|
+
commands,
|
|
19472
|
+
agents
|
|
19473
|
+
);
|
|
19474
|
+
const claudePath = path40.join(pkg.path, "CLAUDE.md");
|
|
19475
|
+
await this.writeWithPreservation(claudePath, content);
|
|
19476
|
+
generatedFiles.push(path40.relative(this.config.projectPath, claudePath));
|
|
19477
|
+
}
|
|
19478
|
+
return generatedFiles;
|
|
19479
|
+
}
|
|
19480
|
+
/**
|
|
19481
|
+
* Generate CLAUDE.md content for a specific package
|
|
19482
|
+
*/
|
|
19483
|
+
async generatePackageClaudeMd(pkg, resolvedCtx, git, stats, commands, agents) {
|
|
19484
|
+
const workflowAgents = agents.filter((a) => a.type === "workflow").map((a) => a.name);
|
|
19485
|
+
const domainAgents = agents.filter((a) => a.type === "domain").map((a) => a.name);
|
|
19486
|
+
let pkgVersion = stats.version;
|
|
19487
|
+
let pkgName = pkg.name;
|
|
19488
|
+
try {
|
|
19489
|
+
const pkgJsonPath = path40.join(pkg.path, "package.json");
|
|
19490
|
+
const pkgJson = JSON.parse(await fs38.readFile(pkgJsonPath, "utf-8"));
|
|
19491
|
+
pkgVersion = pkgJson.version || stats.version;
|
|
19492
|
+
pkgName = pkgJson.name || pkg.name;
|
|
19493
|
+
} catch {
|
|
19494
|
+
}
|
|
19495
|
+
return `# ${pkgName} - Package Rules
|
|
19496
|
+
<!-- package: ${pkg.relativePath} -->
|
|
19497
|
+
<!-- monorepo: ${stats.name} -->
|
|
19498
|
+
<!-- Generated: ${date_helper_default.getTimestamp()} -->
|
|
19499
|
+
<!-- Sources: ${resolvedCtx.sources.join(" \u2192 ")} -->
|
|
19500
|
+
|
|
19501
|
+
## THIS PACKAGE
|
|
19502
|
+
|
|
19503
|
+
**Name:** ${pkgName}
|
|
19504
|
+
**Path:** ${pkg.relativePath}
|
|
19505
|
+
**Version:** ${pkgVersion}
|
|
19506
|
+
**Monorepo:** ${stats.name}
|
|
19507
|
+
|
|
19508
|
+
---
|
|
19509
|
+
|
|
19510
|
+
## INHERITED CONTEXT
|
|
19511
|
+
|
|
19512
|
+
${resolvedCtx.content || "_No PRJCT.md rules defined_"}
|
|
19513
|
+
|
|
19514
|
+
${resolvedCtx.overrides.length > 0 ? `
|
|
19515
|
+
**Overrides:** ${resolvedCtx.overrides.join(", ")}
|
|
19516
|
+
` : ""}
|
|
19517
|
+
|
|
19518
|
+
---
|
|
19519
|
+
|
|
19520
|
+
## COMMANDS
|
|
19521
|
+
|
|
19522
|
+
| Action | Command |
|
|
19523
|
+
|--------|---------|
|
|
19524
|
+
| Install | \`${commands.install}\` |
|
|
19525
|
+
| Dev | \`${commands.dev}\` |
|
|
19526
|
+
| Test | \`${commands.test}\` |
|
|
19527
|
+
| Build | \`${commands.build}\` |
|
|
19528
|
+
|
|
19529
|
+
---
|
|
19530
|
+
|
|
19531
|
+
## PROJECT STATE
|
|
19532
|
+
|
|
19533
|
+
| Field | Value |
|
|
19534
|
+
|-------|-------|
|
|
19535
|
+
| Package | ${pkgName} |
|
|
19536
|
+
| Monorepo | ${stats.name} |
|
|
19537
|
+
| Branch | ${git.branch} |
|
|
19538
|
+
| Ecosystem | ${stats.ecosystem} |
|
|
19539
|
+
|
|
19540
|
+
---
|
|
19541
|
+
|
|
19542
|
+
## AGENTS
|
|
19543
|
+
|
|
19544
|
+
Load from \`~/.prjct-cli/projects/${this.config.projectId}/agents/\`:
|
|
19545
|
+
|
|
19546
|
+
**Workflow**: ${workflowAgents.join(", ")}
|
|
19547
|
+
**Domain**: ${domainAgents.join(", ") || "none"}
|
|
19548
|
+
`;
|
|
19011
19549
|
}
|
|
19012
19550
|
};
|
|
19013
19551
|
}
|
|
19014
19552
|
});
|
|
19015
19553
|
|
|
19016
19554
|
// core/services/stack-detector.ts
|
|
19017
|
-
import
|
|
19018
|
-
import
|
|
19555
|
+
import fs39 from "node:fs/promises";
|
|
19556
|
+
import path41 from "node:path";
|
|
19019
19557
|
var StackDetector;
|
|
19020
19558
|
var init_stack_detector = __esm({
|
|
19021
19559
|
"core/services/stack-detector.ts"() {
|
|
@@ -19174,8 +19712,8 @@ var init_stack_detector = __esm({
|
|
|
19174
19712
|
*/
|
|
19175
19713
|
async readPackageJson() {
|
|
19176
19714
|
try {
|
|
19177
|
-
const pkgPath =
|
|
19178
|
-
const content = await
|
|
19715
|
+
const pkgPath = path41.join(this.projectPath, "package.json");
|
|
19716
|
+
const content = await fs39.readFile(pkgPath, "utf-8");
|
|
19179
19717
|
return JSON.parse(content);
|
|
19180
19718
|
} catch {
|
|
19181
19719
|
return null;
|
|
@@ -19186,7 +19724,7 @@ var init_stack_detector = __esm({
|
|
|
19186
19724
|
*/
|
|
19187
19725
|
async fileExists(filename) {
|
|
19188
19726
|
try {
|
|
19189
|
-
await
|
|
19727
|
+
await fs39.access(path41.join(this.projectPath, filename));
|
|
19190
19728
|
return true;
|
|
19191
19729
|
} catch {
|
|
19192
19730
|
return false;
|
|
@@ -19198,8 +19736,8 @@ var init_stack_detector = __esm({
|
|
|
19198
19736
|
|
|
19199
19737
|
// core/services/sync-service.ts
|
|
19200
19738
|
import { exec as exec10 } from "node:child_process";
|
|
19201
|
-
import
|
|
19202
|
-
import
|
|
19739
|
+
import fs40 from "node:fs/promises";
|
|
19740
|
+
import path42 from "node:path";
|
|
19203
19741
|
import { promisify as promisify10 } from "node:util";
|
|
19204
19742
|
var execAsync5, SyncService, syncService;
|
|
19205
19743
|
var init_sync_service = __esm({
|
|
@@ -19348,7 +19886,7 @@ var init_sync_service = __esm({
|
|
|
19348
19886
|
async ensureDirectories() {
|
|
19349
19887
|
const dirs = ["storage", "context", "agents", "memory", "analysis", "config", "sync"];
|
|
19350
19888
|
await Promise.all(
|
|
19351
|
-
dirs.map((dir) =>
|
|
19889
|
+
dirs.map((dir) => fs40.mkdir(path42.join(this.globalPath, dir), { recursive: true }))
|
|
19352
19890
|
);
|
|
19353
19891
|
}
|
|
19354
19892
|
// ==========================================================================
|
|
@@ -19418,7 +19956,7 @@ var init_sync_service = __esm({
|
|
|
19418
19956
|
const stats = {
|
|
19419
19957
|
fileCount: 0,
|
|
19420
19958
|
version: "0.0.0",
|
|
19421
|
-
name:
|
|
19959
|
+
name: path42.basename(this.projectPath),
|
|
19422
19960
|
ecosystem: "unknown",
|
|
19423
19961
|
projectType: "simple",
|
|
19424
19962
|
languages: [],
|
|
@@ -19434,8 +19972,8 @@ var init_sync_service = __esm({
|
|
|
19434
19972
|
stats.fileCount = 0;
|
|
19435
19973
|
}
|
|
19436
19974
|
try {
|
|
19437
|
-
const pkgPath =
|
|
19438
|
-
const pkg = JSON.parse(await
|
|
19975
|
+
const pkgPath = path42.join(this.projectPath, "package.json");
|
|
19976
|
+
const pkg = JSON.parse(await fs40.readFile(pkgPath, "utf-8"));
|
|
19439
19977
|
stats.version = pkg.version || "0.0.0";
|
|
19440
19978
|
stats.name = pkg.name || stats.name;
|
|
19441
19979
|
stats.ecosystem = "JavaScript";
|
|
@@ -19543,12 +20081,12 @@ var init_sync_service = __esm({
|
|
|
19543
20081
|
// ==========================================================================
|
|
19544
20082
|
async generateAgents(stack, stats) {
|
|
19545
20083
|
const agents = [];
|
|
19546
|
-
const agentsPath =
|
|
20084
|
+
const agentsPath = path42.join(this.globalPath, "agents");
|
|
19547
20085
|
try {
|
|
19548
|
-
const files = await
|
|
20086
|
+
const files = await fs40.readdir(agentsPath);
|
|
19549
20087
|
for (const file of files) {
|
|
19550
20088
|
if (file.endsWith(".md")) {
|
|
19551
|
-
await
|
|
20089
|
+
await fs40.unlink(path42.join(agentsPath, file));
|
|
19552
20090
|
}
|
|
19553
20091
|
}
|
|
19554
20092
|
} catch {
|
|
@@ -19588,7 +20126,7 @@ var init_sync_service = __esm({
|
|
|
19588
20126
|
async generateWorkflowAgent(name, agentsPath) {
|
|
19589
20127
|
let content = "";
|
|
19590
20128
|
try {
|
|
19591
|
-
const templatePath =
|
|
20129
|
+
const templatePath = path42.join(
|
|
19592
20130
|
__dirname,
|
|
19593
20131
|
"..",
|
|
19594
20132
|
"..",
|
|
@@ -19597,16 +20135,16 @@ var init_sync_service = __esm({
|
|
|
19597
20135
|
"workflow",
|
|
19598
20136
|
`${name}.md`
|
|
19599
20137
|
);
|
|
19600
|
-
content = await
|
|
20138
|
+
content = await fs40.readFile(templatePath, "utf-8");
|
|
19601
20139
|
} catch {
|
|
19602
20140
|
content = this.generateMinimalWorkflowAgent(name);
|
|
19603
20141
|
}
|
|
19604
|
-
await
|
|
20142
|
+
await fs40.writeFile(path42.join(agentsPath, `${name}.md`), content, "utf-8");
|
|
19605
20143
|
}
|
|
19606
20144
|
async generateDomainAgent(name, agentsPath, stats, stack) {
|
|
19607
20145
|
let content = "";
|
|
19608
20146
|
try {
|
|
19609
|
-
const templatePath =
|
|
20147
|
+
const templatePath = path42.join(
|
|
19610
20148
|
__dirname,
|
|
19611
20149
|
"..",
|
|
19612
20150
|
"..",
|
|
@@ -19615,14 +20153,14 @@ var init_sync_service = __esm({
|
|
|
19615
20153
|
"domain",
|
|
19616
20154
|
`${name}.md`
|
|
19617
20155
|
);
|
|
19618
|
-
content = await
|
|
20156
|
+
content = await fs40.readFile(templatePath, "utf-8");
|
|
19619
20157
|
content = content.replace("{projectName}", stats.name);
|
|
19620
20158
|
content = content.replace("{frameworks}", stack.frameworks.join(", ") || "None detected");
|
|
19621
20159
|
content = content.replace("{ecosystem}", stats.ecosystem);
|
|
19622
20160
|
} catch {
|
|
19623
20161
|
content = this.generateMinimalDomainAgent(name, stats, stack);
|
|
19624
20162
|
}
|
|
19625
|
-
await
|
|
20163
|
+
await fs40.writeFile(path42.join(agentsPath, `${name}.md`), content, "utf-8");
|
|
19626
20164
|
}
|
|
19627
20165
|
generateMinimalWorkflowAgent(name) {
|
|
19628
20166
|
const descriptions = {
|
|
@@ -19690,8 +20228,8 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
19690
20228
|
})),
|
|
19691
20229
|
agentSkillMap: Object.fromEntries(skills.map((s) => [s.agent, s.skill]))
|
|
19692
20230
|
};
|
|
19693
|
-
|
|
19694
|
-
|
|
20231
|
+
fs40.writeFile(
|
|
20232
|
+
path42.join(this.globalPath, "config", "skills.json"),
|
|
19695
20233
|
JSON.stringify(skillsConfig, null, 2),
|
|
19696
20234
|
"utf-8"
|
|
19697
20235
|
).catch(() => {
|
|
@@ -19713,10 +20251,10 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
19713
20251
|
// PROJECT.JSON UPDATE
|
|
19714
20252
|
// ==========================================================================
|
|
19715
20253
|
async updateProjectJson(git, stats) {
|
|
19716
|
-
const projectJsonPath =
|
|
20254
|
+
const projectJsonPath = path42.join(this.globalPath, "project.json");
|
|
19717
20255
|
let existing = {};
|
|
19718
20256
|
try {
|
|
19719
|
-
existing = JSON.parse(await
|
|
20257
|
+
existing = JSON.parse(await fs40.readFile(projectJsonPath, "utf-8"));
|
|
19720
20258
|
} catch {
|
|
19721
20259
|
}
|
|
19722
20260
|
const updated = {
|
|
@@ -19735,16 +20273,16 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
19735
20273
|
createdAt: existing.createdAt || date_helper_default.getTimestamp(),
|
|
19736
20274
|
lastSync: date_helper_default.getTimestamp()
|
|
19737
20275
|
};
|
|
19738
|
-
await
|
|
20276
|
+
await fs40.writeFile(projectJsonPath, JSON.stringify(updated, null, 2), "utf-8");
|
|
19739
20277
|
}
|
|
19740
20278
|
// ==========================================================================
|
|
19741
20279
|
// STATE.JSON UPDATE
|
|
19742
20280
|
// ==========================================================================
|
|
19743
20281
|
async updateStateJson(stats, stack) {
|
|
19744
|
-
const statePath =
|
|
20282
|
+
const statePath = path42.join(this.globalPath, "storage", "state.json");
|
|
19745
20283
|
let state = {};
|
|
19746
20284
|
try {
|
|
19747
|
-
state = JSON.parse(await
|
|
20285
|
+
state = JSON.parse(await fs40.readFile(statePath, "utf-8"));
|
|
19748
20286
|
} catch {
|
|
19749
20287
|
}
|
|
19750
20288
|
state.projectId = this.projectId;
|
|
@@ -19771,13 +20309,13 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
19771
20309
|
lastAction: "Synced project",
|
|
19772
20310
|
nextAction: 'Run `p. task "description"` to start working'
|
|
19773
20311
|
};
|
|
19774
|
-
await
|
|
20312
|
+
await fs40.writeFile(statePath, JSON.stringify(state, null, 2), "utf-8");
|
|
19775
20313
|
}
|
|
19776
20314
|
// ==========================================================================
|
|
19777
20315
|
// MEMORY LOGGING
|
|
19778
20316
|
// ==========================================================================
|
|
19779
20317
|
async logToMemory(git, stats) {
|
|
19780
|
-
const memoryPath =
|
|
20318
|
+
const memoryPath = path42.join(this.globalPath, "memory", "events.jsonl");
|
|
19781
20319
|
const event = {
|
|
19782
20320
|
ts: date_helper_default.getTimestamp(),
|
|
19783
20321
|
action: "sync",
|
|
@@ -19786,7 +20324,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
19786
20324
|
fileCount: stats.fileCount,
|
|
19787
20325
|
commitCount: git.commits
|
|
19788
20326
|
};
|
|
19789
|
-
await
|
|
20327
|
+
await fs40.appendFile(memoryPath, `${JSON.stringify(event)}
|
|
19790
20328
|
`, "utf-8");
|
|
19791
20329
|
}
|
|
19792
20330
|
// ==========================================================================
|
|
@@ -19806,16 +20344,16 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
19806
20344
|
let filteredChars = 0;
|
|
19807
20345
|
for (const file of contextFiles) {
|
|
19808
20346
|
try {
|
|
19809
|
-
const filePath =
|
|
19810
|
-
const content = await
|
|
20347
|
+
const filePath = path42.join(this.globalPath, file);
|
|
20348
|
+
const content = await fs40.readFile(filePath, "utf-8");
|
|
19811
20349
|
filteredChars += content.length;
|
|
19812
20350
|
} catch {
|
|
19813
20351
|
}
|
|
19814
20352
|
}
|
|
19815
20353
|
for (const agent of agents) {
|
|
19816
20354
|
try {
|
|
19817
|
-
const agentPath =
|
|
19818
|
-
const content = await
|
|
20355
|
+
const agentPath = path42.join(this.globalPath, "agents", `${agent.name}.md`);
|
|
20356
|
+
const content = await fs40.readFile(agentPath, "utf-8");
|
|
19819
20357
|
filteredChars += content.length;
|
|
19820
20358
|
} catch {
|
|
19821
20359
|
}
|
|
@@ -19847,7 +20385,7 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
19847
20385
|
// ==========================================================================
|
|
19848
20386
|
async fileExists(filename) {
|
|
19849
20387
|
try {
|
|
19850
|
-
await
|
|
20388
|
+
await fs40.access(path42.join(this.projectPath, filename));
|
|
19851
20389
|
return true;
|
|
19852
20390
|
} catch {
|
|
19853
20391
|
return false;
|
|
@@ -19855,8 +20393,8 @@ You are the ${name} expert for this project. Apply best practices for the detect
|
|
|
19855
20393
|
}
|
|
19856
20394
|
async getCliVersion() {
|
|
19857
20395
|
try {
|
|
19858
|
-
const pkgPath =
|
|
19859
|
-
const pkg = JSON.parse(await
|
|
20396
|
+
const pkgPath = path42.join(__dirname, "..", "..", "package.json");
|
|
20397
|
+
const pkg = JSON.parse(await fs40.readFile(pkgPath, "utf-8"));
|
|
19860
20398
|
return pkg.version || "0.0.0";
|
|
19861
20399
|
} catch {
|
|
19862
20400
|
return "0.0.0";
|
|
@@ -19926,6 +20464,7 @@ var init_services = __esm({
|
|
|
19926
20464
|
init_file_scorer();
|
|
19927
20465
|
init_git_analyzer();
|
|
19928
20466
|
init_memory_service();
|
|
20467
|
+
init_nested_context_resolver();
|
|
19929
20468
|
init_project_index();
|
|
19930
20469
|
init_project_service();
|
|
19931
20470
|
init_sync_service();
|
|
@@ -20015,22 +20554,22 @@ __export(uninstall_exports, {
|
|
|
20015
20554
|
});
|
|
20016
20555
|
import { execSync as execSync5 } from "node:child_process";
|
|
20017
20556
|
import fsSync2 from "node:fs";
|
|
20018
|
-
import
|
|
20557
|
+
import fs41 from "node:fs/promises";
|
|
20019
20558
|
import os12 from "node:os";
|
|
20020
|
-
import
|
|
20559
|
+
import path43 from "node:path";
|
|
20021
20560
|
import readline2 from "node:readline";
|
|
20022
20561
|
import chalk9 from "chalk";
|
|
20023
20562
|
async function getDirectorySize(dirPath) {
|
|
20024
20563
|
let totalSize = 0;
|
|
20025
20564
|
try {
|
|
20026
|
-
const entries = await
|
|
20565
|
+
const entries = await fs41.readdir(dirPath, { withFileTypes: true });
|
|
20027
20566
|
for (const entry of entries) {
|
|
20028
|
-
const entryPath =
|
|
20567
|
+
const entryPath = path43.join(dirPath, entry.name);
|
|
20029
20568
|
if (entry.isDirectory()) {
|
|
20030
20569
|
totalSize += await getDirectorySize(entryPath);
|
|
20031
20570
|
} else {
|
|
20032
20571
|
try {
|
|
20033
|
-
const stats = await
|
|
20572
|
+
const stats = await fs41.stat(entryPath);
|
|
20034
20573
|
totalSize += stats.size;
|
|
20035
20574
|
} catch {
|
|
20036
20575
|
}
|
|
@@ -20049,7 +20588,7 @@ function formatSize(bytes) {
|
|
|
20049
20588
|
}
|
|
20050
20589
|
async function countDirectoryItems(dirPath) {
|
|
20051
20590
|
try {
|
|
20052
|
-
const entries = await
|
|
20591
|
+
const entries = await fs41.readdir(dirPath, { withFileTypes: true });
|
|
20053
20592
|
return entries.filter((e) => e.isDirectory()).length;
|
|
20054
20593
|
} catch {
|
|
20055
20594
|
return 0;
|
|
@@ -20082,7 +20621,7 @@ async function gatherUninstallItems() {
|
|
|
20082
20621
|
const providerPaths = getProviderPaths();
|
|
20083
20622
|
const prjctCliPath = path_manager_default.getGlobalBasePath();
|
|
20084
20623
|
const prjctCliExists = fsSync2.existsSync(prjctCliPath);
|
|
20085
|
-
const projectCount = prjctCliExists ? await countDirectoryItems(
|
|
20624
|
+
const projectCount = prjctCliExists ? await countDirectoryItems(path43.join(prjctCliPath, "projects")) : 0;
|
|
20086
20625
|
const prjctCliSize = prjctCliExists ? await getDirectorySize(prjctCliPath) : 0;
|
|
20087
20626
|
items.push({
|
|
20088
20627
|
path: prjctCliPath,
|
|
@@ -20092,7 +20631,7 @@ async function gatherUninstallItems() {
|
|
|
20092
20631
|
count: projectCount,
|
|
20093
20632
|
exists: prjctCliExists
|
|
20094
20633
|
});
|
|
20095
|
-
const claudeMdPath =
|
|
20634
|
+
const claudeMdPath = path43.join(providerPaths.claude.config, "CLAUDE.md");
|
|
20096
20635
|
const claudeMdExists = fsSync2.existsSync(claudeMdPath);
|
|
20097
20636
|
let hasPrjctSection = false;
|
|
20098
20637
|
if (claudeMdExists) {
|
|
@@ -20126,7 +20665,7 @@ async function gatherUninstallItems() {
|
|
|
20126
20665
|
description: "Claude router",
|
|
20127
20666
|
exists: claudeRouterExists
|
|
20128
20667
|
});
|
|
20129
|
-
const statusLinePath =
|
|
20668
|
+
const statusLinePath = path43.join(providerPaths.claude.config, "prjct-statusline.sh");
|
|
20130
20669
|
const statusLineExists = fsSync2.existsSync(statusLinePath);
|
|
20131
20670
|
items.push({
|
|
20132
20671
|
path: statusLinePath,
|
|
@@ -20142,7 +20681,7 @@ async function gatherUninstallItems() {
|
|
|
20142
20681
|
description: "Gemini router",
|
|
20143
20682
|
exists: geminiRouterExists
|
|
20144
20683
|
});
|
|
20145
|
-
const geminiMdPath =
|
|
20684
|
+
const geminiMdPath = path43.join(providerPaths.gemini.config, "GEMINI.md");
|
|
20146
20685
|
const geminiMdExists = fsSync2.existsSync(geminiMdPath);
|
|
20147
20686
|
let hasGeminiPrjctSection = false;
|
|
20148
20687
|
if (geminiMdExists) {
|
|
@@ -20164,7 +20703,7 @@ async function gatherUninstallItems() {
|
|
|
20164
20703
|
}
|
|
20165
20704
|
async function removePrjctSection(filePath) {
|
|
20166
20705
|
try {
|
|
20167
|
-
const content = await
|
|
20706
|
+
const content = await fs41.readFile(filePath, "utf-8");
|
|
20168
20707
|
if (!content.includes(PRJCT_START_MARKER) || !content.includes(PRJCT_END_MARKER)) {
|
|
20169
20708
|
return false;
|
|
20170
20709
|
}
|
|
@@ -20173,9 +20712,9 @@ async function removePrjctSection(filePath) {
|
|
|
20173
20712
|
let newContent = content.substring(0, startIndex) + content.substring(endIndex);
|
|
20174
20713
|
newContent = newContent.replace(/\n{3,}/g, "\n\n").trim();
|
|
20175
20714
|
if (!newContent || newContent.trim().length === 0) {
|
|
20176
|
-
await
|
|
20715
|
+
await fs41.unlink(filePath);
|
|
20177
20716
|
} else {
|
|
20178
|
-
await
|
|
20717
|
+
await fs41.writeFile(filePath, `${newContent}
|
|
20179
20718
|
`, "utf-8");
|
|
20180
20719
|
}
|
|
20181
20720
|
return true;
|
|
@@ -20186,12 +20725,12 @@ async function removePrjctSection(filePath) {
|
|
|
20186
20725
|
async function createBackup() {
|
|
20187
20726
|
const homeDir = os12.homedir();
|
|
20188
20727
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-").substring(0, 19);
|
|
20189
|
-
const backupDir =
|
|
20728
|
+
const backupDir = path43.join(homeDir, `.prjct-backup-${timestamp}`);
|
|
20190
20729
|
try {
|
|
20191
|
-
await
|
|
20730
|
+
await fs41.mkdir(backupDir, { recursive: true });
|
|
20192
20731
|
const prjctCliPath = path_manager_default.getGlobalBasePath();
|
|
20193
20732
|
if (fsSync2.existsSync(prjctCliPath)) {
|
|
20194
|
-
await copyDirectory(prjctCliPath,
|
|
20733
|
+
await copyDirectory(prjctCliPath, path43.join(backupDir, ".prjct-cli"));
|
|
20195
20734
|
}
|
|
20196
20735
|
return backupDir;
|
|
20197
20736
|
} catch {
|
|
@@ -20199,15 +20738,15 @@ async function createBackup() {
|
|
|
20199
20738
|
}
|
|
20200
20739
|
}
|
|
20201
20740
|
async function copyDirectory(src, dest) {
|
|
20202
|
-
await
|
|
20203
|
-
const entries = await
|
|
20741
|
+
await fs41.mkdir(dest, { recursive: true });
|
|
20742
|
+
const entries = await fs41.readdir(src, { withFileTypes: true });
|
|
20204
20743
|
for (const entry of entries) {
|
|
20205
|
-
const srcPath =
|
|
20206
|
-
const destPath =
|
|
20744
|
+
const srcPath = path43.join(src, entry.name);
|
|
20745
|
+
const destPath = path43.join(dest, entry.name);
|
|
20207
20746
|
if (entry.isDirectory()) {
|
|
20208
20747
|
await copyDirectory(srcPath, destPath);
|
|
20209
20748
|
} else {
|
|
20210
|
-
await
|
|
20749
|
+
await fs41.copyFile(srcPath, destPath);
|
|
20211
20750
|
}
|
|
20212
20751
|
}
|
|
20213
20752
|
}
|
|
@@ -20223,10 +20762,10 @@ async function performUninstall(items, installation, options) {
|
|
|
20223
20762
|
deleted.push(item.path);
|
|
20224
20763
|
}
|
|
20225
20764
|
} else if (item.type === "directory") {
|
|
20226
|
-
await
|
|
20765
|
+
await fs41.rm(item.path, { recursive: true, force: true });
|
|
20227
20766
|
deleted.push(item.path);
|
|
20228
20767
|
} else if (item.type === "file") {
|
|
20229
|
-
await
|
|
20768
|
+
await fs41.unlink(item.path);
|
|
20230
20769
|
deleted.push(item.path);
|
|
20231
20770
|
}
|
|
20232
20771
|
} catch (error) {
|
|
@@ -20401,7 +20940,7 @@ __export(watch_service_exports, {
|
|
|
20401
20940
|
WatchService: () => WatchService,
|
|
20402
20941
|
watchService: () => watchService
|
|
20403
20942
|
});
|
|
20404
|
-
import
|
|
20943
|
+
import path44 from "node:path";
|
|
20405
20944
|
import chalk10 from "chalk";
|
|
20406
20945
|
import chokidar from "chokidar";
|
|
20407
20946
|
var TRIGGER_PATTERNS, IGNORE_PATTERNS2, WatchService, watchService;
|
|
@@ -20606,7 +21145,7 @@ ${chalk10.dim(`[${timestamp}]`)} ${chalk10.cyan("\u27F3")} ${filesSummary} chang
|
|
|
20606
21145
|
printStartup() {
|
|
20607
21146
|
console.log("");
|
|
20608
21147
|
console.log(chalk10.cyan("\u{1F441}\uFE0F Watching for changes..."));
|
|
20609
|
-
console.log(chalk10.dim(` Project: ${
|
|
21148
|
+
console.log(chalk10.dim(` Project: ${path44.basename(this.projectPath)}`));
|
|
20610
21149
|
console.log(chalk10.dim(` Debounce: ${this.options.debounceMs}ms`));
|
|
20611
21150
|
console.log(chalk10.dim(` Min interval: ${this.options.minIntervalMs / 1e3}s`));
|
|
20612
21151
|
console.log("");
|
|
@@ -20779,10 +21318,15 @@ var init_command_data = __esm({
|
|
|
20779
21318
|
name: "sync",
|
|
20780
21319
|
group: "core",
|
|
20781
21320
|
description: "Sync project state and update workflow agents",
|
|
20782
|
-
usage: { claude: "/p:sync", terminal: "prjct sync" },
|
|
21321
|
+
usage: { claude: "/p:sync", terminal: "prjct sync [--package=<name>]" },
|
|
20783
21322
|
implemented: true,
|
|
20784
21323
|
hasTemplate: true,
|
|
20785
|
-
requiresProject: true
|
|
21324
|
+
requiresProject: true,
|
|
21325
|
+
features: [
|
|
21326
|
+
"Monorepo support: --package=<name> for single package sync",
|
|
21327
|
+
"Nested PRJCT.md inheritance",
|
|
21328
|
+
"Per-package CLAUDE.md generation"
|
|
21329
|
+
]
|
|
20786
21330
|
},
|
|
20787
21331
|
{
|
|
20788
21332
|
name: "suggest",
|
|
@@ -21258,9 +21802,9 @@ __export(setup_exports, {
|
|
|
21258
21802
|
run: () => run
|
|
21259
21803
|
});
|
|
21260
21804
|
import { execSync as execSync6 } from "node:child_process";
|
|
21261
|
-
import
|
|
21805
|
+
import fs42 from "node:fs";
|
|
21262
21806
|
import os13 from "node:os";
|
|
21263
|
-
import
|
|
21807
|
+
import path45 from "node:path";
|
|
21264
21808
|
async function installAICLI(provider) {
|
|
21265
21809
|
const packageName = provider.name === "claude" ? "@anthropic-ai/claude-code" : "@google/gemini-cli";
|
|
21266
21810
|
try {
|
|
@@ -21366,12 +21910,12 @@ async function run() {
|
|
|
21366
21910
|
}
|
|
21367
21911
|
async function installGeminiRouter() {
|
|
21368
21912
|
try {
|
|
21369
|
-
const geminiCommandsDir =
|
|
21370
|
-
const routerSource =
|
|
21371
|
-
const routerDest =
|
|
21372
|
-
|
|
21373
|
-
if (
|
|
21374
|
-
|
|
21913
|
+
const geminiCommandsDir = path45.join(os13.homedir(), ".gemini", "commands");
|
|
21914
|
+
const routerSource = path45.join(getPackageRoot(), "templates", "commands", "p.toml");
|
|
21915
|
+
const routerDest = path45.join(geminiCommandsDir, "p.toml");
|
|
21916
|
+
fs42.mkdirSync(geminiCommandsDir, { recursive: true });
|
|
21917
|
+
if (fs42.existsSync(routerSource)) {
|
|
21918
|
+
fs42.copyFileSync(routerSource, routerDest);
|
|
21375
21919
|
return true;
|
|
21376
21920
|
}
|
|
21377
21921
|
return false;
|
|
@@ -21382,15 +21926,15 @@ async function installGeminiRouter() {
|
|
|
21382
21926
|
}
|
|
21383
21927
|
async function installGeminiGlobalConfig() {
|
|
21384
21928
|
try {
|
|
21385
|
-
const geminiDir =
|
|
21386
|
-
const globalConfigPath =
|
|
21387
|
-
const templatePath =
|
|
21388
|
-
|
|
21389
|
-
const templateContent =
|
|
21929
|
+
const geminiDir = path45.join(os13.homedir(), ".gemini");
|
|
21930
|
+
const globalConfigPath = path45.join(geminiDir, "GEMINI.md");
|
|
21931
|
+
const templatePath = path45.join(getPackageRoot(), "templates", "global", "GEMINI.md");
|
|
21932
|
+
fs42.mkdirSync(geminiDir, { recursive: true });
|
|
21933
|
+
const templateContent = fs42.readFileSync(templatePath, "utf-8");
|
|
21390
21934
|
let existingContent = "";
|
|
21391
21935
|
let fileExists2 = false;
|
|
21392
21936
|
try {
|
|
21393
|
-
existingContent =
|
|
21937
|
+
existingContent = fs42.readFileSync(globalConfigPath, "utf-8");
|
|
21394
21938
|
fileExists2 = true;
|
|
21395
21939
|
} catch (error) {
|
|
21396
21940
|
if (isNotFoundError(error)) {
|
|
@@ -21400,7 +21944,7 @@ async function installGeminiGlobalConfig() {
|
|
|
21400
21944
|
}
|
|
21401
21945
|
}
|
|
21402
21946
|
if (!fileExists2) {
|
|
21403
|
-
|
|
21947
|
+
fs42.writeFileSync(globalConfigPath, templateContent, "utf-8");
|
|
21404
21948
|
return { success: true, action: "created" };
|
|
21405
21949
|
}
|
|
21406
21950
|
const startMarker = "<!-- prjct:start - DO NOT REMOVE THIS MARKER -->";
|
|
@@ -21410,7 +21954,7 @@ async function installGeminiGlobalConfig() {
|
|
|
21410
21954
|
const updatedContent2 = `${existingContent}
|
|
21411
21955
|
|
|
21412
21956
|
${templateContent}`;
|
|
21413
|
-
|
|
21957
|
+
fs42.writeFileSync(globalConfigPath, updatedContent2, "utf-8");
|
|
21414
21958
|
return { success: true, action: "appended" };
|
|
21415
21959
|
}
|
|
21416
21960
|
const beforeMarker = existingContent.substring(0, existingContent.indexOf(startMarker));
|
|
@@ -21422,7 +21966,7 @@ ${templateContent}`;
|
|
|
21422
21966
|
templateContent.indexOf(endMarker) + endMarker.length
|
|
21423
21967
|
);
|
|
21424
21968
|
const updatedContent = beforeMarker + prjctSection + afterMarker;
|
|
21425
|
-
|
|
21969
|
+
fs42.writeFileSync(globalConfigPath, updatedContent, "utf-8");
|
|
21426
21970
|
return { success: true, action: "updated" };
|
|
21427
21971
|
} catch (error) {
|
|
21428
21972
|
console.error(`Gemini config warning: ${error.message}`);
|
|
@@ -21431,18 +21975,18 @@ ${templateContent}`;
|
|
|
21431
21975
|
}
|
|
21432
21976
|
async function installAntigravitySkill() {
|
|
21433
21977
|
try {
|
|
21434
|
-
const antigravitySkillsDir =
|
|
21435
|
-
const prjctSkillDir =
|
|
21436
|
-
const skillMdPath =
|
|
21437
|
-
const templatePath =
|
|
21438
|
-
|
|
21439
|
-
const fileExists2 =
|
|
21440
|
-
if (!
|
|
21978
|
+
const antigravitySkillsDir = path45.join(os13.homedir(), ".gemini", "antigravity", "skills");
|
|
21979
|
+
const prjctSkillDir = path45.join(antigravitySkillsDir, "prjct");
|
|
21980
|
+
const skillMdPath = path45.join(prjctSkillDir, "SKILL.md");
|
|
21981
|
+
const templatePath = path45.join(getPackageRoot(), "templates", "antigravity", "SKILL.md");
|
|
21982
|
+
fs42.mkdirSync(prjctSkillDir, { recursive: true });
|
|
21983
|
+
const fileExists2 = fs42.existsSync(skillMdPath);
|
|
21984
|
+
if (!fs42.existsSync(templatePath)) {
|
|
21441
21985
|
console.error("Antigravity SKILL.md template not found");
|
|
21442
21986
|
return { success: false, action: null };
|
|
21443
21987
|
}
|
|
21444
|
-
const templateContent =
|
|
21445
|
-
|
|
21988
|
+
const templateContent = fs42.readFileSync(templatePath, "utf-8");
|
|
21989
|
+
fs42.writeFileSync(skillMdPath, templateContent, "utf-8");
|
|
21446
21990
|
return { success: true, action: fileExists2 ? "updated" : "created" };
|
|
21447
21991
|
} catch (error) {
|
|
21448
21992
|
console.error(`Antigravity skill warning: ${error.message}`);
|
|
@@ -21461,24 +22005,24 @@ async function installCursorProject(projectRoot) {
|
|
|
21461
22005
|
gitignoreUpdated: false
|
|
21462
22006
|
};
|
|
21463
22007
|
try {
|
|
21464
|
-
const cursorDir =
|
|
21465
|
-
const rulesDir =
|
|
21466
|
-
const commandsDir =
|
|
21467
|
-
const routerMdcDest =
|
|
21468
|
-
const routerMdcSource =
|
|
21469
|
-
const cursorCommandsSource =
|
|
21470
|
-
|
|
21471
|
-
|
|
21472
|
-
if (
|
|
21473
|
-
|
|
22008
|
+
const cursorDir = path45.join(projectRoot, ".cursor");
|
|
22009
|
+
const rulesDir = path45.join(cursorDir, "rules");
|
|
22010
|
+
const commandsDir = path45.join(cursorDir, "commands");
|
|
22011
|
+
const routerMdcDest = path45.join(rulesDir, "prjct.mdc");
|
|
22012
|
+
const routerMdcSource = path45.join(getPackageRoot(), "templates", "cursor", "router.mdc");
|
|
22013
|
+
const cursorCommandsSource = path45.join(getPackageRoot(), "templates", "cursor", "commands");
|
|
22014
|
+
fs42.mkdirSync(rulesDir, { recursive: true });
|
|
22015
|
+
fs42.mkdirSync(commandsDir, { recursive: true });
|
|
22016
|
+
if (fs42.existsSync(routerMdcSource)) {
|
|
22017
|
+
fs42.copyFileSync(routerMdcSource, routerMdcDest);
|
|
21474
22018
|
result.rulesCreated = true;
|
|
21475
22019
|
}
|
|
21476
|
-
if (
|
|
21477
|
-
const commandFiles =
|
|
22020
|
+
if (fs42.existsSync(cursorCommandsSource)) {
|
|
22021
|
+
const commandFiles = fs42.readdirSync(cursorCommandsSource).filter((f) => f.endsWith(".md"));
|
|
21478
22022
|
for (const file of commandFiles) {
|
|
21479
|
-
const src =
|
|
21480
|
-
const dest =
|
|
21481
|
-
|
|
22023
|
+
const src = path45.join(cursorCommandsSource, file);
|
|
22024
|
+
const dest = path45.join(commandsDir, file);
|
|
22025
|
+
fs42.copyFileSync(src, dest);
|
|
21482
22026
|
}
|
|
21483
22027
|
result.commandsCreated = commandFiles.length > 0;
|
|
21484
22028
|
}
|
|
@@ -21492,7 +22036,7 @@ async function installCursorProject(projectRoot) {
|
|
|
21492
22036
|
}
|
|
21493
22037
|
async function addCursorToGitignore(projectRoot) {
|
|
21494
22038
|
try {
|
|
21495
|
-
const gitignorePath =
|
|
22039
|
+
const gitignorePath = path45.join(projectRoot, ".gitignore");
|
|
21496
22040
|
const entriesToAdd = [
|
|
21497
22041
|
"# prjct Cursor routers (regenerated per-developer)",
|
|
21498
22042
|
".cursor/rules/prjct.mdc",
|
|
@@ -21507,7 +22051,7 @@ async function addCursorToGitignore(projectRoot) {
|
|
|
21507
22051
|
let content = "";
|
|
21508
22052
|
let fileExists2 = false;
|
|
21509
22053
|
try {
|
|
21510
|
-
content =
|
|
22054
|
+
content = fs42.readFileSync(gitignorePath, "utf-8");
|
|
21511
22055
|
fileExists2 = true;
|
|
21512
22056
|
} catch (error) {
|
|
21513
22057
|
if (!isNotFoundError(error)) {
|
|
@@ -21522,7 +22066,7 @@ async function addCursorToGitignore(projectRoot) {
|
|
|
21522
22066
|
${entriesToAdd.join("\n")}
|
|
21523
22067
|
` : `${entriesToAdd.join("\n")}
|
|
21524
22068
|
`;
|
|
21525
|
-
|
|
22069
|
+
fs42.writeFileSync(gitignorePath, newContent, "utf-8");
|
|
21526
22070
|
return true;
|
|
21527
22071
|
} catch (error) {
|
|
21528
22072
|
console.error(`Gitignore update warning: ${error.message}`);
|
|
@@ -21530,12 +22074,12 @@ ${entriesToAdd.join("\n")}
|
|
|
21530
22074
|
}
|
|
21531
22075
|
}
|
|
21532
22076
|
function hasCursorProject(projectRoot) {
|
|
21533
|
-
return
|
|
22077
|
+
return fs42.existsSync(path45.join(projectRoot, ".cursor"));
|
|
21534
22078
|
}
|
|
21535
22079
|
function needsCursorRegeneration(projectRoot) {
|
|
21536
|
-
const cursorDir =
|
|
21537
|
-
const routerPath =
|
|
21538
|
-
return
|
|
22080
|
+
const cursorDir = path45.join(projectRoot, ".cursor");
|
|
22081
|
+
const routerPath = path45.join(cursorDir, "rules", "prjct.mdc");
|
|
22082
|
+
return fs42.existsSync(cursorDir) && !fs42.existsSync(routerPath);
|
|
21539
22083
|
}
|
|
21540
22084
|
async function installWindsurfProject(projectRoot) {
|
|
21541
22085
|
const result = {
|
|
@@ -21545,29 +22089,29 @@ async function installWindsurfProject(projectRoot) {
|
|
|
21545
22089
|
gitignoreUpdated: false
|
|
21546
22090
|
};
|
|
21547
22091
|
try {
|
|
21548
|
-
const windsurfDir =
|
|
21549
|
-
const rulesDir =
|
|
21550
|
-
const workflowsDir =
|
|
21551
|
-
const routerDest =
|
|
21552
|
-
const routerSource =
|
|
21553
|
-
const windsurfWorkflowsSource =
|
|
22092
|
+
const windsurfDir = path45.join(projectRoot, ".windsurf");
|
|
22093
|
+
const rulesDir = path45.join(windsurfDir, "rules");
|
|
22094
|
+
const workflowsDir = path45.join(windsurfDir, "workflows");
|
|
22095
|
+
const routerDest = path45.join(rulesDir, "prjct.md");
|
|
22096
|
+
const routerSource = path45.join(getPackageRoot(), "templates", "windsurf", "router.md");
|
|
22097
|
+
const windsurfWorkflowsSource = path45.join(
|
|
21554
22098
|
getPackageRoot(),
|
|
21555
22099
|
"templates",
|
|
21556
22100
|
"windsurf",
|
|
21557
22101
|
"workflows"
|
|
21558
22102
|
);
|
|
21559
|
-
|
|
21560
|
-
|
|
21561
|
-
if (
|
|
21562
|
-
|
|
22103
|
+
fs42.mkdirSync(rulesDir, { recursive: true });
|
|
22104
|
+
fs42.mkdirSync(workflowsDir, { recursive: true });
|
|
22105
|
+
if (fs42.existsSync(routerSource)) {
|
|
22106
|
+
fs42.copyFileSync(routerSource, routerDest);
|
|
21563
22107
|
result.rulesCreated = true;
|
|
21564
22108
|
}
|
|
21565
|
-
if (
|
|
21566
|
-
const workflowFiles =
|
|
22109
|
+
if (fs42.existsSync(windsurfWorkflowsSource)) {
|
|
22110
|
+
const workflowFiles = fs42.readdirSync(windsurfWorkflowsSource).filter((f) => f.endsWith(".md"));
|
|
21567
22111
|
for (const file of workflowFiles) {
|
|
21568
|
-
const src =
|
|
21569
|
-
const dest =
|
|
21570
|
-
|
|
22112
|
+
const src = path45.join(windsurfWorkflowsSource, file);
|
|
22113
|
+
const dest = path45.join(workflowsDir, file);
|
|
22114
|
+
fs42.copyFileSync(src, dest);
|
|
21571
22115
|
}
|
|
21572
22116
|
result.workflowsCreated = workflowFiles.length > 0;
|
|
21573
22117
|
}
|
|
@@ -21581,7 +22125,7 @@ async function installWindsurfProject(projectRoot) {
|
|
|
21581
22125
|
}
|
|
21582
22126
|
async function addWindsurfToGitignore(projectRoot) {
|
|
21583
22127
|
try {
|
|
21584
|
-
const gitignorePath =
|
|
22128
|
+
const gitignorePath = path45.join(projectRoot, ".gitignore");
|
|
21585
22129
|
const entriesToAdd = [
|
|
21586
22130
|
"# prjct Windsurf routers (regenerated per-developer)",
|
|
21587
22131
|
".windsurf/rules/prjct.md",
|
|
@@ -21596,7 +22140,7 @@ async function addWindsurfToGitignore(projectRoot) {
|
|
|
21596
22140
|
let content = "";
|
|
21597
22141
|
let fileExists2 = false;
|
|
21598
22142
|
try {
|
|
21599
|
-
content =
|
|
22143
|
+
content = fs42.readFileSync(gitignorePath, "utf-8");
|
|
21600
22144
|
fileExists2 = true;
|
|
21601
22145
|
} catch (error) {
|
|
21602
22146
|
if (!isNotFoundError(error)) {
|
|
@@ -21611,7 +22155,7 @@ async function addWindsurfToGitignore(projectRoot) {
|
|
|
21611
22155
|
${entriesToAdd.join("\n")}
|
|
21612
22156
|
` : `${entriesToAdd.join("\n")}
|
|
21613
22157
|
`;
|
|
21614
|
-
|
|
22158
|
+
fs42.writeFileSync(gitignorePath, newContent, "utf-8");
|
|
21615
22159
|
return true;
|
|
21616
22160
|
} catch (error) {
|
|
21617
22161
|
console.error(`Gitignore update warning: ${error.message}`);
|
|
@@ -21619,32 +22163,32 @@ ${entriesToAdd.join("\n")}
|
|
|
21619
22163
|
}
|
|
21620
22164
|
}
|
|
21621
22165
|
function hasWindsurfProject(projectRoot) {
|
|
21622
|
-
return
|
|
22166
|
+
return fs42.existsSync(path45.join(projectRoot, ".windsurf"));
|
|
21623
22167
|
}
|
|
21624
22168
|
function needsWindsurfRegeneration(projectRoot) {
|
|
21625
|
-
const windsurfDir =
|
|
21626
|
-
const routerPath =
|
|
21627
|
-
return
|
|
22169
|
+
const windsurfDir = path45.join(projectRoot, ".windsurf");
|
|
22170
|
+
const routerPath = path45.join(windsurfDir, "rules", "prjct.md");
|
|
22171
|
+
return fs42.existsSync(windsurfDir) && !fs42.existsSync(routerPath);
|
|
21628
22172
|
}
|
|
21629
22173
|
async function migrateProjectsCliVersion() {
|
|
21630
22174
|
try {
|
|
21631
|
-
const projectsDir =
|
|
21632
|
-
if (!
|
|
22175
|
+
const projectsDir = path45.join(os13.homedir(), ".prjct-cli", "projects");
|
|
22176
|
+
if (!fs42.existsSync(projectsDir)) {
|
|
21633
22177
|
return;
|
|
21634
22178
|
}
|
|
21635
|
-
const projectDirs =
|
|
22179
|
+
const projectDirs = fs42.readdirSync(projectsDir, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
|
|
21636
22180
|
let migrated = 0;
|
|
21637
22181
|
for (const projectId of projectDirs) {
|
|
21638
|
-
const projectJsonPath =
|
|
21639
|
-
if (!
|
|
22182
|
+
const projectJsonPath = path45.join(projectsDir, projectId, "project.json");
|
|
22183
|
+
if (!fs42.existsSync(projectJsonPath)) {
|
|
21640
22184
|
continue;
|
|
21641
22185
|
}
|
|
21642
22186
|
try {
|
|
21643
|
-
const content =
|
|
22187
|
+
const content = fs42.readFileSync(projectJsonPath, "utf8");
|
|
21644
22188
|
const project = JSON.parse(content);
|
|
21645
22189
|
if (project.cliVersion !== VERSION) {
|
|
21646
22190
|
project.cliVersion = VERSION;
|
|
21647
|
-
|
|
22191
|
+
fs42.writeFileSync(projectJsonPath, JSON.stringify(project, null, 2));
|
|
21648
22192
|
migrated++;
|
|
21649
22193
|
}
|
|
21650
22194
|
} catch (error) {
|
|
@@ -21664,9 +22208,9 @@ async function migrateProjectsCliVersion() {
|
|
|
21664
22208
|
}
|
|
21665
22209
|
function ensureStatusLineSettings(settingsPath, statusLinePath) {
|
|
21666
22210
|
let settings = {};
|
|
21667
|
-
if (
|
|
22211
|
+
if (fs42.existsSync(settingsPath)) {
|
|
21668
22212
|
try {
|
|
21669
|
-
settings = JSON.parse(
|
|
22213
|
+
settings = JSON.parse(fs42.readFileSync(settingsPath, "utf8"));
|
|
21670
22214
|
} catch (error) {
|
|
21671
22215
|
if (!(error instanceof SyntaxError)) {
|
|
21672
22216
|
throw error;
|
|
@@ -21674,42 +22218,42 @@ function ensureStatusLineSettings(settingsPath, statusLinePath) {
|
|
|
21674
22218
|
}
|
|
21675
22219
|
}
|
|
21676
22220
|
settings.statusLine = { type: "command", command: statusLinePath };
|
|
21677
|
-
|
|
22221
|
+
fs42.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
|
21678
22222
|
}
|
|
21679
22223
|
async function installStatusLine() {
|
|
21680
22224
|
try {
|
|
21681
|
-
const claudeDir =
|
|
21682
|
-
const settingsPath =
|
|
21683
|
-
const claudeStatusLinePath =
|
|
21684
|
-
const prjctStatusLineDir =
|
|
21685
|
-
const prjctStatusLinePath =
|
|
21686
|
-
const prjctThemesDir =
|
|
21687
|
-
const prjctLibDir =
|
|
21688
|
-
const prjctComponentsDir =
|
|
21689
|
-
const prjctConfigPath =
|
|
21690
|
-
const assetsDir =
|
|
21691
|
-
const sourceScript =
|
|
21692
|
-
const sourceThemeDir =
|
|
21693
|
-
const sourceLibDir =
|
|
21694
|
-
const sourceComponentsDir =
|
|
21695
|
-
const sourceConfigPath =
|
|
21696
|
-
if (!
|
|
21697
|
-
|
|
22225
|
+
const claudeDir = path45.join(os13.homedir(), ".claude");
|
|
22226
|
+
const settingsPath = path45.join(claudeDir, "settings.json");
|
|
22227
|
+
const claudeStatusLinePath = path45.join(claudeDir, "prjct-statusline.sh");
|
|
22228
|
+
const prjctStatusLineDir = path45.join(os13.homedir(), ".prjct-cli", "statusline");
|
|
22229
|
+
const prjctStatusLinePath = path45.join(prjctStatusLineDir, "statusline.sh");
|
|
22230
|
+
const prjctThemesDir = path45.join(prjctStatusLineDir, "themes");
|
|
22231
|
+
const prjctLibDir = path45.join(prjctStatusLineDir, "lib");
|
|
22232
|
+
const prjctComponentsDir = path45.join(prjctStatusLineDir, "components");
|
|
22233
|
+
const prjctConfigPath = path45.join(prjctStatusLineDir, "config.json");
|
|
22234
|
+
const assetsDir = path45.join(getPackageRoot(), "assets", "statusline");
|
|
22235
|
+
const sourceScript = path45.join(assetsDir, "statusline.sh");
|
|
22236
|
+
const sourceThemeDir = path45.join(assetsDir, "themes");
|
|
22237
|
+
const sourceLibDir = path45.join(assetsDir, "lib");
|
|
22238
|
+
const sourceComponentsDir = path45.join(assetsDir, "components");
|
|
22239
|
+
const sourceConfigPath = path45.join(assetsDir, "default-config.json");
|
|
22240
|
+
if (!fs42.existsSync(claudeDir)) {
|
|
22241
|
+
fs42.mkdirSync(claudeDir, { recursive: true });
|
|
21698
22242
|
}
|
|
21699
|
-
if (!
|
|
21700
|
-
|
|
22243
|
+
if (!fs42.existsSync(prjctStatusLineDir)) {
|
|
22244
|
+
fs42.mkdirSync(prjctStatusLineDir, { recursive: true });
|
|
21701
22245
|
}
|
|
21702
|
-
if (!
|
|
21703
|
-
|
|
22246
|
+
if (!fs42.existsSync(prjctThemesDir)) {
|
|
22247
|
+
fs42.mkdirSync(prjctThemesDir, { recursive: true });
|
|
21704
22248
|
}
|
|
21705
|
-
if (!
|
|
21706
|
-
|
|
22249
|
+
if (!fs42.existsSync(prjctLibDir)) {
|
|
22250
|
+
fs42.mkdirSync(prjctLibDir, { recursive: true });
|
|
21707
22251
|
}
|
|
21708
|
-
if (!
|
|
21709
|
-
|
|
22252
|
+
if (!fs42.existsSync(prjctComponentsDir)) {
|
|
22253
|
+
fs42.mkdirSync(prjctComponentsDir, { recursive: true });
|
|
21710
22254
|
}
|
|
21711
|
-
if (
|
|
21712
|
-
const existingContent =
|
|
22255
|
+
if (fs42.existsSync(prjctStatusLinePath)) {
|
|
22256
|
+
const existingContent = fs42.readFileSync(prjctStatusLinePath, "utf8");
|
|
21713
22257
|
if (existingContent.includes("CLI_VERSION=")) {
|
|
21714
22258
|
const versionMatch = existingContent.match(/CLI_VERSION="([^"]*)"/);
|
|
21715
22259
|
if (versionMatch && versionMatch[1] !== VERSION) {
|
|
@@ -21717,7 +22261,7 @@ async function installStatusLine() {
|
|
|
21717
22261
|
/CLI_VERSION="[^"]*"/,
|
|
21718
22262
|
`CLI_VERSION="${VERSION}"`
|
|
21719
22263
|
);
|
|
21720
|
-
|
|
22264
|
+
fs42.writeFileSync(prjctStatusLinePath, updatedContent, { mode: 493 });
|
|
21721
22265
|
}
|
|
21722
22266
|
installStatusLineModules(sourceLibDir, prjctLibDir);
|
|
21723
22267
|
installStatusLineModules(sourceComponentsDir, prjctComponentsDir);
|
|
@@ -21726,22 +22270,22 @@ async function installStatusLine() {
|
|
|
21726
22270
|
return;
|
|
21727
22271
|
}
|
|
21728
22272
|
}
|
|
21729
|
-
if (
|
|
21730
|
-
let scriptContent =
|
|
22273
|
+
if (fs42.existsSync(sourceScript)) {
|
|
22274
|
+
let scriptContent = fs42.readFileSync(sourceScript, "utf8");
|
|
21731
22275
|
scriptContent = scriptContent.replace(/CLI_VERSION="[^"]*"/, `CLI_VERSION="${VERSION}"`);
|
|
21732
|
-
|
|
22276
|
+
fs42.writeFileSync(prjctStatusLinePath, scriptContent, { mode: 493 });
|
|
21733
22277
|
installStatusLineModules(sourceLibDir, prjctLibDir);
|
|
21734
22278
|
installStatusLineModules(sourceComponentsDir, prjctComponentsDir);
|
|
21735
|
-
if (
|
|
21736
|
-
const themes =
|
|
22279
|
+
if (fs42.existsSync(sourceThemeDir)) {
|
|
22280
|
+
const themes = fs42.readdirSync(sourceThemeDir);
|
|
21737
22281
|
for (const theme of themes) {
|
|
21738
|
-
const src =
|
|
21739
|
-
const dest =
|
|
21740
|
-
|
|
22282
|
+
const src = path45.join(sourceThemeDir, theme);
|
|
22283
|
+
const dest = path45.join(prjctThemesDir, theme);
|
|
22284
|
+
fs42.copyFileSync(src, dest);
|
|
21741
22285
|
}
|
|
21742
22286
|
}
|
|
21743
|
-
if (!
|
|
21744
|
-
|
|
22287
|
+
if (!fs42.existsSync(prjctConfigPath) && fs42.existsSync(sourceConfigPath)) {
|
|
22288
|
+
fs42.copyFileSync(sourceConfigPath, prjctConfigPath);
|
|
21745
22289
|
}
|
|
21746
22290
|
} else {
|
|
21747
22291
|
const scriptContent = `#!/bin/bash
|
|
@@ -21776,7 +22320,7 @@ if [ -f "$CONFIG" ]; then
|
|
|
21776
22320
|
fi
|
|
21777
22321
|
echo "prjct"
|
|
21778
22322
|
`;
|
|
21779
|
-
|
|
22323
|
+
fs42.writeFileSync(prjctStatusLinePath, scriptContent, { mode: 493 });
|
|
21780
22324
|
}
|
|
21781
22325
|
ensureStatusLineSymlink(claudeStatusLinePath, prjctStatusLinePath);
|
|
21782
22326
|
ensureStatusLineSettings(settingsPath, claudeStatusLinePath);
|
|
@@ -21788,10 +22332,10 @@ echo "prjct"
|
|
|
21788
22332
|
}
|
|
21789
22333
|
async function installContext7MCP() {
|
|
21790
22334
|
try {
|
|
21791
|
-
const claudeDir =
|
|
21792
|
-
const mcpConfigPath =
|
|
21793
|
-
if (!
|
|
21794
|
-
|
|
22335
|
+
const claudeDir = path45.join(os13.homedir(), ".claude");
|
|
22336
|
+
const mcpConfigPath = path45.join(claudeDir, "mcp.json");
|
|
22337
|
+
if (!fs42.existsSync(claudeDir)) {
|
|
22338
|
+
fs42.mkdirSync(claudeDir, { recursive: true });
|
|
21795
22339
|
}
|
|
21796
22340
|
const context7Config = {
|
|
21797
22341
|
mcpServers: {
|
|
@@ -21801,54 +22345,54 @@ async function installContext7MCP() {
|
|
|
21801
22345
|
}
|
|
21802
22346
|
}
|
|
21803
22347
|
};
|
|
21804
|
-
if (
|
|
21805
|
-
const existingContent =
|
|
22348
|
+
if (fs42.existsSync(mcpConfigPath)) {
|
|
22349
|
+
const existingContent = fs42.readFileSync(mcpConfigPath, "utf-8");
|
|
21806
22350
|
const existingConfig = JSON.parse(existingContent);
|
|
21807
22351
|
if (existingConfig.mcpServers?.context7) {
|
|
21808
22352
|
return;
|
|
21809
22353
|
}
|
|
21810
22354
|
existingConfig.mcpServers = existingConfig.mcpServers || {};
|
|
21811
22355
|
existingConfig.mcpServers.context7 = context7Config.mcpServers.context7;
|
|
21812
|
-
|
|
22356
|
+
fs42.writeFileSync(mcpConfigPath, JSON.stringify(existingConfig, null, 2), "utf-8");
|
|
21813
22357
|
} else {
|
|
21814
|
-
|
|
22358
|
+
fs42.writeFileSync(mcpConfigPath, JSON.stringify(context7Config, null, 2), "utf-8");
|
|
21815
22359
|
}
|
|
21816
22360
|
} catch (error) {
|
|
21817
22361
|
console.error(`Context7 MCP setup warning: ${error.message}`);
|
|
21818
22362
|
}
|
|
21819
22363
|
}
|
|
21820
22364
|
function installStatusLineModules(sourceDir, destDir) {
|
|
21821
|
-
if (!
|
|
22365
|
+
if (!fs42.existsSync(sourceDir)) {
|
|
21822
22366
|
return;
|
|
21823
22367
|
}
|
|
21824
|
-
const files =
|
|
22368
|
+
const files = fs42.readdirSync(sourceDir);
|
|
21825
22369
|
for (const file of files) {
|
|
21826
22370
|
if (file.endsWith(".sh")) {
|
|
21827
|
-
const src =
|
|
21828
|
-
const dest =
|
|
21829
|
-
|
|
21830
|
-
|
|
22371
|
+
const src = path45.join(sourceDir, file);
|
|
22372
|
+
const dest = path45.join(destDir, file);
|
|
22373
|
+
fs42.copyFileSync(src, dest);
|
|
22374
|
+
fs42.chmodSync(dest, 493);
|
|
21831
22375
|
}
|
|
21832
22376
|
}
|
|
21833
22377
|
}
|
|
21834
22378
|
function ensureStatusLineSymlink(linkPath, targetPath) {
|
|
21835
22379
|
try {
|
|
21836
|
-
if (
|
|
21837
|
-
const stats =
|
|
22380
|
+
if (fs42.existsSync(linkPath)) {
|
|
22381
|
+
const stats = fs42.lstatSync(linkPath);
|
|
21838
22382
|
if (stats.isSymbolicLink()) {
|
|
21839
|
-
const existingTarget =
|
|
22383
|
+
const existingTarget = fs42.readlinkSync(linkPath);
|
|
21840
22384
|
if (existingTarget === targetPath) {
|
|
21841
22385
|
return;
|
|
21842
22386
|
}
|
|
21843
22387
|
}
|
|
21844
|
-
|
|
22388
|
+
fs42.unlinkSync(linkPath);
|
|
21845
22389
|
}
|
|
21846
|
-
|
|
22390
|
+
fs42.symlinkSync(targetPath, linkPath);
|
|
21847
22391
|
} catch (_error) {
|
|
21848
22392
|
try {
|
|
21849
|
-
if (
|
|
21850
|
-
|
|
21851
|
-
|
|
22393
|
+
if (fs42.existsSync(targetPath)) {
|
|
22394
|
+
fs42.copyFileSync(targetPath, linkPath);
|
|
22395
|
+
fs42.chmodSync(linkPath, 493);
|
|
21852
22396
|
}
|
|
21853
22397
|
} catch (copyError) {
|
|
21854
22398
|
if (!isNotFoundError(copyError)) {
|
|
@@ -22263,7 +22807,7 @@ var init_registry2 = __esm({
|
|
|
22263
22807
|
});
|
|
22264
22808
|
|
|
22265
22809
|
// core/commands/analytics.ts
|
|
22266
|
-
import
|
|
22810
|
+
import path46 from "node:path";
|
|
22267
22811
|
var AnalyticsCommands;
|
|
22268
22812
|
var init_analytics = __esm({
|
|
22269
22813
|
"core/commands/analytics.ts"() {
|
|
@@ -22288,7 +22832,7 @@ var init_analytics = __esm({
|
|
|
22288
22832
|
output_default.failWithHint("NO_PROJECT_ID");
|
|
22289
22833
|
return { success: false, error: "No project ID found" };
|
|
22290
22834
|
}
|
|
22291
|
-
const projectName =
|
|
22835
|
+
const projectName = path46.basename(projectPath);
|
|
22292
22836
|
const currentTask = await stateStorage.getCurrentTask(projectId);
|
|
22293
22837
|
const queueTasks = await queueStorage.getActiveTasks(projectId);
|
|
22294
22838
|
const shipped = await shippedStorage.getRecent(projectId, 5);
|
|
@@ -22533,8 +23077,8 @@ ${"\u2550".repeat(50)}
|
|
|
22533
23077
|
});
|
|
22534
23078
|
|
|
22535
23079
|
// core/commands/context.ts
|
|
22536
|
-
import
|
|
22537
|
-
import
|
|
23080
|
+
import fs43 from "node:fs/promises";
|
|
23081
|
+
import path47 from "node:path";
|
|
22538
23082
|
var ContextCommands, contextCommands;
|
|
22539
23083
|
var init_context = __esm({
|
|
22540
23084
|
"core/commands/context.ts"() {
|
|
@@ -22660,8 +23204,8 @@ var init_context = __esm({
|
|
|
22660
23204
|
*/
|
|
22661
23205
|
async loadRepoAnalysis(globalPath) {
|
|
22662
23206
|
try {
|
|
22663
|
-
const analysisPath =
|
|
22664
|
-
const content = await
|
|
23207
|
+
const analysisPath = path47.join(globalPath, "analysis", "repo-analysis.json");
|
|
23208
|
+
const content = await fs43.readFile(analysisPath, "utf-8");
|
|
22665
23209
|
const data = JSON.parse(content);
|
|
22666
23210
|
return {
|
|
22667
23211
|
ecosystem: data.ecosystem || "unknown",
|
|
@@ -22680,7 +23224,7 @@ var init_context = __esm({
|
|
|
22680
23224
|
});
|
|
22681
23225
|
|
|
22682
23226
|
// core/commands/cleanup.ts
|
|
22683
|
-
import
|
|
23227
|
+
import path48 from "node:path";
|
|
22684
23228
|
async function cleanupMemory(projectPath) {
|
|
22685
23229
|
const projectId = await config_manager_default.getProjectId(projectPath);
|
|
22686
23230
|
const results = { rotated: [], totalSize: 0, freedSpace: 0 };
|
|
@@ -22696,7 +23240,7 @@ async function cleanupMemory(projectPath) {
|
|
|
22696
23240
|
results.totalSize += sizeMB;
|
|
22697
23241
|
const rotated = await jsonl_helper_default.rotateJsonLinesIfNeeded(filePath, 10);
|
|
22698
23242
|
if (rotated) {
|
|
22699
|
-
results.rotated.push(
|
|
23243
|
+
results.rotated.push(path48.basename(filePath));
|
|
22700
23244
|
results.freedSpace += sizeMB;
|
|
22701
23245
|
}
|
|
22702
23246
|
}
|
|
@@ -22803,7 +23347,7 @@ var init_cleanup = __esm({
|
|
|
22803
23347
|
});
|
|
22804
23348
|
|
|
22805
23349
|
// core/commands/design.ts
|
|
22806
|
-
import
|
|
23350
|
+
import path49 from "node:path";
|
|
22807
23351
|
async function design(target = null, options = {}, projectPath = process.cwd()) {
|
|
22808
23352
|
try {
|
|
22809
23353
|
const designType = options.type || "architecture";
|
|
@@ -22815,7 +23359,7 @@ async function design(target = null, options = {}, projectPath = process.cwd())
|
|
|
22815
23359
|
const designTarget = target || "system";
|
|
22816
23360
|
output_default.spin(`designing ${designType}...`);
|
|
22817
23361
|
const projectId = await config_manager_default.getProjectId(projectPath);
|
|
22818
|
-
const designsPath =
|
|
23362
|
+
const designsPath = path49.join(
|
|
22819
23363
|
path_manager_default.getGlobalProjectPath(projectId),
|
|
22820
23364
|
"planning",
|
|
22821
23365
|
"designs"
|
|
@@ -22855,7 +23399,7 @@ async function design(target = null, options = {}, projectPath = process.cwd())
|
|
|
22855
23399
|
break;
|
|
22856
23400
|
}
|
|
22857
23401
|
const designFileName = `${designType}-${designTarget.toLowerCase().replace(/\s+/g, "-")}.md`;
|
|
22858
|
-
const designFilePath =
|
|
23402
|
+
const designFilePath = path49.join(designsPath, designFileName);
|
|
22859
23403
|
await file_helper_exports.writeFile(designFilePath, designContent);
|
|
22860
23404
|
await memoryService.log(projectPath, "design_created", {
|
|
22861
23405
|
type: designType,
|
|
@@ -22879,7 +23423,7 @@ var init_design = __esm({
|
|
|
22879
23423
|
});
|
|
22880
23424
|
|
|
22881
23425
|
// core/commands/snapshots.ts
|
|
22882
|
-
import
|
|
23426
|
+
import path50 from "node:path";
|
|
22883
23427
|
async function recover(projectPath = process.cwd()) {
|
|
22884
23428
|
try {
|
|
22885
23429
|
const projectId = await config_manager_default.getProjectId(projectPath);
|
|
@@ -22931,7 +23475,7 @@ async function undo(projectPath = process.cwd()) {
|
|
|
22931
23475
|
output_default.failWithHint("NO_PROJECT_ID");
|
|
22932
23476
|
return { success: false, error: "No project ID found" };
|
|
22933
23477
|
}
|
|
22934
|
-
const snapshotsPath =
|
|
23478
|
+
const snapshotsPath = path50.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
|
|
22935
23479
|
await file_helper_exports.ensureDir(snapshotsPath);
|
|
22936
23480
|
const { execSync: execSync7 } = await import("node:child_process");
|
|
22937
23481
|
try {
|
|
@@ -22949,7 +23493,7 @@ async function undo(projectPath = process.cwd()) {
|
|
|
22949
23493
|
cwd: projectPath,
|
|
22950
23494
|
encoding: "utf-8"
|
|
22951
23495
|
});
|
|
22952
|
-
const snapshotFile =
|
|
23496
|
+
const snapshotFile = path50.join(snapshotsPath, "history.json");
|
|
22953
23497
|
let history2 = { snapshots: [], current: -1 };
|
|
22954
23498
|
try {
|
|
22955
23499
|
const content = await file_helper_exports.readFile(snapshotFile);
|
|
@@ -22989,8 +23533,8 @@ async function redo(projectPath = process.cwd()) {
|
|
|
22989
23533
|
output_default.failWithHint("NO_PROJECT_ID");
|
|
22990
23534
|
return { success: false, error: "No project ID found" };
|
|
22991
23535
|
}
|
|
22992
|
-
const snapshotsPath =
|
|
22993
|
-
const snapshotFile =
|
|
23536
|
+
const snapshotsPath = path50.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
|
|
23537
|
+
const snapshotFile = path50.join(snapshotsPath, "history.json");
|
|
22994
23538
|
let history2;
|
|
22995
23539
|
try {
|
|
22996
23540
|
const content = await file_helper_exports.readFile(snapshotFile);
|
|
@@ -23049,8 +23593,8 @@ async function history(projectPath = process.cwd()) {
|
|
|
23049
23593
|
output_default.failWithHint("NO_PROJECT_ID");
|
|
23050
23594
|
return { success: false, error: "No project ID found" };
|
|
23051
23595
|
}
|
|
23052
|
-
const snapshotsPath =
|
|
23053
|
-
const snapshotFile =
|
|
23596
|
+
const snapshotsPath = path50.join(path_manager_default.getGlobalProjectPath(projectId), "snapshots");
|
|
23597
|
+
const snapshotFile = path50.join(snapshotsPath, "history.json");
|
|
23054
23598
|
let snapshotHistory;
|
|
23055
23599
|
try {
|
|
23056
23600
|
const content = await file_helper_exports.readFile(snapshotFile);
|
|
@@ -23157,8 +23701,8 @@ var init_maintenance = __esm({
|
|
|
23157
23701
|
});
|
|
23158
23702
|
|
|
23159
23703
|
// core/commands/setup.ts
|
|
23160
|
-
import
|
|
23161
|
-
import
|
|
23704
|
+
import fs44 from "node:fs";
|
|
23705
|
+
import path51 from "node:path";
|
|
23162
23706
|
import chalk11 from "chalk";
|
|
23163
23707
|
var SetupCommands;
|
|
23164
23708
|
var init_setup2 = __esm({
|
|
@@ -23285,7 +23829,7 @@ Please install it first:
|
|
|
23285
23829
|
try {
|
|
23286
23830
|
const claudeDir = path_manager_default.getClaudeDir();
|
|
23287
23831
|
const settingsPath = path_manager_default.getClaudeSettingsPath();
|
|
23288
|
-
const statusLinePath =
|
|
23832
|
+
const statusLinePath = path51.join(claudeDir, "prjct-statusline.sh");
|
|
23289
23833
|
const scriptContent = `#!/bin/bash
|
|
23290
23834
|
# prjct Status Line for Claude Code
|
|
23291
23835
|
# Shows version update notifications and current task
|
|
@@ -23343,11 +23887,11 @@ fi
|
|
|
23343
23887
|
# Default: show prjct branding
|
|
23344
23888
|
echo "\u26A1 prjct"
|
|
23345
23889
|
`;
|
|
23346
|
-
|
|
23890
|
+
fs44.writeFileSync(statusLinePath, scriptContent, { mode: 493 });
|
|
23347
23891
|
let settings = {};
|
|
23348
|
-
if (
|
|
23892
|
+
if (fs44.existsSync(settingsPath)) {
|
|
23349
23893
|
try {
|
|
23350
|
-
settings = JSON.parse(
|
|
23894
|
+
settings = JSON.parse(fs44.readFileSync(settingsPath, "utf8"));
|
|
23351
23895
|
} catch (_error) {
|
|
23352
23896
|
}
|
|
23353
23897
|
}
|
|
@@ -23355,7 +23899,7 @@ echo "\u26A1 prjct"
|
|
|
23355
23899
|
type: "command",
|
|
23356
23900
|
command: statusLinePath
|
|
23357
23901
|
};
|
|
23358
|
-
|
|
23902
|
+
fs44.writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
|
|
23359
23903
|
return { success: true };
|
|
23360
23904
|
} catch (error) {
|
|
23361
23905
|
return { success: false, error: error.message };
|
|
@@ -23411,18 +23955,18 @@ echo "\u26A1 prjct"
|
|
|
23411
23955
|
});
|
|
23412
23956
|
|
|
23413
23957
|
// core/utils/project-commands.ts
|
|
23414
|
-
import
|
|
23958
|
+
import path52 from "node:path";
|
|
23415
23959
|
async function detectPackageManager(projectPath, pkg) {
|
|
23416
23960
|
const declared = pkg?.packageManager?.trim().toLowerCase();
|
|
23417
23961
|
if (declared?.startsWith("pnpm@")) return "pnpm";
|
|
23418
23962
|
if (declared?.startsWith("yarn@")) return "yarn";
|
|
23419
23963
|
if (declared?.startsWith("bun@")) return "bun";
|
|
23420
23964
|
if (declared?.startsWith("npm@")) return "npm";
|
|
23421
|
-
if (await fileExists(
|
|
23422
|
-
if (await fileExists(
|
|
23423
|
-
if (await fileExists(
|
|
23424
|
-
if (await fileExists(
|
|
23425
|
-
if (await fileExists(
|
|
23965
|
+
if (await fileExists(path52.join(projectPath, "pnpm-lock.yaml"))) return "pnpm";
|
|
23966
|
+
if (await fileExists(path52.join(projectPath, "yarn.lock"))) return "yarn";
|
|
23967
|
+
if (await fileExists(path52.join(projectPath, "bun.lockb"))) return "bun";
|
|
23968
|
+
if (await fileExists(path52.join(projectPath, "bun.lock"))) return "bun";
|
|
23969
|
+
if (await fileExists(path52.join(projectPath, "package-lock.json"))) return "npm";
|
|
23426
23970
|
return "npm";
|
|
23427
23971
|
}
|
|
23428
23972
|
function pmRun(pm, scriptName) {
|
|
@@ -23438,7 +23982,7 @@ function pmTest(pm) {
|
|
|
23438
23982
|
return "npm test";
|
|
23439
23983
|
}
|
|
23440
23984
|
async function detectProjectCommands(projectPath) {
|
|
23441
|
-
const pkgPath =
|
|
23985
|
+
const pkgPath = path52.join(projectPath, "package.json");
|
|
23442
23986
|
const pkg = await readJson(pkgPath, null);
|
|
23443
23987
|
if (pkg) {
|
|
23444
23988
|
const pm = await detectPackageManager(projectPath, pkg);
|
|
@@ -23455,27 +23999,27 @@ async function detectProjectCommands(projectPath) {
|
|
|
23455
23999
|
}
|
|
23456
24000
|
return result;
|
|
23457
24001
|
}
|
|
23458
|
-
if (await fileExists(
|
|
24002
|
+
if (await fileExists(path52.join(projectPath, "pytest.ini"))) {
|
|
23459
24003
|
return { stack: "python", test: { tool: "pytest", command: "pytest" } };
|
|
23460
24004
|
}
|
|
23461
|
-
const pyproject = await readFile(
|
|
24005
|
+
const pyproject = await readFile(path52.join(projectPath, "pyproject.toml"), "");
|
|
23462
24006
|
if (pyproject.includes("[tool.pytest") || pyproject.includes("pytest")) {
|
|
23463
24007
|
return { stack: "python", test: { tool: "pytest", command: "pytest" } };
|
|
23464
24008
|
}
|
|
23465
|
-
if (await fileExists(
|
|
24009
|
+
if (await fileExists(path52.join(projectPath, "Cargo.toml"))) {
|
|
23466
24010
|
return { stack: "rust", test: { tool: "cargo", command: "cargo test" } };
|
|
23467
24011
|
}
|
|
23468
|
-
if (await fileExists(
|
|
24012
|
+
if (await fileExists(path52.join(projectPath, "go.mod"))) {
|
|
23469
24013
|
return { stack: "go", test: { tool: "go", command: "go test ./..." } };
|
|
23470
24014
|
}
|
|
23471
24015
|
const files = await listFiles(projectPath);
|
|
23472
24016
|
if (files.some((f) => f.endsWith(".sln") || f.endsWith(".csproj") || f.endsWith(".fsproj"))) {
|
|
23473
24017
|
return { stack: "dotnet", test: { tool: "dotnet", command: "dotnet test" } };
|
|
23474
24018
|
}
|
|
23475
|
-
if (await fileExists(
|
|
24019
|
+
if (await fileExists(path52.join(projectPath, "pom.xml"))) {
|
|
23476
24020
|
return { stack: "java", test: { tool: "maven", command: "mvn test" } };
|
|
23477
24021
|
}
|
|
23478
|
-
if (await fileExists(
|
|
24022
|
+
if (await fileExists(path52.join(projectPath, "gradlew")) && (await fileExists(path52.join(projectPath, "build.gradle")) || await fileExists(path52.join(projectPath, "build.gradle.kts")))) {
|
|
23479
24023
|
return { stack: "java", test: { tool: "gradle", command: "./gradlew test" } };
|
|
23480
24024
|
}
|
|
23481
24025
|
return { stack: "unknown" };
|
|
@@ -23652,7 +24196,7 @@ var init_workflow_preferences = __esm({
|
|
|
23652
24196
|
});
|
|
23653
24197
|
|
|
23654
24198
|
// core/commands/shipping.ts
|
|
23655
|
-
import
|
|
24199
|
+
import path53 from "node:path";
|
|
23656
24200
|
var ShippingCommands;
|
|
23657
24201
|
var init_shipping = __esm({
|
|
23658
24202
|
"core/commands/shipping.ts"() {
|
|
@@ -23798,7 +24342,7 @@ ${result.stderr}`.trim();
|
|
|
23798
24342
|
*/
|
|
23799
24343
|
async _bumpVersion(projectPath) {
|
|
23800
24344
|
try {
|
|
23801
|
-
const pkgPath =
|
|
24345
|
+
const pkgPath = path53.join(projectPath, "package.json");
|
|
23802
24346
|
const pkg = await file_helper_exports.readJson(pkgPath, { version: "0.0.0" });
|
|
23803
24347
|
const oldVersion = pkg?.version || "0.0.0";
|
|
23804
24348
|
const [major, minor, patch] = oldVersion.split(".").map(Number);
|
|
@@ -23820,7 +24364,7 @@ ${result.stderr}`.trim();
|
|
|
23820
24364
|
*/
|
|
23821
24365
|
async _updateChangelog(feature, version, projectPath) {
|
|
23822
24366
|
try {
|
|
23823
|
-
const changelogPath =
|
|
24367
|
+
const changelogPath = path53.join(projectPath, "CHANGELOG.md");
|
|
23824
24368
|
const changelog = await file_helper_exports.readFile(changelogPath, "# Changelog\n\n");
|
|
23825
24369
|
const entry = `## [${version}] - ${date_helper_default.formatDate(/* @__PURE__ */ new Date())}
|
|
23826
24370
|
|
|
@@ -24712,19 +25256,19 @@ var init_linear = __esm({
|
|
|
24712
25256
|
});
|
|
24713
25257
|
|
|
24714
25258
|
// core/utils/project-credentials.ts
|
|
24715
|
-
import
|
|
25259
|
+
import fs45 from "node:fs";
|
|
24716
25260
|
import os14 from "node:os";
|
|
24717
|
-
import
|
|
25261
|
+
import path54 from "node:path";
|
|
24718
25262
|
function getCredentialsPath(projectId) {
|
|
24719
|
-
return
|
|
25263
|
+
return path54.join(os14.homedir(), ".prjct-cli", "projects", projectId, "config", "credentials.json");
|
|
24720
25264
|
}
|
|
24721
25265
|
async function getProjectCredentials(projectId) {
|
|
24722
25266
|
const credPath = getCredentialsPath(projectId);
|
|
24723
|
-
if (!
|
|
25267
|
+
if (!fs45.existsSync(credPath)) {
|
|
24724
25268
|
return {};
|
|
24725
25269
|
}
|
|
24726
25270
|
try {
|
|
24727
|
-
return JSON.parse(
|
|
25271
|
+
return JSON.parse(fs45.readFileSync(credPath, "utf-8"));
|
|
24728
25272
|
} catch (error) {
|
|
24729
25273
|
console.error("[project-credentials] Failed to read credentials:", error.message);
|
|
24730
25274
|
return {};
|
|
@@ -25297,7 +25841,7 @@ var require_package = __commonJS({
|
|
|
25297
25841
|
"package.json"(exports, module) {
|
|
25298
25842
|
module.exports = {
|
|
25299
25843
|
name: "prjct-cli",
|
|
25300
|
-
version: "0.
|
|
25844
|
+
version: "0.58.0",
|
|
25301
25845
|
description: "Context layer for AI agents. Project context for Claude Code, Gemini CLI, and more.",
|
|
25302
25846
|
main: "core/index.ts",
|
|
25303
25847
|
bin: {
|
|
@@ -25404,9 +25948,9 @@ var require_package = __commonJS({
|
|
|
25404
25948
|
|
|
25405
25949
|
// core/index.ts
|
|
25406
25950
|
var core_exports = {};
|
|
25407
|
-
import
|
|
25951
|
+
import fs46 from "node:fs";
|
|
25408
25952
|
import os15 from "node:os";
|
|
25409
|
-
import
|
|
25953
|
+
import path55 from "node:path";
|
|
25410
25954
|
async function main() {
|
|
25411
25955
|
const [commandName, ...rawArgs] = process.argv.slice(2);
|
|
25412
25956
|
if (["-v", "--version", "version"].includes(commandName)) {
|
|
@@ -25487,7 +26031,8 @@ Use 'prjct --help' to see available commands.`);
|
|
|
25487
26031
|
aiTools: options.agents ? String(options.agents).split(",") : void 0,
|
|
25488
26032
|
preview: options.preview === true,
|
|
25489
26033
|
yes: options.yes === true,
|
|
25490
|
-
json: options.json === true
|
|
26034
|
+
json: options.json === true,
|
|
26035
|
+
package: options.package ? String(options.package) : void 0
|
|
25491
26036
|
}), "sync"),
|
|
25492
26037
|
start: /* @__PURE__ */ __name(() => commands.start(), "start"),
|
|
25493
26038
|
// Context (for Claude templates)
|
|
@@ -25534,12 +26079,12 @@ function parseCommandArgs(_cmd, rawArgs) {
|
|
|
25534
26079
|
}
|
|
25535
26080
|
function displayVersion(version) {
|
|
25536
26081
|
const detection = detectAllProviders();
|
|
25537
|
-
const claudeCommandPath =
|
|
25538
|
-
const geminiCommandPath =
|
|
25539
|
-
const claudeConfigured =
|
|
25540
|
-
const geminiConfigured =
|
|
25541
|
-
const cursorConfigured =
|
|
25542
|
-
const cursorExists =
|
|
26082
|
+
const claudeCommandPath = path55.join(os15.homedir(), ".claude", "commands", "p.md");
|
|
26083
|
+
const geminiCommandPath = path55.join(os15.homedir(), ".gemini", "commands", "p.toml");
|
|
26084
|
+
const claudeConfigured = fs46.existsSync(claudeCommandPath);
|
|
26085
|
+
const geminiConfigured = fs46.existsSync(geminiCommandPath);
|
|
26086
|
+
const cursorConfigured = fs46.existsSync(path55.join(process.cwd(), ".cursor", "commands", "sync.md"));
|
|
26087
|
+
const cursorExists = fs46.existsSync(path55.join(process.cwd(), ".cursor"));
|
|
25543
26088
|
console.log(`
|
|
25544
26089
|
${CYAN3}p/${RESET5} prjct v${version}
|
|
25545
26090
|
${DIM6}Context layer for AI coding agents${RESET5}
|
|
@@ -25672,9 +26217,9 @@ var init_core = __esm({
|
|
|
25672
26217
|
init_ai_provider();
|
|
25673
26218
|
init_config_manager();
|
|
25674
26219
|
init_editors_config();
|
|
25675
|
-
import
|
|
26220
|
+
import fs47 from "node:fs";
|
|
25676
26221
|
import os16 from "node:os";
|
|
25677
|
-
import
|
|
26222
|
+
import path56 from "node:path";
|
|
25678
26223
|
|
|
25679
26224
|
// core/server/server.ts
|
|
25680
26225
|
import { Hono as Hono3 } from "hono";
|
|
@@ -26416,14 +26961,14 @@ function checkRoutersInstalled() {
|
|
|
26416
26961
|
const home = os16.homedir();
|
|
26417
26962
|
const detection = detectAllProviders();
|
|
26418
26963
|
if (detection.claude.installed) {
|
|
26419
|
-
const claudeRouter =
|
|
26420
|
-
if (!
|
|
26964
|
+
const claudeRouter = path56.join(home, ".claude", "commands", "p.md");
|
|
26965
|
+
if (!fs47.existsSync(claudeRouter)) {
|
|
26421
26966
|
return false;
|
|
26422
26967
|
}
|
|
26423
26968
|
}
|
|
26424
26969
|
if (detection.gemini.installed) {
|
|
26425
|
-
const geminiRouter =
|
|
26426
|
-
if (!
|
|
26970
|
+
const geminiRouter = path56.join(home, ".gemini", "commands", "p.toml");
|
|
26971
|
+
if (!fs47.existsSync(geminiRouter)) {
|
|
26427
26972
|
return false;
|
|
26428
26973
|
}
|
|
26429
26974
|
}
|
|
@@ -26524,7 +27069,7 @@ if (args[0] === "start" || args[0] === "setup") {
|
|
|
26524
27069
|
console.error('No prjct project found. Run "prjct init" first.');
|
|
26525
27070
|
process.exitCode = 1;
|
|
26526
27071
|
} else {
|
|
26527
|
-
const linearCliPath =
|
|
27072
|
+
const linearCliPath = path56.join(__dirname, "..", "core", "cli", "linear.ts");
|
|
26528
27073
|
const linearArgs = ["--project", projectId, ...args.slice(1)];
|
|
26529
27074
|
const child = spawn("bun", [linearCliPath, ...linearArgs], {
|
|
26530
27075
|
stdio: "inherit",
|
|
@@ -26543,12 +27088,12 @@ if (args[0] === "start" || args[0] === "setup") {
|
|
|
26543
27088
|
const detection = detectAllProviders();
|
|
26544
27089
|
const home = os16.homedir();
|
|
26545
27090
|
const cwd = process.cwd();
|
|
26546
|
-
const claudeConfigured =
|
|
26547
|
-
const geminiConfigured =
|
|
26548
|
-
const cursorDetected =
|
|
26549
|
-
const cursorConfigured =
|
|
26550
|
-
const windsurfDetected =
|
|
26551
|
-
const windsurfConfigured =
|
|
27091
|
+
const claudeConfigured = fs47.existsSync(path56.join(home, ".claude", "commands", "p.md"));
|
|
27092
|
+
const geminiConfigured = fs47.existsSync(path56.join(home, ".gemini", "commands", "p.toml"));
|
|
27093
|
+
const cursorDetected = fs47.existsSync(path56.join(cwd, ".cursor"));
|
|
27094
|
+
const cursorConfigured = fs47.existsSync(path56.join(cwd, ".cursor", "rules", "prjct.mdc"));
|
|
27095
|
+
const windsurfDetected = fs47.existsSync(path56.join(cwd, ".windsurf"));
|
|
27096
|
+
const windsurfConfigured = fs47.existsSync(path56.join(cwd, ".windsurf", "rules", "prjct.md"));
|
|
26552
27097
|
const GREEN7 = "\x1B[32m";
|
|
26553
27098
|
console.log(`
|
|
26554
27099
|
${CYAN4}p/${RESET6} prjct v${VERSION}
|
|
@@ -26587,9 +27132,9 @@ ${DIM7}Run 'prjct init' to configure (Cursor/Windsurf IDE)${RESET6}
|
|
|
26587
27132
|
${CYAN4}https://prjct.app${RESET6}
|
|
26588
27133
|
`);
|
|
26589
27134
|
} else {
|
|
26590
|
-
const configPath =
|
|
27135
|
+
const configPath = path56.join(os16.homedir(), ".prjct-cli", "config", "installed-editors.json");
|
|
26591
27136
|
const routersInstalled = checkRoutersInstalled();
|
|
26592
|
-
if (!
|
|
27137
|
+
if (!fs47.existsSync(configPath) || !routersInstalled) {
|
|
26593
27138
|
console.log(`
|
|
26594
27139
|
${CYAN4}${BOLD4} Welcome to prjct!${RESET6}
|
|
26595
27140
|
|