xtrm-tools 0.5.26 → 0.5.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +5 -0
- package/README.md +8 -1
- package/cli/dist/index.cjs +263 -306
- package/cli/dist/index.cjs.map +1 -1
- package/cli/package.json +1 -1
- package/config/hooks.json +11 -10
- package/config/pi/extensions/beads/index.ts +103 -77
- package/config/pi/extensions/custom-footer/index.ts +245 -49
- package/config/pi/extensions/quality-gates/index.ts +28 -29
- package/config/pi/extensions/session-flow/index.ts +50 -21
- package/config/pi/extensions/xtrm-loader/index.ts +38 -24
- package/hooks/hooks.json +14 -0
- package/package.json +1 -1
- package/plugins/xtrm-tools/.claude-plugin/plugin.json +1 -1
- package/plugins/xtrm-tools/hooks/hooks.json +14 -0
- package/plugins/xtrm-tools/skills/planning/SKILL.md +350 -0
- package/plugins/xtrm-tools/skills/planning/evals/evals.json +19 -0
- package/skills/planning/SKILL.md +350 -0
- package/skills/planning/evals/evals.json +19 -0
- package/config/pi/extensions/plan-mode/README.md +0 -65
- package/config/pi/extensions/plan-mode/index.ts +0 -417
- package/config/pi/extensions/plan-mode/package.json +0 -12
- package/config/pi/extensions/plan-mode/utils.ts +0 -324
package/cli/dist/index.cjs
CHANGED
|
@@ -27021,19 +27021,19 @@ var require_esprima = __commonJS({
|
|
|
27021
27021
|
}
|
|
27022
27022
|
return error49;
|
|
27023
27023
|
};
|
|
27024
|
-
ErrorHandler2.prototype.createError = function(index, line,
|
|
27024
|
+
ErrorHandler2.prototype.createError = function(index, line, col, description) {
|
|
27025
27025
|
var msg = "Line " + line + ": " + description;
|
|
27026
|
-
var error49 = this.constructError(msg,
|
|
27026
|
+
var error49 = this.constructError(msg, col);
|
|
27027
27027
|
error49.index = index;
|
|
27028
27028
|
error49.lineNumber = line;
|
|
27029
27029
|
error49.description = description;
|
|
27030
27030
|
return error49;
|
|
27031
27031
|
};
|
|
27032
|
-
ErrorHandler2.prototype.throwError = function(index, line,
|
|
27033
|
-
throw this.createError(index, line,
|
|
27032
|
+
ErrorHandler2.prototype.throwError = function(index, line, col, description) {
|
|
27033
|
+
throw this.createError(index, line, col, description);
|
|
27034
27034
|
};
|
|
27035
|
-
ErrorHandler2.prototype.tolerateError = function(index, line,
|
|
27036
|
-
var error49 = this.createError(index, line,
|
|
27035
|
+
ErrorHandler2.prototype.tolerateError = function(index, line, col, description) {
|
|
27036
|
+
var error49 = this.createError(index, line, col, description);
|
|
27037
27037
|
if (this.tolerant) {
|
|
27038
27038
|
this.recordError(error49);
|
|
27039
27039
|
} else {
|
|
@@ -32847,19 +32847,19 @@ var require_layout_manager = __commonJS({
|
|
|
32847
32847
|
var Cell = require_cell();
|
|
32848
32848
|
var { ColSpanCell, RowSpanCell } = Cell;
|
|
32849
32849
|
(function() {
|
|
32850
|
-
function next(alloc,
|
|
32851
|
-
if (alloc[
|
|
32852
|
-
return next(alloc,
|
|
32850
|
+
function next(alloc, col) {
|
|
32851
|
+
if (alloc[col] > 0) {
|
|
32852
|
+
return next(alloc, col + 1);
|
|
32853
32853
|
}
|
|
32854
|
-
return
|
|
32854
|
+
return col;
|
|
32855
32855
|
}
|
|
32856
32856
|
function layoutTable(table) {
|
|
32857
32857
|
let alloc = {};
|
|
32858
32858
|
table.forEach(function(row, rowIndex) {
|
|
32859
|
-
let
|
|
32859
|
+
let col = 0;
|
|
32860
32860
|
row.forEach(function(cell) {
|
|
32861
32861
|
cell.y = rowIndex;
|
|
32862
|
-
cell.x = rowIndex ? next(alloc,
|
|
32862
|
+
cell.x = rowIndex ? next(alloc, col) : col;
|
|
32863
32863
|
const rowSpan = cell.rowSpan || 1;
|
|
32864
32864
|
const colSpan = cell.colSpan || 1;
|
|
32865
32865
|
if (rowSpan > 1) {
|
|
@@ -32867,7 +32867,7 @@ var require_layout_manager = __commonJS({
|
|
|
32867
32867
|
alloc[cell.x + cs] = rowSpan;
|
|
32868
32868
|
}
|
|
32869
32869
|
}
|
|
32870
|
-
|
|
32870
|
+
col = cell.x + colSpan;
|
|
32871
32871
|
});
|
|
32872
32872
|
Object.keys(alloc).forEach((idx) => {
|
|
32873
32873
|
alloc[idx]--;
|
|
@@ -33039,29 +33039,29 @@ var require_layout_manager = __commonJS({
|
|
|
33039
33039
|
for (let k = spanners.length - 1; k >= 0; k--) {
|
|
33040
33040
|
let cell = spanners[k];
|
|
33041
33041
|
let span = cell[colSpan];
|
|
33042
|
-
let
|
|
33043
|
-
let existingWidth = result[
|
|
33044
|
-
let editableCols = typeof vals[
|
|
33042
|
+
let col = cell[x];
|
|
33043
|
+
let existingWidth = result[col];
|
|
33044
|
+
let editableCols = typeof vals[col] === "number" ? 0 : 1;
|
|
33045
33045
|
if (typeof existingWidth === "number") {
|
|
33046
33046
|
for (let i = 1; i < span; i++) {
|
|
33047
|
-
existingWidth += 1 + result[
|
|
33048
|
-
if (typeof vals[
|
|
33047
|
+
existingWidth += 1 + result[col + i];
|
|
33048
|
+
if (typeof vals[col + i] !== "number") {
|
|
33049
33049
|
editableCols++;
|
|
33050
33050
|
}
|
|
33051
33051
|
}
|
|
33052
33052
|
} else {
|
|
33053
33053
|
existingWidth = desiredWidth === "desiredWidth" ? cell.desiredWidth - 1 : 1;
|
|
33054
|
-
if (!auto[
|
|
33055
|
-
auto[
|
|
33054
|
+
if (!auto[col] || auto[col] < existingWidth) {
|
|
33055
|
+
auto[col] = existingWidth;
|
|
33056
33056
|
}
|
|
33057
33057
|
}
|
|
33058
33058
|
if (cell[desiredWidth] > existingWidth) {
|
|
33059
33059
|
let i = 0;
|
|
33060
33060
|
while (editableCols > 0 && cell[desiredWidth] > existingWidth) {
|
|
33061
|
-
if (typeof vals[
|
|
33061
|
+
if (typeof vals[col + i] !== "number") {
|
|
33062
33062
|
let dif = Math.round((cell[desiredWidth] - existingWidth) / editableCols);
|
|
33063
33063
|
existingWidth += dif;
|
|
33064
|
-
result[
|
|
33064
|
+
result[col + i] += dif;
|
|
33065
33065
|
editableCols--;
|
|
33066
33066
|
}
|
|
33067
33067
|
i++;
|
|
@@ -35746,7 +35746,7 @@ var Listr = class {
|
|
|
35746
35746
|
};
|
|
35747
35747
|
|
|
35748
35748
|
// src/commands/install.ts
|
|
35749
|
-
var
|
|
35749
|
+
var import_fs_extra12 = __toESM(require_lib2(), 1);
|
|
35750
35750
|
var import_os5 = __toESM(require("os"), 1);
|
|
35751
35751
|
|
|
35752
35752
|
// src/core/context.ts
|
|
@@ -40801,36 +40801,49 @@ var sym = {
|
|
|
40801
40801
|
};
|
|
40802
40802
|
|
|
40803
40803
|
// src/commands/install.ts
|
|
40804
|
-
var
|
|
40804
|
+
var import_path12 = __toESM(require("path"), 1);
|
|
40805
40805
|
|
|
40806
40806
|
// src/commands/pi-install.ts
|
|
40807
|
-
var
|
|
40808
|
-
var
|
|
40807
|
+
var import_fs_extra11 = __toESM(require_lib2(), 1);
|
|
40808
|
+
var import_path11 = __toESM(require("path"), 1);
|
|
40809
40809
|
var import_node_child_process = require("child_process");
|
|
40810
40810
|
var import_node_os4 = require("os");
|
|
40811
|
-
|
|
40811
|
+
|
|
40812
|
+
// src/utils/pi-extensions.ts
|
|
40813
|
+
var import_fs_extra10 = __toESM(require_lib2(), 1);
|
|
40814
|
+
var import_path10 = __toESM(require("path"), 1);
|
|
40815
|
+
async function syncManagedPiExtensions({
|
|
40816
|
+
sourceDir,
|
|
40817
|
+
targetDir,
|
|
40818
|
+
dryRun = false,
|
|
40819
|
+
log
|
|
40820
|
+
}) {
|
|
40821
|
+
if (!await import_fs_extra10.default.pathExists(sourceDir)) return 0;
|
|
40822
|
+
if (!dryRun) {
|
|
40823
|
+
await import_fs_extra10.default.ensureDir(import_path10.default.dirname(targetDir));
|
|
40824
|
+
await import_fs_extra10.default.copy(sourceDir, targetDir, { overwrite: true });
|
|
40825
|
+
}
|
|
40826
|
+
const entries = await import_fs_extra10.default.readdir(sourceDir, { withFileTypes: true });
|
|
40827
|
+
const managedPackages = entries.filter((entry) => entry.isDirectory()).length;
|
|
40828
|
+
if (log) {
|
|
40829
|
+
if (dryRun) {
|
|
40830
|
+
log(` [DRY RUN] sync extensions ${sourceDir} -> ${targetDir}`);
|
|
40831
|
+
}
|
|
40832
|
+
log(` Pi will auto-discover ${managedPackages} extension package(s) from ${targetDir}`);
|
|
40833
|
+
}
|
|
40834
|
+
return managedPackages;
|
|
40835
|
+
}
|
|
40836
|
+
|
|
40837
|
+
// src/commands/pi-install.ts
|
|
40838
|
+
var PI_AGENT_DIR = process.env.PI_AGENT_DIR || import_path11.default.join((0, import_node_os4.homedir)(), ".pi", "agent");
|
|
40812
40839
|
function isPiInstalled() {
|
|
40813
40840
|
const r = (0, import_node_child_process.spawnSync)("pi", ["--version"], { encoding: "utf8", stdio: "pipe" });
|
|
40814
40841
|
return r.status === 0;
|
|
40815
40842
|
}
|
|
40816
|
-
async function listExtensionDirs(baseDir) {
|
|
40817
|
-
if (!await import_fs_extra10.default.pathExists(baseDir)) return [];
|
|
40818
|
-
const entries = await import_fs_extra10.default.readdir(baseDir, { withFileTypes: true });
|
|
40819
|
-
const extDirs = [];
|
|
40820
|
-
for (const entry of entries) {
|
|
40821
|
-
if (!entry.isDirectory()) continue;
|
|
40822
|
-
const extPath = import_path10.default.join(baseDir, entry.name);
|
|
40823
|
-
const pkgPath = import_path10.default.join(extPath, "package.json");
|
|
40824
|
-
if (await import_fs_extra10.default.pathExists(pkgPath)) {
|
|
40825
|
-
extDirs.push(extPath);
|
|
40826
|
-
}
|
|
40827
|
-
}
|
|
40828
|
-
return extDirs;
|
|
40829
|
-
}
|
|
40830
40843
|
async function runPiInstall(dryRun = false) {
|
|
40831
40844
|
const repoRoot = await findRepoRoot();
|
|
40832
|
-
const piConfigDir =
|
|
40833
|
-
const schemaPath =
|
|
40845
|
+
const piConfigDir = import_path11.default.join(repoRoot, "config", "pi");
|
|
40846
|
+
const schemaPath = import_path11.default.join(piConfigDir, "install-schema.json");
|
|
40834
40847
|
console.log(t.bold("\n \u2699 Pi extensions + packages"));
|
|
40835
40848
|
if (!isPiInstalled()) {
|
|
40836
40849
|
console.log(kleur_default.yellow(" pi not found \u2014 installing oh-pi globally..."));
|
|
@@ -40848,37 +40861,22 @@ async function runPiInstall(dryRun = false) {
|
|
|
40848
40861
|
const v = (0, import_node_child_process.spawnSync)("pi", ["--version"], { encoding: "utf8" });
|
|
40849
40862
|
console.log(t.success(` \u2713 pi ${v.stdout.trim()} already installed`));
|
|
40850
40863
|
}
|
|
40851
|
-
const extensionsSrc =
|
|
40852
|
-
const extensionsDst =
|
|
40853
|
-
|
|
40854
|
-
|
|
40855
|
-
|
|
40856
|
-
|
|
40857
|
-
|
|
40858
|
-
|
|
40859
|
-
|
|
40860
|
-
|
|
40861
|
-
console.log(kleur_default.dim(` Registering ${extDirs.length} extensions...`));
|
|
40862
|
-
for (const extPath of extDirs) {
|
|
40863
|
-
const extName = import_path10.default.basename(extPath);
|
|
40864
|
-
if (dryRun) {
|
|
40865
|
-
console.log(kleur_default.cyan(` [DRY RUN] pi install -l ~/.pi/agent/extensions/${extName}`));
|
|
40866
|
-
continue;
|
|
40867
|
-
}
|
|
40868
|
-
const r = (0, import_node_child_process.spawnSync)("pi", ["install", "-l", extPath], { stdio: "pipe", encoding: "utf8" });
|
|
40869
|
-
if (r.status === 0) {
|
|
40870
|
-
console.log(t.success(` ${sym.ok} ${extName} registered`));
|
|
40871
|
-
} else {
|
|
40872
|
-
console.log(kleur_default.yellow(` \u26A0 ${extName} \u2014 registration failed`));
|
|
40873
|
-
}
|
|
40874
|
-
}
|
|
40875
|
-
}
|
|
40864
|
+
const extensionsSrc = import_path11.default.join(piConfigDir, "extensions");
|
|
40865
|
+
const extensionsDst = import_path11.default.join(PI_AGENT_DIR, "extensions");
|
|
40866
|
+
const managedPackages = await syncManagedPiExtensions({
|
|
40867
|
+
sourceDir: extensionsSrc,
|
|
40868
|
+
targetDir: extensionsDst,
|
|
40869
|
+
dryRun,
|
|
40870
|
+
log: (message) => console.log(kleur_default.dim(message))
|
|
40871
|
+
});
|
|
40872
|
+
if (managedPackages > 0) {
|
|
40873
|
+
console.log(t.success(` ${sym.ok} extensions synced (${managedPackages} packages)`));
|
|
40876
40874
|
}
|
|
40877
|
-
if (!await
|
|
40875
|
+
if (!await import_fs_extra11.default.pathExists(schemaPath)) {
|
|
40878
40876
|
console.log(kleur_default.dim(" No install-schema.json found, skipping packages"));
|
|
40879
40877
|
return;
|
|
40880
40878
|
}
|
|
40881
|
-
const schema = await
|
|
40879
|
+
const schema = await import_fs_extra11.default.readJson(schemaPath);
|
|
40882
40880
|
for (const pkg of schema.packages) {
|
|
40883
40881
|
if (dryRun) {
|
|
40884
40882
|
console.log(kleur_default.cyan(` [DRY RUN] pi install ${pkg}`));
|
|
@@ -40944,7 +40942,7 @@ function formatTargetLabel(target) {
|
|
|
40944
40942
|
const normalized = target.replace(/\\/g, "/").toLowerCase();
|
|
40945
40943
|
if (normalized.endsWith("/.agents/skills") || normalized.includes("/.agents/skills/")) return "~/.agents/skills";
|
|
40946
40944
|
if (normalized.endsWith("/.claude") || normalized.includes("/.claude/")) return "~/.claude";
|
|
40947
|
-
return
|
|
40945
|
+
return import_path12.default.basename(target);
|
|
40948
40946
|
}
|
|
40949
40947
|
function isBeadsInstalled() {
|
|
40950
40948
|
try {
|
|
@@ -40974,15 +40972,15 @@ async function needsSettingsSync(repoRoot, target) {
|
|
|
40974
40972
|
const normalizedTarget = target.replace(/\\/g, "/").toLowerCase();
|
|
40975
40973
|
if (normalizedTarget.includes(".agents/skills")) return false;
|
|
40976
40974
|
if (detectAgent(target) === "claude") return false;
|
|
40977
|
-
const hooksTemplatePath =
|
|
40978
|
-
if (!await
|
|
40979
|
-
const requiredEvents = Object.keys((await
|
|
40975
|
+
const hooksTemplatePath = import_path12.default.join(repoRoot, "config", "hooks.json");
|
|
40976
|
+
if (!await import_fs_extra12.default.pathExists(hooksTemplatePath)) return false;
|
|
40977
|
+
const requiredEvents = Object.keys((await import_fs_extra12.default.readJson(hooksTemplatePath)).hooks ?? {});
|
|
40980
40978
|
if (requiredEvents.length === 0) return false;
|
|
40981
|
-
const targetSettingsPath =
|
|
40982
|
-
if (!await
|
|
40979
|
+
const targetSettingsPath = import_path12.default.join(target, "settings.json");
|
|
40980
|
+
if (!await import_fs_extra12.default.pathExists(targetSettingsPath)) return true;
|
|
40983
40981
|
let settings = {};
|
|
40984
40982
|
try {
|
|
40985
|
-
settings = await
|
|
40983
|
+
settings = await import_fs_extra12.default.readJson(targetSettingsPath);
|
|
40986
40984
|
} catch {
|
|
40987
40985
|
return true;
|
|
40988
40986
|
}
|
|
@@ -41027,46 +41025,46 @@ async function installOfficialClaudePlugins(dryRun) {
|
|
|
41027
41025
|
}
|
|
41028
41026
|
async function cleanStalePrePluginFiles(repoRoot, dryRun) {
|
|
41029
41027
|
const home = import_os5.default.homedir();
|
|
41030
|
-
const staleHooksDir =
|
|
41031
|
-
const staleSkillsDir =
|
|
41032
|
-
const settingsPath =
|
|
41028
|
+
const staleHooksDir = import_path12.default.join(home, ".claude", "hooks");
|
|
41029
|
+
const staleSkillsDir = import_path12.default.join(home, ".claude", "skills");
|
|
41030
|
+
const settingsPath = import_path12.default.join(home, ".claude", "settings.json");
|
|
41033
41031
|
const removed = [];
|
|
41034
|
-
const repoHooksDir =
|
|
41035
|
-
if (await
|
|
41036
|
-
const repoHookNames = (await
|
|
41032
|
+
const repoHooksDir = import_path12.default.join(repoRoot, "hooks");
|
|
41033
|
+
if (await import_fs_extra12.default.pathExists(repoHooksDir) && await import_fs_extra12.default.pathExists(staleHooksDir)) {
|
|
41034
|
+
const repoHookNames = (await import_fs_extra12.default.readdir(repoHooksDir)).filter((n) => n !== "README.md" && n !== "hooks.json");
|
|
41037
41035
|
for (const name of repoHookNames) {
|
|
41038
|
-
const staleFile =
|
|
41039
|
-
if (await
|
|
41036
|
+
const staleFile = import_path12.default.join(staleHooksDir, name);
|
|
41037
|
+
if (await import_fs_extra12.default.pathExists(staleFile)) {
|
|
41040
41038
|
if (dryRun) {
|
|
41041
41039
|
console.log(t.accent(` [DRY RUN] Would remove stale hook: ~/.claude/hooks/${name}`));
|
|
41042
41040
|
} else {
|
|
41043
|
-
await
|
|
41041
|
+
await import_fs_extra12.default.remove(staleFile);
|
|
41044
41042
|
console.log(t.muted(` \u2717 Removed stale hook: ~/.claude/hooks/${name}`));
|
|
41045
41043
|
}
|
|
41046
41044
|
removed.push(`hooks/${name}`);
|
|
41047
41045
|
}
|
|
41048
41046
|
}
|
|
41049
41047
|
}
|
|
41050
|
-
const repoSkillsDir =
|
|
41051
|
-
if (await
|
|
41052
|
-
const repoSkillNames = (await
|
|
41048
|
+
const repoSkillsDir = import_path12.default.join(repoRoot, "skills");
|
|
41049
|
+
if (await import_fs_extra12.default.pathExists(repoSkillsDir) && await import_fs_extra12.default.pathExists(staleSkillsDir)) {
|
|
41050
|
+
const repoSkillNames = (await import_fs_extra12.default.readdir(repoSkillsDir)).filter((n) => !n.startsWith("."));
|
|
41053
41051
|
for (const name of repoSkillNames) {
|
|
41054
|
-
const staleDir =
|
|
41055
|
-
if (await
|
|
41052
|
+
const staleDir = import_path12.default.join(staleSkillsDir, name);
|
|
41053
|
+
if (await import_fs_extra12.default.pathExists(staleDir)) {
|
|
41056
41054
|
if (dryRun) {
|
|
41057
41055
|
console.log(t.accent(` [DRY RUN] Would remove stale skill: ~/.claude/skills/${name}`));
|
|
41058
41056
|
} else {
|
|
41059
|
-
await
|
|
41057
|
+
await import_fs_extra12.default.remove(staleDir);
|
|
41060
41058
|
console.log(t.muted(` \u2717 Removed stale skill: ~/.claude/skills/${name}`));
|
|
41061
41059
|
}
|
|
41062
41060
|
removed.push(`skills/${name}`);
|
|
41063
41061
|
}
|
|
41064
41062
|
}
|
|
41065
41063
|
}
|
|
41066
|
-
if (await
|
|
41064
|
+
if (await import_fs_extra12.default.pathExists(settingsPath)) {
|
|
41067
41065
|
let settings;
|
|
41068
41066
|
try {
|
|
41069
|
-
settings = await
|
|
41067
|
+
settings = await import_fs_extra12.default.readJson(settingsPath);
|
|
41070
41068
|
} catch {
|
|
41071
41069
|
settings = null;
|
|
41072
41070
|
}
|
|
@@ -41107,7 +41105,7 @@ async function cleanStalePrePluginFiles(repoRoot, dryRun) {
|
|
|
41107
41105
|
}
|
|
41108
41106
|
}
|
|
41109
41107
|
if (settingsModified && !dryRun) {
|
|
41110
|
-
await
|
|
41108
|
+
await import_fs_extra12.default.writeJson(settingsPath, settings, { spaces: 2 });
|
|
41111
41109
|
}
|
|
41112
41110
|
}
|
|
41113
41111
|
}
|
|
@@ -41123,7 +41121,7 @@ async function installPlugin(repoRoot, dryRun) {
|
|
|
41123
41121
|
await installOfficialClaudePlugins(true);
|
|
41124
41122
|
return;
|
|
41125
41123
|
}
|
|
41126
|
-
const xtrmPkgRoot =
|
|
41124
|
+
const xtrmPkgRoot = import_path12.default.resolve(__dirname, "..", "..");
|
|
41127
41125
|
(0, import_child_process3.spawnSync)("claude", ["plugin", "marketplace", "add", xtrmPkgRoot, "--scope", "user"], { stdio: "pipe" });
|
|
41128
41126
|
const listResult = (0, import_child_process3.spawnSync)("claude", ["plugin", "list"], { encoding: "utf8", stdio: "pipe" });
|
|
41129
41127
|
if (listResult.stdout?.includes("xtrm-tools@xtrm-tools")) {
|
|
@@ -41499,31 +41497,31 @@ function createClaudeCommand() {
|
|
|
41499
41497
|
}
|
|
41500
41498
|
|
|
41501
41499
|
// src/commands/pi.ts
|
|
41502
|
-
var
|
|
41500
|
+
var import_path14 = __toESM(require("path"), 1);
|
|
41503
41501
|
var import_node_child_process5 = require("child_process");
|
|
41504
41502
|
var import_node_os7 = require("os");
|
|
41505
|
-
var
|
|
41503
|
+
var import_fs_extra14 = __toESM(require_lib2(), 1);
|
|
41506
41504
|
|
|
41507
41505
|
// src/commands/install-pi.ts
|
|
41508
41506
|
var import_prompts2 = __toESM(require_prompts3(), 1);
|
|
41509
|
-
var
|
|
41510
|
-
var
|
|
41507
|
+
var import_fs_extra13 = __toESM(require_lib2(), 1);
|
|
41508
|
+
var import_path13 = __toESM(require("path"), 1);
|
|
41511
41509
|
var import_node_child_process4 = require("child_process");
|
|
41512
41510
|
var import_node_os6 = require("os");
|
|
41513
|
-
var PI_AGENT_DIR2 = process.env.PI_AGENT_DIR ||
|
|
41511
|
+
var PI_AGENT_DIR2 = process.env.PI_AGENT_DIR || import_path13.default.join((0, import_node_os6.homedir)(), ".pi", "agent");
|
|
41514
41512
|
function fillTemplate(template, values) {
|
|
41515
41513
|
return template.replace(/\{\{(\w+)\}\}/g, (_, key) => values[key] ?? "");
|
|
41516
41514
|
}
|
|
41517
41515
|
function readExistingPiValues(piAgentDir) {
|
|
41518
41516
|
const values = {};
|
|
41519
41517
|
try {
|
|
41520
|
-
const auth = JSON.parse(require("fs").readFileSync(
|
|
41518
|
+
const auth = JSON.parse(require("fs").readFileSync(import_path13.default.join(piAgentDir, "auth.json"), "utf8"));
|
|
41521
41519
|
if (auth?.dashscope?.key) values["DASHSCOPE_API_KEY"] = auth.dashscope.key;
|
|
41522
41520
|
if (auth?.zai?.key) values["ZAI_API_KEY"] = auth.zai.key;
|
|
41523
41521
|
} catch {
|
|
41524
41522
|
}
|
|
41525
41523
|
try {
|
|
41526
|
-
const models = JSON.parse(require("fs").readFileSync(
|
|
41524
|
+
const models = JSON.parse(require("fs").readFileSync(import_path13.default.join(piAgentDir, "models.json"), "utf8"));
|
|
41527
41525
|
if (!values["DASHSCOPE_API_KEY"] && models?.providers?.dashscope?.apiKey) {
|
|
41528
41526
|
values["DASHSCOPE_API_KEY"] = models.providers.dashscope.apiKey;
|
|
41529
41527
|
}
|
|
@@ -41534,15 +41532,15 @@ function readExistingPiValues(piAgentDir) {
|
|
|
41534
41532
|
function isPiInstalled2() {
|
|
41535
41533
|
return (0, import_node_child_process4.spawnSync)("pi", ["--version"], { encoding: "utf8" }).status === 0;
|
|
41536
41534
|
}
|
|
41537
|
-
async function
|
|
41538
|
-
if (!await
|
|
41539
|
-
const entries = await
|
|
41535
|
+
async function listExtensionDirs(baseDir) {
|
|
41536
|
+
if (!await import_fs_extra13.default.pathExists(baseDir)) return [];
|
|
41537
|
+
const entries = await import_fs_extra13.default.readdir(baseDir, { withFileTypes: true });
|
|
41540
41538
|
const extDirs = [];
|
|
41541
41539
|
for (const entry of entries) {
|
|
41542
41540
|
if (!entry.isDirectory()) continue;
|
|
41543
|
-
const extPath =
|
|
41544
|
-
const pkgPath =
|
|
41545
|
-
if (await
|
|
41541
|
+
const extPath = import_path13.default.join(baseDir, entry.name);
|
|
41542
|
+
const pkgPath = import_path13.default.join(extPath, "package.json");
|
|
41543
|
+
if (await import_fs_extra13.default.pathExists(pkgPath)) {
|
|
41546
41544
|
extDirs.push(entry.name);
|
|
41547
41545
|
}
|
|
41548
41546
|
}
|
|
@@ -41550,37 +41548,37 @@ async function listExtensionDirs2(baseDir) {
|
|
|
41550
41548
|
}
|
|
41551
41549
|
async function fileSha256(filePath) {
|
|
41552
41550
|
const crypto2 = await import("crypto");
|
|
41553
|
-
const content = await
|
|
41551
|
+
const content = await import_fs_extra13.default.readFile(filePath);
|
|
41554
41552
|
return crypto2.createHash("sha256").update(content).digest("hex");
|
|
41555
41553
|
}
|
|
41556
41554
|
async function extensionHash(extDir) {
|
|
41557
|
-
const pkgPath =
|
|
41558
|
-
const indexPath =
|
|
41555
|
+
const pkgPath = import_path13.default.join(extDir, "package.json");
|
|
41556
|
+
const indexPath = import_path13.default.join(extDir, "index.ts");
|
|
41559
41557
|
const hashes = [];
|
|
41560
|
-
if (await
|
|
41558
|
+
if (await import_fs_extra13.default.pathExists(pkgPath)) {
|
|
41561
41559
|
hashes.push(await fileSha256(pkgPath));
|
|
41562
41560
|
}
|
|
41563
|
-
if (await
|
|
41561
|
+
if (await import_fs_extra13.default.pathExists(indexPath)) {
|
|
41564
41562
|
hashes.push(await fileSha256(indexPath));
|
|
41565
41563
|
}
|
|
41566
41564
|
return hashes.join(":");
|
|
41567
41565
|
}
|
|
41568
41566
|
async function diffPiExtensions(sourceDir, targetDir) {
|
|
41569
|
-
const sourceAbs =
|
|
41570
|
-
const targetAbs =
|
|
41571
|
-
const sourceExts = await
|
|
41567
|
+
const sourceAbs = import_path13.default.resolve(sourceDir);
|
|
41568
|
+
const targetAbs = import_path13.default.resolve(targetDir);
|
|
41569
|
+
const sourceExts = await listExtensionDirs(sourceAbs);
|
|
41572
41570
|
const missing = [];
|
|
41573
41571
|
const stale = [];
|
|
41574
41572
|
const upToDate = [];
|
|
41575
41573
|
for (const extName of sourceExts) {
|
|
41576
|
-
const srcExtPath =
|
|
41577
|
-
const dstExtPath =
|
|
41578
|
-
if (!await
|
|
41574
|
+
const srcExtPath = import_path13.default.join(sourceAbs, extName);
|
|
41575
|
+
const dstExtPath = import_path13.default.join(targetAbs, extName);
|
|
41576
|
+
if (!await import_fs_extra13.default.pathExists(dstExtPath)) {
|
|
41579
41577
|
missing.push(extName);
|
|
41580
41578
|
continue;
|
|
41581
41579
|
}
|
|
41582
|
-
const dstPkgPath =
|
|
41583
|
-
if (!await
|
|
41580
|
+
const dstPkgPath = import_path13.default.join(dstExtPath, "package.json");
|
|
41581
|
+
if (!await import_fs_extra13.default.pathExists(dstPkgPath)) {
|
|
41584
41582
|
missing.push(extName);
|
|
41585
41583
|
continue;
|
|
41586
41584
|
}
|
|
@@ -41619,10 +41617,10 @@ function createInstallPiCommand() {
|
|
|
41619
41617
|
cmd.description("Install Pi coding agent with providers, extensions, and npm packages").option("-y, --yes", "Skip confirmation prompts", false).option("--check", "Check Pi extension deployment drift without writing changes", false).action(async (opts) => {
|
|
41620
41618
|
const { yes, check: check2 } = opts;
|
|
41621
41619
|
const repoRoot = await findRepoRoot();
|
|
41622
|
-
const piConfigDir =
|
|
41620
|
+
const piConfigDir = import_path13.default.join(repoRoot, "config", "pi");
|
|
41623
41621
|
if (check2) {
|
|
41624
|
-
const sourceDir =
|
|
41625
|
-
const targetDir =
|
|
41622
|
+
const sourceDir = import_path13.default.join(piConfigDir, "extensions");
|
|
41623
|
+
const targetDir = import_path13.default.join(PI_AGENT_DIR2, "extensions");
|
|
41626
41624
|
const diff = await diffPiExtensions(sourceDir, targetDir);
|
|
41627
41625
|
printPiCheckSummary(diff);
|
|
41628
41626
|
if (diff.missing.length > 0 || diff.stale.length > 0) {
|
|
@@ -41645,7 +41643,7 @@ function createInstallPiCommand() {
|
|
|
41645
41643
|
console.log(t.success(` pi ${v.stdout.trim()} already installed
|
|
41646
41644
|
`));
|
|
41647
41645
|
}
|
|
41648
|
-
const schema = await
|
|
41646
|
+
const schema = await import_fs_extra13.default.readJson(import_path13.default.join(piConfigDir, "install-schema.json"));
|
|
41649
41647
|
const existing = readExistingPiValues(PI_AGENT_DIR2);
|
|
41650
41648
|
const values = { ...existing };
|
|
41651
41649
|
console.log(t.bold(" API Keys\n"));
|
|
@@ -41661,37 +41659,30 @@ function createInstallPiCommand() {
|
|
|
41661
41659
|
const { value } = await (0, import_prompts2.default)({ type: field.secret ? "password" : "text", name: "value", message: ` ${field.label}`, hint: field.hint, validate: (v) => field.required && !v ? "Required" : true });
|
|
41662
41660
|
if (value) values[field.key] = value;
|
|
41663
41661
|
}
|
|
41664
|
-
await
|
|
41662
|
+
await import_fs_extra13.default.ensureDir(PI_AGENT_DIR2);
|
|
41665
41663
|
console.log(t.muted(`
|
|
41666
41664
|
Writing config to ${PI_AGENT_DIR2}`));
|
|
41667
41665
|
for (const name of ["models.json", "auth.json", "settings.json"]) {
|
|
41668
|
-
const destPath =
|
|
41669
|
-
if (name === "auth.json" && await
|
|
41666
|
+
const destPath = import_path13.default.join(PI_AGENT_DIR2, name);
|
|
41667
|
+
if (name === "auth.json" && await import_fs_extra13.default.pathExists(destPath) && !yes) {
|
|
41670
41668
|
const { overwrite } = await (0, import_prompts2.default)({ type: "confirm", name: "overwrite", message: ` ${name} already exists \u2014 overwrite? (OAuth tokens will be lost)`, initial: false });
|
|
41671
41669
|
if (!overwrite) {
|
|
41672
41670
|
console.log(t.muted(` skipped ${name}`));
|
|
41673
41671
|
continue;
|
|
41674
41672
|
}
|
|
41675
41673
|
}
|
|
41676
|
-
const raw = await
|
|
41677
|
-
await
|
|
41674
|
+
const raw = await import_fs_extra13.default.readFile(import_path13.default.join(piConfigDir, `${name}.template`), "utf8");
|
|
41675
|
+
await import_fs_extra13.default.writeFile(destPath, fillTemplate(raw, values), "utf8");
|
|
41678
41676
|
console.log(t.success(` ${sym.ok} ${name}`));
|
|
41679
41677
|
}
|
|
41680
|
-
|
|
41681
|
-
|
|
41682
|
-
|
|
41683
|
-
|
|
41684
|
-
console.log(kleur_default.dim(`
|
|
41685
|
-
|
|
41686
|
-
|
|
41687
|
-
|
|
41688
|
-
const r = (0, import_node_child_process4.spawnSync)("pi", ["install", "-l", extPath], { stdio: "pipe", encoding: "utf8" });
|
|
41689
|
-
if (r.status === 0) {
|
|
41690
|
-
console.log(t.success(` ${sym.ok} ${extName} registered`));
|
|
41691
|
-
} else {
|
|
41692
|
-
console.log(kleur_default.yellow(` \u26A0 ${extName} \u2014 registration failed`));
|
|
41693
|
-
}
|
|
41694
|
-
}
|
|
41678
|
+
const managedPackages = await syncManagedPiExtensions({
|
|
41679
|
+
sourceDir: import_path13.default.join(piConfigDir, "extensions"),
|
|
41680
|
+
targetDir: import_path13.default.join(PI_AGENT_DIR2, "extensions"),
|
|
41681
|
+
dryRun: false,
|
|
41682
|
+
log: (message) => console.log(kleur_default.dim(` ${message}`))
|
|
41683
|
+
});
|
|
41684
|
+
if (managedPackages > 0) {
|
|
41685
|
+
console.log(t.success(` ${sym.ok} extensions/ (${managedPackages} packages)`));
|
|
41695
41686
|
}
|
|
41696
41687
|
console.log(t.bold("\n npm Packages\n"));
|
|
41697
41688
|
for (const pkg of schema.packages) {
|
|
@@ -41709,7 +41700,7 @@ function createInstallPiCommand() {
|
|
|
41709
41700
|
}
|
|
41710
41701
|
|
|
41711
41702
|
// src/commands/pi.ts
|
|
41712
|
-
var PI_AGENT_DIR3 = process.env.PI_AGENT_DIR ||
|
|
41703
|
+
var PI_AGENT_DIR3 = process.env.PI_AGENT_DIR || import_path14.default.join((0, import_node_os7.homedir)(), ".pi", "agent");
|
|
41713
41704
|
function createPiCommand() {
|
|
41714
41705
|
const cmd = new Command("pi").description("Launch a Pi session in a sandboxed worktree, or manage the Pi runtime").argument("[name]", "Optional session name \u2014 used as xt/<name> branch (random if omitted)").action(async (name) => {
|
|
41715
41706
|
await launchWorktreeSession({ runtime: "pi", name });
|
|
@@ -41732,8 +41723,8 @@ function createPiCommand() {
|
|
|
41732
41723
|
return;
|
|
41733
41724
|
}
|
|
41734
41725
|
const repoRoot = await findRepoRoot();
|
|
41735
|
-
const sourceDir =
|
|
41736
|
-
const targetDir =
|
|
41726
|
+
const sourceDir = import_path14.default.join(repoRoot, "config", "pi", "extensions");
|
|
41727
|
+
const targetDir = import_path14.default.join(PI_AGENT_DIR3, "extensions");
|
|
41737
41728
|
const diff = await diffPiExtensions(sourceDir, targetDir);
|
|
41738
41729
|
if (diff.missing.length === 0 && diff.stale.length === 0) {
|
|
41739
41730
|
console.log(t.success(` \u2713 extensions up-to-date (${diff.upToDate.length} deployed)`));
|
|
@@ -41755,9 +41746,9 @@ function createPiCommand() {
|
|
|
41755
41746
|
allOk = false;
|
|
41756
41747
|
}
|
|
41757
41748
|
const repoRoot = await findRepoRoot();
|
|
41758
|
-
const piConfigDir =
|
|
41759
|
-
const sourceDir =
|
|
41760
|
-
const targetDir =
|
|
41749
|
+
const piConfigDir = import_path14.default.join(repoRoot, "config", "pi");
|
|
41750
|
+
const sourceDir = import_path14.default.join(piConfigDir, "extensions");
|
|
41751
|
+
const targetDir = import_path14.default.join(PI_AGENT_DIR3, "extensions");
|
|
41761
41752
|
const diff = await diffPiExtensions(sourceDir, targetDir);
|
|
41762
41753
|
if (diff.missing.length === 0 && diff.stale.length === 0) {
|
|
41763
41754
|
console.log(t.success(` \u2713 extensions deployed (${diff.upToDate.length})`));
|
|
@@ -41765,11 +41756,11 @@ function createPiCommand() {
|
|
|
41765
41756
|
console.log(kleur_default.yellow(` \u26A0 extension drift (${diff.missing.length} missing, ${diff.stale.length} stale)`));
|
|
41766
41757
|
allOk = false;
|
|
41767
41758
|
}
|
|
41768
|
-
const schemaPath =
|
|
41769
|
-
if (await
|
|
41759
|
+
const schemaPath = import_path14.default.join(piConfigDir, "install-schema.json");
|
|
41760
|
+
if (await import_fs_extra14.default.pathExists(schemaPath)) {
|
|
41770
41761
|
try {
|
|
41771
41762
|
(0, import_node_child_process5.execSync)("pi --version", { stdio: "ignore" });
|
|
41772
|
-
const schema = await
|
|
41763
|
+
const schema = await import_fs_extra14.default.readJson(schemaPath);
|
|
41773
41764
|
const listResult = (0, import_node_child_process5.spawnSync)("pi", ["list"], { encoding: "utf8", stdio: "pipe" });
|
|
41774
41765
|
const installed = listResult.stdout ?? "";
|
|
41775
41766
|
const missing = schema.packages.filter((p) => !installed.includes(p.replace("npm:", "")));
|
|
@@ -41797,43 +41788,43 @@ function createPiCommand() {
|
|
|
41797
41788
|
}
|
|
41798
41789
|
|
|
41799
41790
|
// src/commands/init.ts
|
|
41800
|
-
var
|
|
41801
|
-
var
|
|
41791
|
+
var import_path16 = __toESM(require("path"), 1);
|
|
41792
|
+
var import_fs_extra16 = __toESM(require_lib2(), 1);
|
|
41802
41793
|
var import_child_process4 = require("child_process");
|
|
41803
41794
|
|
|
41804
41795
|
// src/commands/install-service-skills.ts
|
|
41805
|
-
var
|
|
41806
|
-
var
|
|
41796
|
+
var import_path15 = __toESM(require("path"), 1);
|
|
41797
|
+
var import_fs_extra15 = __toESM(require_lib2(), 1);
|
|
41807
41798
|
function resolvePkgRoot() {
|
|
41808
41799
|
const candidates = [
|
|
41809
|
-
|
|
41810
|
-
|
|
41800
|
+
import_path15.default.resolve(__dirname, "../.."),
|
|
41801
|
+
import_path15.default.resolve(__dirname, "../../..")
|
|
41811
41802
|
];
|
|
41812
|
-
const match = candidates.find((candidate) =>
|
|
41803
|
+
const match = candidates.find((candidate) => import_fs_extra15.default.existsSync(import_path15.default.join(candidate, "project-skills")));
|
|
41813
41804
|
if (!match) {
|
|
41814
41805
|
throw new Error("Unable to locate project-skills directory from CLI runtime.");
|
|
41815
41806
|
}
|
|
41816
41807
|
return match;
|
|
41817
41808
|
}
|
|
41818
41809
|
var PKG_ROOT = resolvePkgRoot();
|
|
41819
|
-
var SKILLS_SRC =
|
|
41810
|
+
var SKILLS_SRC = import_path15.default.join(PKG_ROOT, "project-skills", "service-skills-set", ".claude");
|
|
41820
41811
|
|
|
41821
41812
|
// src/commands/init.ts
|
|
41822
41813
|
function resolvePkgRoot2() {
|
|
41823
41814
|
const candidates = [
|
|
41824
|
-
|
|
41825
|
-
|
|
41815
|
+
import_path16.default.resolve(__dirname, "../.."),
|
|
41816
|
+
import_path16.default.resolve(__dirname, "../../..")
|
|
41826
41817
|
];
|
|
41827
|
-
const match = candidates.find((candidate) =>
|
|
41818
|
+
const match = candidates.find((candidate) => import_fs_extra16.default.existsSync(import_path16.default.join(candidate, "project-skills")));
|
|
41828
41819
|
if (!match) {
|
|
41829
41820
|
throw new Error("Unable to locate project-skills directory from CLI runtime.");
|
|
41830
41821
|
}
|
|
41831
41822
|
return match;
|
|
41832
41823
|
}
|
|
41833
41824
|
var PKG_ROOT2 = resolvePkgRoot2();
|
|
41834
|
-
var PROJECT_SKILLS_DIR =
|
|
41835
|
-
var MCP_CORE_CONFIG_PATH =
|
|
41836
|
-
var INSTRUCTIONS_DIR =
|
|
41825
|
+
var PROJECT_SKILLS_DIR = import_path16.default.join(PKG_ROOT2, "project-skills");
|
|
41826
|
+
var MCP_CORE_CONFIG_PATH = import_path16.default.join(PKG_ROOT2, "config", "mcp_servers.json");
|
|
41827
|
+
var INSTRUCTIONS_DIR = import_path16.default.join(PKG_ROOT2, "config", "instructions");
|
|
41837
41828
|
var XTRM_BLOCK_START = "<!-- xtrm:start -->";
|
|
41838
41829
|
var XTRM_BLOCK_END = "<!-- xtrm:end -->";
|
|
41839
41830
|
function parseComposeServices(content) {
|
|
@@ -41859,8 +41850,8 @@ function parseComposeServices(content) {
|
|
|
41859
41850
|
return [...services];
|
|
41860
41851
|
}
|
|
41861
41852
|
async function detectProjectFeatures(projectRoot) {
|
|
41862
|
-
const hasTypeScript = await
|
|
41863
|
-
const hasPython = await
|
|
41853
|
+
const hasTypeScript = await import_fs_extra16.default.pathExists(import_path16.default.join(projectRoot, "tsconfig.json"));
|
|
41854
|
+
const hasPython = await import_fs_extra16.default.pathExists(import_path16.default.join(projectRoot, "pyproject.toml")) || await import_fs_extra16.default.pathExists(import_path16.default.join(projectRoot, "setup.py")) || await import_fs_extra16.default.pathExists(import_path16.default.join(projectRoot, "requirements.txt"));
|
|
41864
41855
|
const composeCandidates = [
|
|
41865
41856
|
"docker-compose.yml",
|
|
41866
41857
|
"docker-compose.yaml",
|
|
@@ -41869,19 +41860,19 @@ async function detectProjectFeatures(projectRoot) {
|
|
|
41869
41860
|
];
|
|
41870
41861
|
const dockerServices = /* @__PURE__ */ new Set();
|
|
41871
41862
|
for (const composeFile of composeCandidates) {
|
|
41872
|
-
const composePath =
|
|
41873
|
-
if (!await
|
|
41863
|
+
const composePath = import_path16.default.join(projectRoot, composeFile);
|
|
41864
|
+
if (!await import_fs_extra16.default.pathExists(composePath)) continue;
|
|
41874
41865
|
try {
|
|
41875
|
-
const content = await
|
|
41866
|
+
const content = await import_fs_extra16.default.readFile(composePath, "utf8");
|
|
41876
41867
|
for (const service of parseComposeServices(content)) {
|
|
41877
41868
|
dockerServices.add(service);
|
|
41878
41869
|
}
|
|
41879
41870
|
} catch {
|
|
41880
41871
|
}
|
|
41881
41872
|
}
|
|
41882
|
-
const hasDockerfile = await
|
|
41873
|
+
const hasDockerfile = await import_fs_extra16.default.pathExists(import_path16.default.join(projectRoot, "Dockerfile"));
|
|
41883
41874
|
if (hasDockerfile && dockerServices.size === 0) {
|
|
41884
|
-
dockerServices.add(
|
|
41875
|
+
dockerServices.add(import_path16.default.basename(projectRoot));
|
|
41885
41876
|
}
|
|
41886
41877
|
return {
|
|
41887
41878
|
hasTypeScript,
|
|
@@ -41915,20 +41906,20 @@ async function injectProjectInstructionHeaders(projectRoot) {
|
|
|
41915
41906
|
];
|
|
41916
41907
|
console.log(kleur_default.bold("Injecting xtrm agent instruction headers..."));
|
|
41917
41908
|
for (const target of targets) {
|
|
41918
|
-
const templatePath =
|
|
41919
|
-
if (!await
|
|
41909
|
+
const templatePath = import_path16.default.join(INSTRUCTIONS_DIR, target.template);
|
|
41910
|
+
if (!await import_fs_extra16.default.pathExists(templatePath)) {
|
|
41920
41911
|
console.log(kleur_default.yellow(` \u26A0 Missing template: ${target.template}`));
|
|
41921
41912
|
continue;
|
|
41922
41913
|
}
|
|
41923
|
-
const template = await
|
|
41924
|
-
const outputPath =
|
|
41925
|
-
const existing = await
|
|
41914
|
+
const template = await import_fs_extra16.default.readFile(templatePath, "utf8");
|
|
41915
|
+
const outputPath = import_path16.default.join(projectRoot, target.output);
|
|
41916
|
+
const existing = await import_fs_extra16.default.pathExists(outputPath) ? await import_fs_extra16.default.readFile(outputPath, "utf8") : "";
|
|
41926
41917
|
const next = upsertManagedBlock(existing, template);
|
|
41927
41918
|
if (next === existing) {
|
|
41928
41919
|
console.log(kleur_default.dim(` \u2713 ${target.output} already up to date`));
|
|
41929
41920
|
continue;
|
|
41930
41921
|
}
|
|
41931
|
-
await
|
|
41922
|
+
await import_fs_extra16.default.writeFile(outputPath, next.endsWith("\n") ? next : `${next}
|
|
41932
41923
|
`, "utf8");
|
|
41933
41924
|
console.log(`${kleur_default.green(" \u2713")} updated ${target.output}`);
|
|
41934
41925
|
}
|
|
@@ -42065,14 +42056,14 @@ function getProjectRoot() {
|
|
|
42065
42056
|
if (result.status !== 0) {
|
|
42066
42057
|
throw new Error("Not inside a git repository. Run this command from your target project directory.");
|
|
42067
42058
|
}
|
|
42068
|
-
return
|
|
42059
|
+
return import_path16.default.resolve(result.stdout.trim());
|
|
42069
42060
|
}
|
|
42070
42061
|
|
|
42071
42062
|
// src/commands/status.ts
|
|
42072
42063
|
var import_prompts3 = __toESM(require_prompts3(), 1);
|
|
42073
42064
|
|
|
42074
42065
|
// src/core/manifest.ts
|
|
42075
|
-
var
|
|
42066
|
+
var import_path17 = require("path");
|
|
42076
42067
|
|
|
42077
42068
|
// ../node_modules/zod/v4/classic/external.js
|
|
42078
42069
|
var external_exports = {};
|
|
@@ -55881,17 +55872,17 @@ var ManifestSchema = external_exports.object({
|
|
|
55881
55872
|
// src/core/manifest.ts
|
|
55882
55873
|
var MANIFEST_FILE = ".jaggers-sync-manifest.json";
|
|
55883
55874
|
function getManifestPath(projectDir) {
|
|
55884
|
-
return (0,
|
|
55875
|
+
return (0, import_path17.join)(projectDir, MANIFEST_FILE);
|
|
55885
55876
|
}
|
|
55886
55877
|
|
|
55887
55878
|
// src/commands/status.ts
|
|
55888
|
-
var
|
|
55889
|
-
var
|
|
55879
|
+
var import_fs_extra17 = __toESM(require_lib2(), 1);
|
|
55880
|
+
var import_path18 = __toESM(require("path"), 1);
|
|
55890
55881
|
function formatTargetLabel2(target) {
|
|
55891
55882
|
const normalized = target.replace(/\\/g, "/").toLowerCase();
|
|
55892
55883
|
if (normalized.endsWith("/.agents/skills") || normalized.includes("/.agents/skills/")) return "~/.agents/skills";
|
|
55893
55884
|
if (normalized.endsWith("/.claude") || normalized.includes("/.claude/")) return "~/.claude";
|
|
55894
|
-
return
|
|
55885
|
+
return import_path18.default.basename(target);
|
|
55895
55886
|
}
|
|
55896
55887
|
function formatRelativeTime(timestamp) {
|
|
55897
55888
|
const now = Date.now();
|
|
@@ -55911,7 +55902,7 @@ function createStatusCommand() {
|
|
|
55911
55902
|
const candidates = getCandidatePaths();
|
|
55912
55903
|
const targets = [];
|
|
55913
55904
|
for (const c of candidates) {
|
|
55914
|
-
if (await
|
|
55905
|
+
if (await import_fs_extra17.default.pathExists(c.path)) targets.push(c.path);
|
|
55915
55906
|
}
|
|
55916
55907
|
if (targets.length === 0) {
|
|
55917
55908
|
console.log(kleur_default.yellow("\n No agent environments found (~/.claude, ~/.agents/skills)\n"));
|
|
@@ -55922,8 +55913,8 @@ function createStatusCommand() {
|
|
|
55922
55913
|
const manifestPath = getManifestPath(target);
|
|
55923
55914
|
let lastSync = null;
|
|
55924
55915
|
try {
|
|
55925
|
-
if (await
|
|
55926
|
-
const manifest = await
|
|
55916
|
+
if (await import_fs_extra17.default.pathExists(manifestPath)) {
|
|
55917
|
+
const manifest = await import_fs_extra17.default.readJson(manifestPath);
|
|
55927
55918
|
if (manifest.lastSync) lastSync = manifest.lastSync;
|
|
55928
55919
|
}
|
|
55929
55920
|
} catch {
|
|
@@ -56015,127 +56006,91 @@ function createResetCommand() {
|
|
|
56015
56006
|
}
|
|
56016
56007
|
|
|
56017
56008
|
// src/commands/help.ts
|
|
56018
|
-
|
|
56019
|
-
|
|
56020
|
-
var HOOK_CATALOG = [
|
|
56021
|
-
{ file: "using-xtrm-reminder.mjs", event: "SessionStart", desc: "Injects using-xtrm session operating manual into system prompt" },
|
|
56022
|
-
{ file: "gitnexus/gitnexus-hook.cjs", event: "PostToolUse", desc: "Adds GitNexus context for search and Serena tooling" },
|
|
56023
|
-
{ file: "quality-check.cjs", event: "PostToolUse", desc: "Runs JS/TS quality checks on mutating edits" },
|
|
56024
|
-
{ file: "quality-check.py", event: "PostToolUse", desc: "Runs Python quality checks on mutating edits" },
|
|
56025
|
-
{ file: "quality-check-env.mjs", event: "SessionStart", desc: "Warns if tsc/ruff/eslint are missing at session start" },
|
|
56026
|
-
{ file: "worktree-boundary.mjs", event: "PreToolUse", desc: "Blocks edits outside .xtrm/worktrees when in worktree session" },
|
|
56027
|
-
{ file: "statusline.mjs", event: "statusLine", desc: "Renders 2-line status: XTRM model branch + claim/open issues" },
|
|
56028
|
-
{ file: "beads-edit-gate.mjs", event: "PreToolUse", desc: "Blocks file edits if no beads issue is claimed", beads: true },
|
|
56029
|
-
{ file: "beads-commit-gate.mjs", event: "PreToolUse", desc: "Blocks commits when no beads issue is in progress", beads: true },
|
|
56030
|
-
{ file: "beads-stop-gate.mjs", event: "Stop", desc: "Blocks stop when there is an unclosed in_progress claim", beads: true },
|
|
56031
|
-
{ file: "beads-memory-gate.mjs", event: "Stop", desc: "Prompts memory save when claim was closed this session", beads: true },
|
|
56032
|
-
{ file: "beads-compact-save.mjs", event: "PreCompact", desc: "Saves claim state across /compact", beads: true },
|
|
56033
|
-
{ file: "beads-compact-restore.mjs", event: "SessionStart", desc: "Restores claim state after /compact", beads: true },
|
|
56034
|
-
{ file: "beads-claim-sync.mjs", event: "PostToolUse", desc: "Notifies on bd update --claim; auto-commits on bd close", sessionFlow: true }
|
|
56035
|
-
];
|
|
56036
|
-
async function readSkillsFromDir(dir) {
|
|
56037
|
-
if (!await import_fs_extra17.default.pathExists(dir)) return [];
|
|
56038
|
-
const entries = await import_fs_extra17.default.readdir(dir);
|
|
56039
|
-
const skills = [];
|
|
56040
|
-
for (const name of entries.sort()) {
|
|
56041
|
-
const skillMd = import_path18.default.join(dir, name, "SKILL.md");
|
|
56042
|
-
if (!await import_fs_extra17.default.pathExists(skillMd)) continue;
|
|
56043
|
-
const content = await import_fs_extra17.default.readFile(skillMd, "utf8");
|
|
56044
|
-
const m = content.match(/^description:\s*(.+)$/m);
|
|
56045
|
-
skills.push({ name, desc: m ? m[1].replace(/^["']|["']$/g, "").trim() : "" });
|
|
56046
|
-
}
|
|
56047
|
-
return skills;
|
|
56048
|
-
}
|
|
56049
|
-
function resolvePkgRootFallback() {
|
|
56050
|
-
const candidates = [
|
|
56051
|
-
import_path18.default.resolve(__dirname, "../.."),
|
|
56052
|
-
import_path18.default.resolve(__dirname, "../../..")
|
|
56053
|
-
];
|
|
56054
|
-
const match = candidates.find(
|
|
56055
|
-
(candidate) => import_fs_extra17.default.existsSync(import_path18.default.join(candidate, "skills")) || import_fs_extra17.default.existsSync(import_path18.default.join(candidate, "project-skills"))
|
|
56056
|
-
);
|
|
56057
|
-
return match || null;
|
|
56058
|
-
}
|
|
56059
|
-
function col(s, width) {
|
|
56060
|
-
return s.length >= width ? s.slice(0, width - 1) + "\u2026" : s.padEnd(width);
|
|
56009
|
+
function section(title, lines) {
|
|
56010
|
+
return [title, ...lines, ""].join("\n");
|
|
56061
56011
|
}
|
|
56062
56012
|
function createHelpCommand() {
|
|
56063
|
-
return new Command("help").description("Show help
|
|
56064
|
-
|
|
56065
|
-
|
|
56066
|
-
|
|
56067
|
-
|
|
56068
|
-
|
|
56069
|
-
|
|
56070
|
-
|
|
56071
|
-
|
|
56072
|
-
|
|
56073
|
-
|
|
56074
|
-
|
|
56075
|
-
|
|
56076
|
-
|
|
56077
|
-
|
|
56078
|
-
|
|
56079
|
-
|
|
56080
|
-
""
|
|
56081
|
-
|
|
56082
|
-
|
|
56083
|
-
|
|
56084
|
-
"",
|
|
56085
|
-
|
|
56086
|
-
].join("\n");
|
|
56087
|
-
const general = HOOK_CATALOG.filter((h) => !h.beads && !h.sessionFlow);
|
|
56088
|
-
const beads = HOOK_CATALOG.filter((h) => h.beads);
|
|
56089
|
-
const sessionFlow = HOOK_CATALOG.filter((h) => h.sessionFlow);
|
|
56090
|
-
const hookRows = (hooks) => hooks.map(
|
|
56091
|
-
(h) => ` ${kleur_default.white(col(h.file, 34))}${kleur_default.yellow(col(h.event, 20))}${kleur_default.dim(h.desc)}`
|
|
56092
|
-
).join("\n");
|
|
56093
|
-
const hooksSection = [
|
|
56094
|
-
section("GLOBAL HOOKS"),
|
|
56013
|
+
return new Command("help").description("Show rich CLI help in a plain text format").action(async () => {
|
|
56014
|
+
const blocks = [];
|
|
56015
|
+
blocks.push(section("XTRM CLI", [
|
|
56016
|
+
" xtrm and xt are equivalent commands.",
|
|
56017
|
+
" Use xt for short workflow commands (xt claude, xt pi, xt end)."
|
|
56018
|
+
]));
|
|
56019
|
+
blocks.push(section("USAGE", [
|
|
56020
|
+
" xtrm <command> [subcommand] [options]",
|
|
56021
|
+
" xt <command> [subcommand] [options]"
|
|
56022
|
+
]));
|
|
56023
|
+
blocks.push(section("CORE WORKFLOW", [
|
|
56024
|
+
" 1) Start a runtime session in a worktree:",
|
|
56025
|
+
" xt claude [name] or xt pi [name]",
|
|
56026
|
+
" 2) Do your work in that worktree/branch.",
|
|
56027
|
+
" 3) Finish with:",
|
|
56028
|
+
" xt end",
|
|
56029
|
+
" 4) Manage old worktrees when needed:",
|
|
56030
|
+
" xt worktree list | xt worktree clean"
|
|
56031
|
+
]));
|
|
56032
|
+
blocks.push(section("PRIMARY COMMANDS", [
|
|
56033
|
+
" xtrm install [target-selector] [options]",
|
|
56034
|
+
" Install/sync tools, hooks, skills, and MCP wiring.",
|
|
56035
|
+
" Options: --dry-run, --yes/-y, --prune, --backport",
|
|
56095
56036
|
"",
|
|
56096
|
-
|
|
56037
|
+
" xtrm status [--json]",
|
|
56038
|
+
" Show pending changes for detected environments.",
|
|
56097
56039
|
"",
|
|
56098
|
-
|
|
56040
|
+
" xtrm clean [options]",
|
|
56041
|
+
" Remove orphaned hooks/skills and stale hook wiring entries.",
|
|
56042
|
+
" Options: --dry-run, --hooks-only, --skills-only, --yes/-y",
|
|
56099
56043
|
"",
|
|
56100
|
-
|
|
56101
|
-
|
|
56044
|
+
" xtrm init",
|
|
56045
|
+
" Initialize project-level workflow setup.",
|
|
56102
56046
|
"",
|
|
56103
|
-
|
|
56104
|
-
|
|
56105
|
-
].join("\n");
|
|
56106
|
-
const skillRows = skills.map((s) => {
|
|
56107
|
-
const desc = s.desc.length > 46 ? s.desc.slice(0, 45) + "\u2026" : s.desc;
|
|
56108
|
-
return ` ${kleur_default.white(col(s.name, 30))}${kleur_default.dim(desc)}`;
|
|
56109
|
-
}).join("\n");
|
|
56110
|
-
const skillsSection = [
|
|
56111
|
-
section(`SKILLS ${kleur_default.dim("(" + skills.length + " available)")}`),
|
|
56047
|
+
" xtrm docs show [filter] [--raw] [--json]",
|
|
56048
|
+
" Show frontmatter for README/CHANGELOG/docs/*.md.",
|
|
56112
56049
|
"",
|
|
56113
|
-
|
|
56114
|
-
|
|
56115
|
-
|
|
56116
|
-
section("OTHER COMMANDS"),
|
|
56050
|
+
" xtrm debug [options]",
|
|
56051
|
+
" Stream xtrm event log (tool calls, gates, session/bd lifecycle).",
|
|
56052
|
+
" Options: --follow, --all, --session <id>, --type <domain>, --json",
|
|
56117
56053
|
"",
|
|
56118
|
-
|
|
56119
|
-
|
|
56120
|
-
` ${kleur_default.bold("xtrm init")} ${kleur_default.dim("Initialize project data (beads, gitnexus, service-registry)")}`,
|
|
56121
|
-
` ${kleur_default.bold("xtrm docs show")} ${kleur_default.dim("Display frontmatter for README, CHANGELOG, docs/*.md")}`,
|
|
56122
|
-
` ${kleur_default.bold("xtrm debug")} ${kleur_default.dim("Watch xtrm hook and bd lifecycle events in real time")}`,
|
|
56123
|
-
` ${kleur_default.bold("xtrm reset")} ${kleur_default.dim("Clear saved preferences and start fresh")}`,
|
|
56124
|
-
` ${kleur_default.bold("xtrm end")} ${kleur_default.dim("Close worktree session: rebase, push, PR, link issues, cleanup")}`,
|
|
56125
|
-
` ${kleur_default.bold("xtrm worktree list")} ${kleur_default.dim("List all active xt/* worktrees with status")}`,
|
|
56126
|
-
` ${kleur_default.bold("xtrm worktree clean")} ${kleur_default.dim("Remove worktrees whose branch has been merged into main")}`,
|
|
56127
|
-
` ${kleur_default.bold("xtrm help")} ${kleur_default.dim("Show this overview")}`
|
|
56128
|
-
].join("\n");
|
|
56129
|
-
const resourcesSection = [
|
|
56130
|
-
section("RESOURCES"),
|
|
56054
|
+
" xtrm reset",
|
|
56055
|
+
" Clear saved CLI preferences.",
|
|
56131
56056
|
"",
|
|
56132
|
-
|
|
56133
|
-
|
|
56057
|
+
" xtrm help",
|
|
56058
|
+
" Show this help page."
|
|
56059
|
+
]));
|
|
56060
|
+
blocks.push(section("RUNTIME COMMANDS", [
|
|
56061
|
+
" xt claude [name]",
|
|
56062
|
+
" Launch Claude in a sandboxed xt/<name> worktree.",
|
|
56063
|
+
" xt claude install [--dry-run]",
|
|
56064
|
+
" Install/refresh xtrm Claude plugin + official plugins.",
|
|
56065
|
+
" xt claude status | xt claude doctor | xt claude reload",
|
|
56134
56066
|
"",
|
|
56135
|
-
|
|
56136
|
-
""
|
|
56137
|
-
|
|
56138
|
-
|
|
56067
|
+
" xt pi [name]",
|
|
56068
|
+
" Launch Pi in a sandboxed xt/<name> worktree.",
|
|
56069
|
+
" xt pi install [--dry-run]",
|
|
56070
|
+
" Non-interactive extension sync + package install.",
|
|
56071
|
+
" xt pi setup",
|
|
56072
|
+
" Interactive first-time setup.",
|
|
56073
|
+
" xt pi status | xt pi doctor | xt pi reload"
|
|
56074
|
+
]));
|
|
56075
|
+
blocks.push(section("WORKTREE COMMANDS", [
|
|
56076
|
+
" xt worktree list",
|
|
56077
|
+
" List active xt/* worktrees and merge status.",
|
|
56078
|
+
" xt worktree clean [--yes/-y]",
|
|
56079
|
+
" Remove worktrees already merged into main.",
|
|
56080
|
+
" xt worktree remove <name> [--yes/-y]",
|
|
56081
|
+
" Remove a specific xt worktree by name or path."
|
|
56082
|
+
]));
|
|
56083
|
+
blocks.push(section("SESSION CLOSE", [
|
|
56084
|
+
" xt end [options]",
|
|
56085
|
+
" Rebase to origin/main, push, open PR, link issues, and optionally clean worktree.",
|
|
56086
|
+
" Options: --draft, --keep, --yes/-y"
|
|
56087
|
+
]));
|
|
56088
|
+
blocks.push(section("NOTES", [
|
|
56089
|
+
" - Banner is shown only for xtrm install.",
|
|
56090
|
+
" - For command-level details, run: xtrm <command> --help",
|
|
56091
|
+
" - For subcommand details, run: xtrm <command> <subcommand> --help"
|
|
56092
|
+
]));
|
|
56093
|
+
process.stdout.write(blocks.join("\n"));
|
|
56139
56094
|
});
|
|
56140
56095
|
}
|
|
56141
56096
|
|
|
@@ -56145,7 +56100,6 @@ var import_path19 = __toESM(require("path"), 1);
|
|
|
56145
56100
|
var import_os6 = require("os");
|
|
56146
56101
|
var CANONICAL_HOOKS = /* @__PURE__ */ new Set([
|
|
56147
56102
|
"using-xtrm-reminder.mjs",
|
|
56148
|
-
"serena-workflow-reminder.py",
|
|
56149
56103
|
"beads-gate-core.mjs",
|
|
56150
56104
|
"beads-gate-utils.mjs",
|
|
56151
56105
|
"beads-gate-messages.mjs",
|
|
@@ -56156,13 +56110,16 @@ var CANONICAL_HOOKS = /* @__PURE__ */ new Set([
|
|
|
56156
56110
|
"beads-claim-sync.mjs",
|
|
56157
56111
|
"beads-compact-save.mjs",
|
|
56158
56112
|
"beads-compact-restore.mjs",
|
|
56113
|
+
"worktree-boundary.mjs",
|
|
56159
56114
|
"statusline.mjs",
|
|
56160
56115
|
"quality-check.cjs",
|
|
56161
56116
|
"quality-check-env.mjs",
|
|
56162
56117
|
"quality-check.py",
|
|
56118
|
+
"xtrm-logger.mjs",
|
|
56119
|
+
"xtrm-tool-logger.mjs",
|
|
56120
|
+
"xtrm-session-logger.mjs",
|
|
56163
56121
|
"gitnexus",
|
|
56164
56122
|
// directory
|
|
56165
|
-
"statusline-starship.sh",
|
|
56166
56123
|
"README.md"
|
|
56167
56124
|
]);
|
|
56168
56125
|
var CANONICAL_SKILLS = /* @__PURE__ */ new Set([
|
|
@@ -57321,9 +57278,9 @@ process.on("unhandledRejection", (reason) => {
|
|
|
57321
57278
|
process.exit(1);
|
|
57322
57279
|
});
|
|
57323
57280
|
var isHelpOrVersion = process.argv.some((a) => a === "--help" || a === "-h" || a === "--version" || a === "-V");
|
|
57324
|
-
var
|
|
57281
|
+
var isInstallCommand = (process.argv[2] ?? "") === "install";
|
|
57325
57282
|
(async () => {
|
|
57326
|
-
if (!isHelpOrVersion &&
|
|
57283
|
+
if (!isHelpOrVersion && isInstallCommand) {
|
|
57327
57284
|
await printBanner(version2);
|
|
57328
57285
|
}
|
|
57329
57286
|
program2.parseAsync(process.argv);
|