@atlashub/smartstack-cli 3.1.0 → 3.3.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/.documentation/prd-json-v2.0.0.md +396 -0
- package/.documentation/testing-ba-e2e.md +462 -0
- package/dist/index.js +605 -25
- package/dist/index.js.map +1 -1
- package/package.json +6 -2
- package/templates/agents/ba-reader.md +1 -1
- package/templates/agents/ba-writer.md +8 -1
- package/templates/skills/business-analyse/SKILL.md +46 -31
- package/templates/skills/business-analyse/_architecture.md +123 -0
- package/templates/skills/business-analyse/_elicitation.md +206 -0
- package/templates/skills/business-analyse/_module-loop.md +56 -0
- package/templates/skills/business-analyse/_shared.md +75 -531
- package/templates/skills/business-analyse/_suggestions.md +34 -0
- package/templates/skills/business-analyse/html/ba-interactive.html +146 -57
- package/templates/skills/business-analyse/questionnaire/06-security.md +1 -1
- package/templates/skills/business-analyse/questionnaire.md +22 -17
- package/templates/skills/business-analyse/react/components.md +1 -1
- package/templates/skills/business-analyse/react/schema.md +1 -1
- package/templates/skills/business-analyse/references/html-data-mapping.md +294 -0
- package/templates/skills/business-analyse/schemas/feature-schema.json +1 -1
- package/templates/skills/business-analyse/schemas/sections/analysis-schema.json +1 -1
- package/templates/skills/business-analyse/schemas/sections/handoff-schema.json +1 -1
- package/templates/skills/business-analyse/schemas/sections/specification-schema.json +1 -1
- package/templates/skills/business-analyse/steps/step-00-init.md +85 -59
- package/templates/skills/business-analyse/steps/step-01-cadrage.md +2 -0
- package/templates/skills/business-analyse/steps/step-02-decomposition.md +5 -3
- package/templates/skills/business-analyse/steps/{step-03-specify.md → step-03a-specify.md} +16 -606
- package/templates/skills/business-analyse/steps/step-03b-compile.md +670 -0
- package/templates/skills/business-analyse/steps/step-04-consolidation.md +7 -5
- package/templates/skills/business-analyse/steps/step-05a-handoff.md +727 -0
- package/templates/skills/business-analyse/steps/step-05b-deploy.md +479 -0
- package/templates/skills/business-analyse/steps/step-06-extract.md +134 -4
- package/templates/skills/business-analyse/templates/tpl-frd.md +1 -1
- package/templates/skills/business-analyse/templates/tpl-launch-displays.md +161 -0
- package/templates/skills/business-analyse/templates/tpl-progress.md +171 -0
- package/templates/skills/ralph-loop/SKILL.md +138 -20
- package/templates/skills/ralph-loop/steps/step-01-task.md +75 -18
- package/templates/skills/ralph-loop/steps/step-04-check.md +72 -5
- package/templates/skills/business-analyse/steps/step-05-handoff.md +0 -1414
package/dist/index.js
CHANGED
|
@@ -6573,7 +6573,7 @@ var require_jsonfile = __commonJS({
|
|
|
6573
6573
|
return obj;
|
|
6574
6574
|
}
|
|
6575
6575
|
var readFile2 = universalify.fromPromise(_readFile);
|
|
6576
|
-
function
|
|
6576
|
+
function readFileSync5(file, options = {}) {
|
|
6577
6577
|
if (typeof options === "string") {
|
|
6578
6578
|
options = { encoding: options };
|
|
6579
6579
|
}
|
|
@@ -6598,16 +6598,16 @@ var require_jsonfile = __commonJS({
|
|
|
6598
6598
|
await universalify.fromCallback(fs16.writeFile)(file, str, options);
|
|
6599
6599
|
}
|
|
6600
6600
|
var writeFile2 = universalify.fromPromise(_writeFile);
|
|
6601
|
-
function
|
|
6601
|
+
function writeFileSync3(file, obj, options = {}) {
|
|
6602
6602
|
const fs16 = options.fs || _fs;
|
|
6603
6603
|
const str = stringify2(obj, options);
|
|
6604
6604
|
return fs16.writeFileSync(file, str, options);
|
|
6605
6605
|
}
|
|
6606
6606
|
module2.exports = {
|
|
6607
6607
|
readFile: readFile2,
|
|
6608
|
-
readFileSync:
|
|
6608
|
+
readFileSync: readFileSync5,
|
|
6609
6609
|
writeFile: writeFile2,
|
|
6610
|
-
writeFileSync:
|
|
6610
|
+
writeFileSync: writeFileSync3
|
|
6611
6611
|
};
|
|
6612
6612
|
}
|
|
6613
6613
|
});
|
|
@@ -19200,7 +19200,7 @@ var require_buffer_list = __commonJS({
|
|
|
19200
19200
|
}
|
|
19201
19201
|
}, {
|
|
19202
19202
|
key: "join",
|
|
19203
|
-
value: function
|
|
19203
|
+
value: function join15(s) {
|
|
19204
19204
|
if (this.length === 0) return "";
|
|
19205
19205
|
var p = this.head;
|
|
19206
19206
|
var ret = "" + p.data;
|
|
@@ -33660,7 +33660,7 @@ var require_table = __commonJS({
|
|
|
33660
33660
|
var debug = require_debug();
|
|
33661
33661
|
var utils = require_utils4();
|
|
33662
33662
|
var tableLayout = require_layout_manager();
|
|
33663
|
-
var
|
|
33663
|
+
var Table7 = class extends Array {
|
|
33664
33664
|
constructor(opts) {
|
|
33665
33665
|
super();
|
|
33666
33666
|
const options = utils.mergeOptions(opts);
|
|
@@ -33735,7 +33735,7 @@ var require_table = __commonJS({
|
|
|
33735
33735
|
return str[0].length;
|
|
33736
33736
|
}
|
|
33737
33737
|
};
|
|
33738
|
-
|
|
33738
|
+
Table7.reset = () => debug.reset();
|
|
33739
33739
|
function doDraw(row, lineNum, result) {
|
|
33740
33740
|
let line = [];
|
|
33741
33741
|
row.forEach(function(cell) {
|
|
@@ -33744,7 +33744,7 @@ var require_table = __commonJS({
|
|
|
33744
33744
|
let str = line.join("");
|
|
33745
33745
|
if (str.length) result.push(str);
|
|
33746
33746
|
}
|
|
33747
|
-
module2.exports =
|
|
33747
|
+
module2.exports = Table7;
|
|
33748
33748
|
}
|
|
33749
33749
|
});
|
|
33750
33750
|
|
|
@@ -39525,9 +39525,9 @@ var require_table2 = __commonJS({
|
|
|
39525
39525
|
var objectHasProperty = require_utils6().objectHasProperty;
|
|
39526
39526
|
var MAX = 65535;
|
|
39527
39527
|
var JSON_COLUMN_ID = "JSON_F52E2B61-18A1-11d1-B105-00805F49916B";
|
|
39528
|
-
function
|
|
39528
|
+
function Table7(name) {
|
|
39529
39529
|
if (name) {
|
|
39530
|
-
const parsed =
|
|
39530
|
+
const parsed = Table7.parseName(name);
|
|
39531
39531
|
this.name = parsed.name;
|
|
39532
39532
|
this.schema = parsed.schema;
|
|
39533
39533
|
this.database = parsed.database;
|
|
@@ -39573,7 +39573,7 @@ var require_table2 = __commonJS({
|
|
|
39573
39573
|
}
|
|
39574
39574
|
);
|
|
39575
39575
|
}
|
|
39576
|
-
|
|
39576
|
+
Table7.prototype._makeBulk = function _makeBulk() {
|
|
39577
39577
|
for (let i = 0; i < this.columns.length; i++) {
|
|
39578
39578
|
const col = this.columns[i];
|
|
39579
39579
|
switch (col.type) {
|
|
@@ -39605,7 +39605,7 @@ var require_table2 = __commonJS({
|
|
|
39605
39605
|
}
|
|
39606
39606
|
return this;
|
|
39607
39607
|
};
|
|
39608
|
-
|
|
39608
|
+
Table7.prototype.declare = function declare() {
|
|
39609
39609
|
const pkey = this.columns.filter((col) => col.primary === true).map((col) => `[${col.name}]`);
|
|
39610
39610
|
const cols = this.columns.map((col) => {
|
|
39611
39611
|
const def = [`[${col.name}] ${declareType(col.type, col)}`];
|
|
@@ -39622,7 +39622,7 @@ var require_table2 = __commonJS({
|
|
|
39622
39622
|
const constraint = pkey.length > 1 ? `, constraint [PK_${this.temporary ? this.name.substr(1) : this.name}] primary key (${pkey.join(", ")})` : "";
|
|
39623
39623
|
return `create table ${this.path} (${cols.join(", ")}${constraint})`;
|
|
39624
39624
|
};
|
|
39625
|
-
|
|
39625
|
+
Table7.fromRecordset = function fromRecordset(recordset, name) {
|
|
39626
39626
|
const t = new this(name);
|
|
39627
39627
|
for (const colName in recordset.columns) {
|
|
39628
39628
|
if (objectHasProperty(recordset.columns, colName)) {
|
|
@@ -39650,7 +39650,7 @@ var require_table2 = __commonJS({
|
|
|
39650
39650
|
}
|
|
39651
39651
|
return t;
|
|
39652
39652
|
};
|
|
39653
|
-
|
|
39653
|
+
Table7.parseName = function parseName(name) {
|
|
39654
39654
|
const length = name.length;
|
|
39655
39655
|
let cursor = -1;
|
|
39656
39656
|
let buffer = "";
|
|
@@ -39707,7 +39707,7 @@ var require_table2 = __commonJS({
|
|
|
39707
39707
|
throw new Error("Invalid table name.");
|
|
39708
39708
|
}
|
|
39709
39709
|
};
|
|
39710
|
-
module2.exports =
|
|
39710
|
+
module2.exports = Table7;
|
|
39711
39711
|
}
|
|
39712
39712
|
});
|
|
39713
39713
|
|
|
@@ -39716,7 +39716,7 @@ var require_shared = __commonJS({
|
|
|
39716
39716
|
"node_modules/mssql/lib/shared.js"(exports2, module2) {
|
|
39717
39717
|
"use strict";
|
|
39718
39718
|
var TYPES = require_datatypes().TYPES;
|
|
39719
|
-
var
|
|
39719
|
+
var Table7 = require_table2();
|
|
39720
39720
|
var PromiseLibrary = Promise;
|
|
39721
39721
|
var driver = {};
|
|
39722
39722
|
var map8 = [];
|
|
@@ -39739,7 +39739,7 @@ var require_shared = __commonJS({
|
|
|
39739
39739
|
map8.register(Boolean, TYPES.Bit);
|
|
39740
39740
|
map8.register(Date, TYPES.DateTime);
|
|
39741
39741
|
map8.register(Buffer, TYPES.VarBinary);
|
|
39742
|
-
map8.register(
|
|
39742
|
+
map8.register(Table7, TYPES.TVP);
|
|
39743
39743
|
var getTypeByValue = function(value) {
|
|
39744
39744
|
if (value === null || value === void 0) {
|
|
39745
39745
|
return TYPES.NVarChar;
|
|
@@ -41872,7 +41872,7 @@ var require_base = __commonJS({
|
|
|
41872
41872
|
var Transaction = require_transaction();
|
|
41873
41873
|
var { ConnectionError, TransactionError, RequestError, PreparedStatementError, MSSQLError } = require_error2();
|
|
41874
41874
|
var shared = require_shared();
|
|
41875
|
-
var
|
|
41875
|
+
var Table7 = require_table2();
|
|
41876
41876
|
var ISOLATION_LEVEL = require_isolationlevel();
|
|
41877
41877
|
var { TYPES } = require_datatypes();
|
|
41878
41878
|
var { connect, close, on, off, removeListener, query, batch } = require_global_connection();
|
|
@@ -41893,7 +41893,7 @@ var require_base = __commonJS({
|
|
|
41893
41893
|
RequestError,
|
|
41894
41894
|
PreparedStatementError,
|
|
41895
41895
|
MSSQLError,
|
|
41896
|
-
Table:
|
|
41896
|
+
Table: Table7,
|
|
41897
41897
|
ISOLATION_LEVEL,
|
|
41898
41898
|
TYPES,
|
|
41899
41899
|
MAX: 65535,
|
|
@@ -108014,7 +108014,7 @@ var require_request3 = __commonJS({
|
|
|
108014
108014
|
var RequestError = require_request_error();
|
|
108015
108015
|
var { IDS, objectHasProperty } = require_utils6();
|
|
108016
108016
|
var { TYPES, DECLARATIONS, declare, cast } = require_datatypes();
|
|
108017
|
-
var
|
|
108017
|
+
var Table7 = require_table2();
|
|
108018
108018
|
var { PARSERS: UDT } = require_udt2();
|
|
108019
108019
|
var { valueHandler } = require_shared();
|
|
108020
108020
|
var JSON_COLUMN_ID = "JSON_F52E2B61-18A1-11d1-B105-00805F49916B";
|
|
@@ -108239,7 +108239,7 @@ var require_request3 = __commonJS({
|
|
|
108239
108239
|
}
|
|
108240
108240
|
};
|
|
108241
108241
|
var parameterCorrection = function(value) {
|
|
108242
|
-
if (value instanceof
|
|
108242
|
+
if (value instanceof Table7) {
|
|
108243
108243
|
const tvp = {
|
|
108244
108244
|
name: value.name,
|
|
108245
108245
|
schema: value.schema,
|
|
@@ -108553,7 +108553,7 @@ var require_request3 = __commonJS({
|
|
|
108553
108553
|
enumerable: false,
|
|
108554
108554
|
configurable: true,
|
|
108555
108555
|
value(name) {
|
|
108556
|
-
return
|
|
108556
|
+
return Table7.fromRecordset(this, name);
|
|
108557
108557
|
}
|
|
108558
108558
|
});
|
|
108559
108559
|
recordsets.push(recordset);
|
|
@@ -108865,7 +108865,7 @@ var require_request3 = __commonJS({
|
|
|
108865
108865
|
enumerable: false,
|
|
108866
108866
|
configurable: true,
|
|
108867
108867
|
value(name) {
|
|
108868
|
-
return
|
|
108868
|
+
return Table7.fromRecordset(this, name);
|
|
108869
108869
|
}
|
|
108870
108870
|
});
|
|
108871
108871
|
recordsets.push(recordset);
|
|
@@ -126871,10 +126871,589 @@ Processing module: ${source_default.bold(moduleName)}`));
|
|
|
126871
126871
|
}
|
|
126872
126872
|
});
|
|
126873
126873
|
|
|
126874
|
-
// src/
|
|
126874
|
+
// src/commands/tmux.ts
|
|
126875
|
+
var import_cli_table36 = __toESM(require_cli_table3());
|
|
126876
|
+
|
|
126877
|
+
// src/lib/wsl-provisioner.ts
|
|
126878
|
+
var import_child_process10 = require("child_process");
|
|
126875
126879
|
var import_fs5 = require("fs");
|
|
126876
126880
|
var import_path12 = require("path");
|
|
126877
|
-
|
|
126881
|
+
function wslExec(command, timeout = 1e4) {
|
|
126882
|
+
try {
|
|
126883
|
+
const output = (0, import_child_process10.execSync)(`wsl -e bash -c "${command.replace(/"/g, '\\"')}"`, {
|
|
126884
|
+
encoding: "utf-8",
|
|
126885
|
+
timeout,
|
|
126886
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
126887
|
+
});
|
|
126888
|
+
return output.split("\n").filter((l) => !l.includes("WSL") || !l.includes("ERROR")).join("\n").trim();
|
|
126889
|
+
} catch {
|
|
126890
|
+
return null;
|
|
126891
|
+
}
|
|
126892
|
+
}
|
|
126893
|
+
function wslInstall(command, timeout = 12e4) {
|
|
126894
|
+
try {
|
|
126895
|
+
const output = (0, import_child_process10.execSync)(`wsl -e bash -c "${command.replace(/"/g, '\\"')}"`, {
|
|
126896
|
+
encoding: "utf-8",
|
|
126897
|
+
timeout,
|
|
126898
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
126899
|
+
});
|
|
126900
|
+
return output.trim();
|
|
126901
|
+
} catch (err) {
|
|
126902
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
126903
|
+
logger.debug(`wslInstall error: ${msg}`);
|
|
126904
|
+
return null;
|
|
126905
|
+
}
|
|
126906
|
+
}
|
|
126907
|
+
function parseWslList(raw) {
|
|
126908
|
+
return raw.replace(/\0/g, "").split("\n").map((l) => l.trim()).filter((l) => l.length > 0);
|
|
126909
|
+
}
|
|
126910
|
+
function checkWsl() {
|
|
126911
|
+
try {
|
|
126912
|
+
const statusRaw = (0, import_child_process10.execSync)("wsl --status", {
|
|
126913
|
+
encoding: "utf-8",
|
|
126914
|
+
timeout: 1e4,
|
|
126915
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
126916
|
+
}).replace(/\0/g, "");
|
|
126917
|
+
let version2 = null;
|
|
126918
|
+
const versionMatch = statusRaw.match(/(\d)\s*$/m) || statusRaw.match(/version.*?:\s*(\d)/i);
|
|
126919
|
+
if (versionMatch) version2 = parseInt(versionMatch[1], 10);
|
|
126920
|
+
let defaultDistro = null;
|
|
126921
|
+
try {
|
|
126922
|
+
const listRaw = (0, import_child_process10.execSync)("wsl --list --verbose", {
|
|
126923
|
+
encoding: "utf-8",
|
|
126924
|
+
timeout: 1e4,
|
|
126925
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
126926
|
+
});
|
|
126927
|
+
const lines = parseWslList(listRaw);
|
|
126928
|
+
for (const line of lines) {
|
|
126929
|
+
if (line.startsWith("*")) {
|
|
126930
|
+
const parts = line.substring(1).trim().split(/\s+/);
|
|
126931
|
+
defaultDistro = parts[0] || null;
|
|
126932
|
+
if (!version2 && parts.length >= 3) {
|
|
126933
|
+
version2 = parseInt(parts[parts.length - 1], 10);
|
|
126934
|
+
}
|
|
126935
|
+
break;
|
|
126936
|
+
}
|
|
126937
|
+
}
|
|
126938
|
+
} catch {
|
|
126939
|
+
}
|
|
126940
|
+
return { installed: true, version: version2 || 2, defaultDistro };
|
|
126941
|
+
} catch {
|
|
126942
|
+
return { installed: false, version: null, defaultDistro: null };
|
|
126943
|
+
}
|
|
126944
|
+
}
|
|
126945
|
+
function checkGitInWsl() {
|
|
126946
|
+
const out = wslExec("git --version 2>/dev/null");
|
|
126947
|
+
if (!out) return { installed: false, version: null };
|
|
126948
|
+
const match2 = out.match(/(\d+\.\d+\.\d+)/);
|
|
126949
|
+
return { installed: true, version: match2 ? match2[1] : out };
|
|
126950
|
+
}
|
|
126951
|
+
function checkTmuxInWsl() {
|
|
126952
|
+
const out = wslExec("tmux -V 2>/dev/null");
|
|
126953
|
+
if (!out) return { installed: false, version: null };
|
|
126954
|
+
const match2 = out.match(/(\d+\.\d+\w?)/);
|
|
126955
|
+
return { installed: true, version: match2 ? match2[1] : out };
|
|
126956
|
+
}
|
|
126957
|
+
function checkNvmInWsl() {
|
|
126958
|
+
const out = wslExec("source ~/.nvm/nvm.sh 2>/dev/null && nvm --version 2>/dev/null");
|
|
126959
|
+
if (!out) return { installed: false, version: null };
|
|
126960
|
+
const match2 = out.match(/(\d+\.\d+\.\d+)/);
|
|
126961
|
+
return { installed: true, version: match2 ? match2[1] : out };
|
|
126962
|
+
}
|
|
126963
|
+
function checkNodeInWsl() {
|
|
126964
|
+
const out = wslExec("source ~/.nvm/nvm.sh 2>/dev/null; node --version 2>/dev/null");
|
|
126965
|
+
if (!out) return { installed: false, version: null };
|
|
126966
|
+
const match2 = out.match(/(v?\d+\.\d+\.\d+)/);
|
|
126967
|
+
return { installed: true, version: match2 ? match2[1] : out };
|
|
126968
|
+
}
|
|
126969
|
+
function checkDotnetInWsl() {
|
|
126970
|
+
const out = wslExec("export PATH=\\$PATH:\\$HOME/.dotnet && dotnet --version 2>/dev/null");
|
|
126971
|
+
if (!out) return { installed: false, version: null };
|
|
126972
|
+
const match2 = out.match(/(\d+\.\d+\.\d+)/);
|
|
126973
|
+
return { installed: true, version: match2 ? match2[1] : out };
|
|
126974
|
+
}
|
|
126975
|
+
function checkClaudeInWsl() {
|
|
126976
|
+
const out = wslExec("source ~/.nvm/nvm.sh 2>/dev/null; claude --version 2>/dev/null");
|
|
126977
|
+
if (!out) return { installed: false, version: null };
|
|
126978
|
+
const match2 = out.match(/(\d+\.\d+\.\d+)/);
|
|
126979
|
+
return { installed: true, version: match2 ? match2[1] : out };
|
|
126980
|
+
}
|
|
126981
|
+
async function installGitInWsl() {
|
|
126982
|
+
const status = checkGitInWsl();
|
|
126983
|
+
if (status.installed) return { success: true, version: status.version, skipped: true };
|
|
126984
|
+
const spinner = logger.spinner("Installing git...");
|
|
126985
|
+
const result = wslInstall("sudo apt-get update -qq && sudo apt-get install -y -qq git", 6e4);
|
|
126986
|
+
if (!result && result !== "") {
|
|
126987
|
+
spinner.fail("Failed to install git");
|
|
126988
|
+
return { success: false, error: "apt-get install git failed" };
|
|
126989
|
+
}
|
|
126990
|
+
const check = checkGitInWsl();
|
|
126991
|
+
if (check.installed) {
|
|
126992
|
+
spinner.succeed(`git ${check.version} installed`);
|
|
126993
|
+
return { success: true, version: check.version };
|
|
126994
|
+
}
|
|
126995
|
+
spinner.fail("git installation could not be verified");
|
|
126996
|
+
return { success: false, error: "Verification failed after install" };
|
|
126997
|
+
}
|
|
126998
|
+
async function installTmuxInWsl() {
|
|
126999
|
+
const status = checkTmuxInWsl();
|
|
127000
|
+
if (status.installed) return { success: true, version: status.version, skipped: true };
|
|
127001
|
+
const spinner = logger.spinner("Installing tmux...");
|
|
127002
|
+
const result = wslInstall("sudo apt-get update -qq && sudo apt-get install -y -qq tmux", 6e4);
|
|
127003
|
+
if (!result && result !== "") {
|
|
127004
|
+
spinner.fail("Failed to install tmux");
|
|
127005
|
+
return { success: false, error: "apt-get install tmux failed" };
|
|
127006
|
+
}
|
|
127007
|
+
const check = checkTmuxInWsl();
|
|
127008
|
+
if (check.installed) {
|
|
127009
|
+
spinner.succeed(`tmux ${check.version} installed`);
|
|
127010
|
+
return { success: true, version: check.version };
|
|
127011
|
+
}
|
|
127012
|
+
spinner.fail("tmux installation could not be verified");
|
|
127013
|
+
return { success: false, error: "Verification failed after install" };
|
|
127014
|
+
}
|
|
127015
|
+
async function installNvmInWsl() {
|
|
127016
|
+
const status = checkNvmInWsl();
|
|
127017
|
+
if (status.installed) return { success: true, version: status.version, skipped: true };
|
|
127018
|
+
const spinner = logger.spinner("Installing nvm...");
|
|
127019
|
+
const result = wslInstall(
|
|
127020
|
+
"curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash",
|
|
127021
|
+
6e4
|
|
127022
|
+
);
|
|
127023
|
+
if (result === null) {
|
|
127024
|
+
spinner.fail("Failed to install nvm");
|
|
127025
|
+
return { success: false, error: "nvm install script failed" };
|
|
127026
|
+
}
|
|
127027
|
+
const check = checkNvmInWsl();
|
|
127028
|
+
if (check.installed) {
|
|
127029
|
+
spinner.succeed(`nvm ${check.version} installed`);
|
|
127030
|
+
return { success: true, version: check.version };
|
|
127031
|
+
}
|
|
127032
|
+
spinner.fail("nvm installation could not be verified");
|
|
127033
|
+
return { success: false, error: "Verification failed after install" };
|
|
127034
|
+
}
|
|
127035
|
+
async function installNodeInWsl() {
|
|
127036
|
+
const status = checkNodeInWsl();
|
|
127037
|
+
if (status.installed) return { success: true, version: status.version, skipped: true };
|
|
127038
|
+
const nvmCheck = checkNvmInWsl();
|
|
127039
|
+
if (!nvmCheck.installed) {
|
|
127040
|
+
return { success: false, error: "nvm is not installed (required for Node.js)" };
|
|
127041
|
+
}
|
|
127042
|
+
const spinner = logger.spinner("Installing Node.js LTS...");
|
|
127043
|
+
const result = wslInstall(
|
|
127044
|
+
"source ~/.nvm/nvm.sh && nvm install --lts && nvm alias default lts/*",
|
|
127045
|
+
12e4
|
|
127046
|
+
);
|
|
127047
|
+
if (result === null) {
|
|
127048
|
+
spinner.fail("Failed to install Node.js");
|
|
127049
|
+
return { success: false, error: "nvm install --lts failed" };
|
|
127050
|
+
}
|
|
127051
|
+
const check = checkNodeInWsl();
|
|
127052
|
+
if (check.installed) {
|
|
127053
|
+
spinner.succeed(`Node.js ${check.version} installed`);
|
|
127054
|
+
return { success: true, version: check.version };
|
|
127055
|
+
}
|
|
127056
|
+
spinner.fail("Node.js installation could not be verified");
|
|
127057
|
+
return { success: false, error: "Verification failed after install" };
|
|
127058
|
+
}
|
|
127059
|
+
async function installDotnetInWsl() {
|
|
127060
|
+
const status = checkDotnetInWsl();
|
|
127061
|
+
if (status.installed) return { success: true, version: status.version, skipped: true };
|
|
127062
|
+
const spinner = logger.spinner("Installing .NET SDK 10...");
|
|
127063
|
+
const installCmd = [
|
|
127064
|
+
"wget -q https://dot.net/v1/dotnet-install.sh -O /tmp/dotnet-install.sh",
|
|
127065
|
+
"chmod +x /tmp/dotnet-install.sh",
|
|
127066
|
+
"/tmp/dotnet-install.sh --channel 10.0"
|
|
127067
|
+
].join(" && ");
|
|
127068
|
+
const result = wslInstall(installCmd, 18e4);
|
|
127069
|
+
if (result === null) {
|
|
127070
|
+
spinner.fail("Failed to install .NET SDK 10");
|
|
127071
|
+
return { success: false, error: "dotnet-install.sh failed" };
|
|
127072
|
+
}
|
|
127073
|
+
wslInstall(
|
|
127074
|
+
`grep -q "\\$HOME/.dotnet" ~/.bashrc || echo 'export PATH="$PATH:$HOME/.dotnet"' >> ~/.bashrc`,
|
|
127075
|
+
5e3
|
|
127076
|
+
);
|
|
127077
|
+
const check = checkDotnetInWsl();
|
|
127078
|
+
if (check.installed) {
|
|
127079
|
+
spinner.succeed(`.NET SDK ${check.version} installed`);
|
|
127080
|
+
return { success: true, version: check.version };
|
|
127081
|
+
}
|
|
127082
|
+
spinner.fail(".NET SDK installation could not be verified");
|
|
127083
|
+
return { success: false, error: "Verification failed after install" };
|
|
127084
|
+
}
|
|
127085
|
+
async function installClaudeInWsl() {
|
|
127086
|
+
const status = checkClaudeInWsl();
|
|
127087
|
+
if (status.installed) return { success: true, version: status.version, skipped: true };
|
|
127088
|
+
const nodeCheck = checkNodeInWsl();
|
|
127089
|
+
if (!nodeCheck.installed) {
|
|
127090
|
+
return { success: false, error: "Node.js is not installed (required for Claude Code)" };
|
|
127091
|
+
}
|
|
127092
|
+
const spinner = logger.spinner("Installing Claude Code...");
|
|
127093
|
+
const result = wslInstall(
|
|
127094
|
+
"source ~/.nvm/nvm.sh && npm install -g @anthropic-ai/claude-code",
|
|
127095
|
+
18e4
|
|
127096
|
+
);
|
|
127097
|
+
if (result === null) {
|
|
127098
|
+
spinner.fail("Failed to install Claude Code");
|
|
127099
|
+
return { success: false, error: "npm install -g @anthropic-ai/claude-code failed" };
|
|
127100
|
+
}
|
|
127101
|
+
const check = checkClaudeInWsl();
|
|
127102
|
+
if (check.installed) {
|
|
127103
|
+
spinner.succeed(`Claude Code ${check.version} installed`);
|
|
127104
|
+
return { success: true, version: check.version };
|
|
127105
|
+
}
|
|
127106
|
+
spinner.fail("Claude Code installation could not be verified");
|
|
127107
|
+
return { success: false, error: "Verification failed after install" };
|
|
127108
|
+
}
|
|
127109
|
+
var SMARTSTACK_PROFILE_NAME = "SmartStack Dev";
|
|
127110
|
+
var SMARTSTACK_PROFILE_GUID = "{17ce5bfe-17ed-5f3a-ab15-5cd5baafed5b}";
|
|
127111
|
+
function checkWindowsTerminal() {
|
|
127112
|
+
try {
|
|
127113
|
+
(0, import_child_process10.execSync)("where wt", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 5e3 });
|
|
127114
|
+
return { installed: true, version: "installed" };
|
|
127115
|
+
} catch {
|
|
127116
|
+
return { installed: false, version: null };
|
|
127117
|
+
}
|
|
127118
|
+
}
|
|
127119
|
+
async function installWindowsTerminal() {
|
|
127120
|
+
const status = checkWindowsTerminal();
|
|
127121
|
+
if (status.installed) return { success: true, version: "installed", skipped: true };
|
|
127122
|
+
const spinner = logger.spinner("Installing Windows Terminal via winget...");
|
|
127123
|
+
try {
|
|
127124
|
+
(0, import_child_process10.execSync)("winget install Microsoft.WindowsTerminal --accept-source-agreements --accept-package-agreements", {
|
|
127125
|
+
encoding: "utf-8",
|
|
127126
|
+
timeout: 12e4,
|
|
127127
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
127128
|
+
});
|
|
127129
|
+
} catch (err) {
|
|
127130
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
127131
|
+
if (msg.includes("already installed") || msg.includes("No applicable update")) {
|
|
127132
|
+
spinner.succeed("Windows Terminal already installed");
|
|
127133
|
+
return { success: true, version: "installed", skipped: true };
|
|
127134
|
+
}
|
|
127135
|
+
spinner.fail("Failed to install Windows Terminal");
|
|
127136
|
+
return { success: false, error: `winget install failed: ${msg.substring(0, 200)}` };
|
|
127137
|
+
}
|
|
127138
|
+
const check = checkWindowsTerminal();
|
|
127139
|
+
if (check.installed) {
|
|
127140
|
+
spinner.succeed("Windows Terminal installed");
|
|
127141
|
+
return { success: true, version: "installed" };
|
|
127142
|
+
}
|
|
127143
|
+
spinner.fail("Windows Terminal installation could not be verified");
|
|
127144
|
+
return { success: false, error: "Verification failed after install" };
|
|
127145
|
+
}
|
|
127146
|
+
function getWtSettingsPath() {
|
|
127147
|
+
const localAppData = process.env.LOCALAPPDATA;
|
|
127148
|
+
if (!localAppData) return null;
|
|
127149
|
+
const standardPath = (0, import_path12.join)(localAppData, "Packages", "Microsoft.WindowsTerminal_8wekyb3d8bbwe", "LocalState", "settings.json");
|
|
127150
|
+
if ((0, import_fs5.existsSync)(standardPath)) return standardPath;
|
|
127151
|
+
const previewPath = (0, import_path12.join)(localAppData, "Packages", "Microsoft.WindowsTerminalPreview_8wekyb3d8bbwe", "LocalState", "settings.json");
|
|
127152
|
+
if ((0, import_fs5.existsSync)(previewPath)) return previewPath;
|
|
127153
|
+
const unpackagedPath = (0, import_path12.join)(localAppData, "Microsoft", "Windows Terminal", "settings.json");
|
|
127154
|
+
if ((0, import_fs5.existsSync)(unpackagedPath)) return unpackagedPath;
|
|
127155
|
+
return null;
|
|
127156
|
+
}
|
|
127157
|
+
function configureWindowsTerminal() {
|
|
127158
|
+
const settingsPath = getWtSettingsPath();
|
|
127159
|
+
if (!settingsPath) {
|
|
127160
|
+
return { success: false, error: "Windows Terminal settings.json not found. Launch Windows Terminal once to generate it." };
|
|
127161
|
+
}
|
|
127162
|
+
try {
|
|
127163
|
+
const raw = (0, import_fs5.readFileSync)(settingsPath, "utf-8");
|
|
127164
|
+
const cleaned = raw.replace(/^\uFEFF/, "").replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "");
|
|
127165
|
+
const settings = JSON.parse(cleaned);
|
|
127166
|
+
if (!settings.profiles) settings.profiles = {};
|
|
127167
|
+
if (!settings.profiles.list) settings.profiles.list = [];
|
|
127168
|
+
const existing = settings.profiles.list.find(
|
|
127169
|
+
(p) => p.guid === SMARTSTACK_PROFILE_GUID || p.name === SMARTSTACK_PROFILE_NAME
|
|
127170
|
+
);
|
|
127171
|
+
if (existing) {
|
|
127172
|
+
return { success: true, profileExists: true };
|
|
127173
|
+
}
|
|
127174
|
+
const profile = {
|
|
127175
|
+
guid: SMARTSTACK_PROFILE_GUID,
|
|
127176
|
+
name: SMARTSTACK_PROFILE_NAME,
|
|
127177
|
+
commandline: 'wsl -e bash -lc "source ~/.nvm/nvm.sh 2>/dev/null; tmux new-session -A -s smartstack"',
|
|
127178
|
+
icon: "\u26A1",
|
|
127179
|
+
colorScheme: "One Half Dark",
|
|
127180
|
+
startingDirectory: "~"
|
|
127181
|
+
};
|
|
127182
|
+
settings.profiles.list.push(profile);
|
|
127183
|
+
const backupPath = settingsPath + ".bak";
|
|
127184
|
+
(0, import_fs5.writeFileSync)(backupPath, raw, "utf-8");
|
|
127185
|
+
(0, import_fs5.writeFileSync)(settingsPath, JSON.stringify(settings, null, 4), "utf-8");
|
|
127186
|
+
return { success: true };
|
|
127187
|
+
} catch (err) {
|
|
127188
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
127189
|
+
return { success: false, error: `Failed to update settings: ${msg}` };
|
|
127190
|
+
}
|
|
127191
|
+
}
|
|
127192
|
+
function launchWindowsTerminal() {
|
|
127193
|
+
try {
|
|
127194
|
+
(0, import_child_process10.spawn)("wt", ["-p", SMARTSTACK_PROFILE_NAME], {
|
|
127195
|
+
detached: true,
|
|
127196
|
+
stdio: "ignore"
|
|
127197
|
+
}).unref();
|
|
127198
|
+
return true;
|
|
127199
|
+
} catch {
|
|
127200
|
+
return false;
|
|
127201
|
+
}
|
|
127202
|
+
}
|
|
127203
|
+
|
|
127204
|
+
// src/commands/tmux.ts
|
|
127205
|
+
var tmuxCommand = new Command("tmux").description("WSL development environment setup (tmux, dotnet, claude, git)").action(() => {
|
|
127206
|
+
console.log(source_default.cyan(`
|
|
127207
|
+
\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557
|
|
127208
|
+
\u2551 ${source_default.bold("WSL Dev Environment")} - SmartStack \u2551
|
|
127209
|
+
\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
|
|
127210
|
+
`));
|
|
127211
|
+
console.log("Available commands:");
|
|
127212
|
+
console.log(` ${source_default.cyan("ss tmux install")} Set up complete WSL dev environment`);
|
|
127213
|
+
console.log(` ${source_default.cyan("ss tmux status")} Check WSL environment status`);
|
|
127214
|
+
console.log();
|
|
127215
|
+
console.log("Installs: Windows Terminal, git, tmux, nvm, Node.js, .NET 10, Claude Code");
|
|
127216
|
+
console.log("Then launches Windows Terminal with Claude Code in tmux.");
|
|
127217
|
+
console.log();
|
|
127218
|
+
});
|
|
127219
|
+
tmuxCommand.command("install").description("Install complete WSL dev environment and launch Claude Code").option("-f, --force", "Re-install even if already present").option("-v, --verbose", "Show detailed debug output").option("--no-launch", "Do not launch Windows Terminal after install").action(async (options) => {
|
|
127220
|
+
if (options.verbose) logger.setVerbose(true);
|
|
127221
|
+
logger.header("WSL Development Environment Setup");
|
|
127222
|
+
const totalSteps = 10;
|
|
127223
|
+
logger.step(1, totalSteps, "Windows Terminal...");
|
|
127224
|
+
const wtStatus = checkWindowsTerminal();
|
|
127225
|
+
if (wtStatus.installed && !options.force) {
|
|
127226
|
+
logger.success("Windows Terminal already installed");
|
|
127227
|
+
} else {
|
|
127228
|
+
const wtResult = await installWindowsTerminal();
|
|
127229
|
+
if (!wtResult.success) {
|
|
127230
|
+
logger.error(`Windows Terminal: ${wtResult.error}`);
|
|
127231
|
+
logger.info("You can install manually: winget install Microsoft.WindowsTerminal");
|
|
127232
|
+
}
|
|
127233
|
+
}
|
|
127234
|
+
console.log();
|
|
127235
|
+
logger.step(2, totalSteps, "Checking WSL installation...");
|
|
127236
|
+
const wslStatus = checkWsl();
|
|
127237
|
+
if (!wslStatus.installed) {
|
|
127238
|
+
logger.error("WSL is not installed on this system");
|
|
127239
|
+
logger.box([
|
|
127240
|
+
"WSL is required to continue.",
|
|
127241
|
+
"",
|
|
127242
|
+
"Install WSL from an admin terminal:",
|
|
127243
|
+
" wsl --install",
|
|
127244
|
+
"",
|
|
127245
|
+
"Then restart your computer and run ss tmux install again."
|
|
127246
|
+
], "error");
|
|
127247
|
+
process.exit(1);
|
|
127248
|
+
}
|
|
127249
|
+
logger.success(`WSL ${wslStatus.version} installed`);
|
|
127250
|
+
if (wslStatus.defaultDistro) {
|
|
127251
|
+
logger.info(`Default distro: ${wslStatus.defaultDistro}`);
|
|
127252
|
+
} else {
|
|
127253
|
+
logger.error("No Linux distribution found");
|
|
127254
|
+
logger.box([
|
|
127255
|
+
"A Linux distribution is required.",
|
|
127256
|
+
"",
|
|
127257
|
+
"Install Ubuntu:",
|
|
127258
|
+
" wsl --install -d Ubuntu"
|
|
127259
|
+
], "error");
|
|
127260
|
+
process.exit(1);
|
|
127261
|
+
}
|
|
127262
|
+
console.log();
|
|
127263
|
+
const tools = [
|
|
127264
|
+
{ name: "Git", step: 3, check: checkGitInWsl, install: installGitInWsl },
|
|
127265
|
+
{ name: "tmux", step: 4, check: checkTmuxInWsl, install: installTmuxInWsl },
|
|
127266
|
+
{ name: "nvm", step: 5, check: checkNvmInWsl, install: installNvmInWsl },
|
|
127267
|
+
{ name: "Node.js", step: 6, check: checkNodeInWsl, install: installNodeInWsl },
|
|
127268
|
+
{ name: ".NET SDK 10", step: 7, check: checkDotnetInWsl, install: installDotnetInWsl },
|
|
127269
|
+
{ name: "Claude Code", step: 8, check: checkClaudeInWsl, install: installClaudeInWsl }
|
|
127270
|
+
];
|
|
127271
|
+
let allSuccess = true;
|
|
127272
|
+
const results = [];
|
|
127273
|
+
for (const tool of tools) {
|
|
127274
|
+
logger.step(tool.step, totalSteps, `${tool.name}...`);
|
|
127275
|
+
if (!options.force) {
|
|
127276
|
+
const status = tool.check();
|
|
127277
|
+
if (status.installed) {
|
|
127278
|
+
logger.success(`${tool.name} already installed (${status.version})`);
|
|
127279
|
+
results.push({ name: tool.name, status: "skipped", version: status.version });
|
|
127280
|
+
console.log();
|
|
127281
|
+
continue;
|
|
127282
|
+
}
|
|
127283
|
+
}
|
|
127284
|
+
const result = await tool.install();
|
|
127285
|
+
if (result.success) {
|
|
127286
|
+
if (result.skipped) {
|
|
127287
|
+
logger.success(`${tool.name} already installed (${result.version})`);
|
|
127288
|
+
results.push({ name: tool.name, status: "skipped", version: result.version });
|
|
127289
|
+
} else {
|
|
127290
|
+
results.push({ name: tool.name, status: "ok", version: result.version });
|
|
127291
|
+
}
|
|
127292
|
+
} else {
|
|
127293
|
+
logger.error(`Failed to install ${tool.name}: ${result.error}`);
|
|
127294
|
+
results.push({ name: tool.name, status: "error", error: result.error });
|
|
127295
|
+
allSuccess = false;
|
|
127296
|
+
}
|
|
127297
|
+
console.log();
|
|
127298
|
+
}
|
|
127299
|
+
if (!allSuccess) {
|
|
127300
|
+
const failed = results.filter((r) => r.status === "error");
|
|
127301
|
+
logger.box([
|
|
127302
|
+
`${failed.length} tool(s) failed to install:`,
|
|
127303
|
+
...failed.map((f) => ` - ${f.name}: ${f.error}`),
|
|
127304
|
+
"",
|
|
127305
|
+
"Run again with --verbose for details:",
|
|
127306
|
+
" ss tmux install --verbose"
|
|
127307
|
+
], "error");
|
|
127308
|
+
process.exit(1);
|
|
127309
|
+
}
|
|
127310
|
+
logger.step(9, totalSteps, "Configuring Windows Terminal...");
|
|
127311
|
+
const wtCheck = checkWindowsTerminal();
|
|
127312
|
+
if (wtCheck.installed) {
|
|
127313
|
+
const configResult = configureWindowsTerminal();
|
|
127314
|
+
if (configResult.success) {
|
|
127315
|
+
if (configResult.profileExists) {
|
|
127316
|
+
logger.success("SmartStack Dev profile already configured");
|
|
127317
|
+
} else {
|
|
127318
|
+
logger.success("SmartStack Dev profile added to Windows Terminal");
|
|
127319
|
+
}
|
|
127320
|
+
} else {
|
|
127321
|
+
logger.warning(`Configuration skipped: ${configResult.error}`);
|
|
127322
|
+
logger.info("You can configure manually after launching Windows Terminal once.");
|
|
127323
|
+
}
|
|
127324
|
+
} else {
|
|
127325
|
+
logger.warning("Windows Terminal not available - skipping configuration");
|
|
127326
|
+
}
|
|
127327
|
+
console.log();
|
|
127328
|
+
logger.step(10, totalSteps, "Launching...");
|
|
127329
|
+
if (options.launch === false) {
|
|
127330
|
+
logger.info("Launch skipped (--no-launch)");
|
|
127331
|
+
logger.box([
|
|
127332
|
+
"WSL development environment ready!",
|
|
127333
|
+
"",
|
|
127334
|
+
"Launch manually:",
|
|
127335
|
+
' wt -p "SmartStack Dev"'
|
|
127336
|
+
], "success");
|
|
127337
|
+
return;
|
|
127338
|
+
}
|
|
127339
|
+
if (wtCheck.installed) {
|
|
127340
|
+
logger.info("Opening Windows Terminal with SmartStack Dev profile...");
|
|
127341
|
+
const launched = launchWindowsTerminal();
|
|
127342
|
+
if (launched) {
|
|
127343
|
+
logger.box([
|
|
127344
|
+
"WSL development environment ready!",
|
|
127345
|
+
"",
|
|
127346
|
+
"Windows Terminal is opening with tmux.",
|
|
127347
|
+
"Run claude inside tmux to start Claude Code.",
|
|
127348
|
+
"",
|
|
127349
|
+
"Next time, launch directly:",
|
|
127350
|
+
' wt -p "SmartStack Dev"'
|
|
127351
|
+
], "success");
|
|
127352
|
+
} else {
|
|
127353
|
+
logger.warning("Could not launch Windows Terminal automatically");
|
|
127354
|
+
logger.info('Launch manually: wt -p "SmartStack Dev"');
|
|
127355
|
+
}
|
|
127356
|
+
} else {
|
|
127357
|
+
logger.info("Opening WSL with tmux...");
|
|
127358
|
+
logger.box([
|
|
127359
|
+
"WSL development environment ready!",
|
|
127360
|
+
"",
|
|
127361
|
+
"Start manually:",
|
|
127362
|
+
' wsl -e bash -c "tmux new -s smartstack"',
|
|
127363
|
+
" Then run: claude"
|
|
127364
|
+
], "success");
|
|
127365
|
+
}
|
|
127366
|
+
});
|
|
127367
|
+
tmuxCommand.command("status").description("Show WSL development environment status").option("--json", "Output as JSON").option("-v, --verbose", "Show detailed information").action(async (options) => {
|
|
127368
|
+
if (options.verbose) logger.setVerbose(true);
|
|
127369
|
+
const wslStatus = checkWsl();
|
|
127370
|
+
const wtStatus = checkWindowsTerminal();
|
|
127371
|
+
const gitStatus = checkGitInWsl();
|
|
127372
|
+
const tmuxStatus = checkTmuxInWsl();
|
|
127373
|
+
const nvmStatus = checkNvmInWsl();
|
|
127374
|
+
const nodeStatus = checkNodeInWsl();
|
|
127375
|
+
const dotnetStatus = checkDotnetInWsl();
|
|
127376
|
+
const claudeStatus = checkClaudeInWsl();
|
|
127377
|
+
if (options.json) {
|
|
127378
|
+
console.log(JSON.stringify({
|
|
127379
|
+
wsl: wslStatus,
|
|
127380
|
+
windowsTerminal: wtStatus,
|
|
127381
|
+
tools: {
|
|
127382
|
+
git: gitStatus,
|
|
127383
|
+
tmux: tmuxStatus,
|
|
127384
|
+
nvm: nvmStatus,
|
|
127385
|
+
node: nodeStatus,
|
|
127386
|
+
dotnet: dotnetStatus,
|
|
127387
|
+
claude: claudeStatus
|
|
127388
|
+
}
|
|
127389
|
+
}, null, 2));
|
|
127390
|
+
const allInstalled2 = wtStatus.installed && gitStatus.installed && tmuxStatus.installed && nodeStatus.installed && dotnetStatus.installed && claudeStatus.installed;
|
|
127391
|
+
process.exit(allInstalled2 ? 0 : 1);
|
|
127392
|
+
}
|
|
127393
|
+
logger.header("WSL Development Environment Status");
|
|
127394
|
+
console.log(source_default.bold("Windows"));
|
|
127395
|
+
if (wslStatus.installed) {
|
|
127396
|
+
console.log(` ${source_default.green("\u2713")} WSL ${wslStatus.version} ${source_default.gray(`(${wslStatus.defaultDistro || "no distro"})`)}`);
|
|
127397
|
+
} else {
|
|
127398
|
+
console.log(` ${source_default.red("\u2717")} WSL not installed`);
|
|
127399
|
+
}
|
|
127400
|
+
console.log(` ${wtStatus.installed ? source_default.green("\u2713") : source_default.red("\u2717")} Windows Terminal`);
|
|
127401
|
+
console.log();
|
|
127402
|
+
if (!wslStatus.installed) {
|
|
127403
|
+
logger.box([
|
|
127404
|
+
"WSL is not installed.",
|
|
127405
|
+
"",
|
|
127406
|
+
"Install WSL: wsl --install"
|
|
127407
|
+
], "error");
|
|
127408
|
+
process.exit(1);
|
|
127409
|
+
}
|
|
127410
|
+
console.log(source_default.bold("WSL Tools"));
|
|
127411
|
+
const table = new import_cli_table36.default({
|
|
127412
|
+
head: [source_default.cyan("Tool"), source_default.cyan("Status"), source_default.cyan("Version")],
|
|
127413
|
+
style: { head: [], border: [] },
|
|
127414
|
+
colWidths: [18, 15, 25]
|
|
127415
|
+
});
|
|
127416
|
+
const tools = [
|
|
127417
|
+
{ name: "Git", s: gitStatus },
|
|
127418
|
+
{ name: "tmux", s: tmuxStatus },
|
|
127419
|
+
{ name: "nvm", s: nvmStatus },
|
|
127420
|
+
{ name: "Node.js", s: nodeStatus },
|
|
127421
|
+
{ name: ".NET SDK", s: dotnetStatus },
|
|
127422
|
+
{ name: "Claude Code", s: claudeStatus }
|
|
127423
|
+
];
|
|
127424
|
+
for (const t of tools) {
|
|
127425
|
+
table.push([
|
|
127426
|
+
t.name,
|
|
127427
|
+
t.s.installed ? source_default.green("\u2713 OK") : source_default.red("\u2717 Missing"),
|
|
127428
|
+
t.s.version || source_default.gray("-")
|
|
127429
|
+
]);
|
|
127430
|
+
}
|
|
127431
|
+
console.log(table.toString());
|
|
127432
|
+
console.log();
|
|
127433
|
+
const allInstalled = tools.every((t) => t.s.installed) && wtStatus.installed;
|
|
127434
|
+
if (allInstalled) {
|
|
127435
|
+
logger.box([
|
|
127436
|
+
"All tools installed!",
|
|
127437
|
+
"",
|
|
127438
|
+
'Launch: wt -p "SmartStack Dev"'
|
|
127439
|
+
], "success");
|
|
127440
|
+
} else {
|
|
127441
|
+
const missing = [];
|
|
127442
|
+
if (!wtStatus.installed) missing.push("Windows Terminal");
|
|
127443
|
+
missing.push(...tools.filter((t) => !t.s.installed).map((t) => t.name));
|
|
127444
|
+
logger.box([
|
|
127445
|
+
`Missing: ${missing.join(", ")}`,
|
|
127446
|
+
"",
|
|
127447
|
+
`Fix with: ${source_default.cyan("ss tmux install")}`
|
|
127448
|
+
], "warning");
|
|
127449
|
+
process.exit(1);
|
|
127450
|
+
}
|
|
127451
|
+
});
|
|
127452
|
+
|
|
127453
|
+
// src/index.ts
|
|
127454
|
+
var import_fs6 = require("fs");
|
|
127455
|
+
var import_path13 = require("path");
|
|
127456
|
+
var pkg = JSON.parse((0, import_fs6.readFileSync)((0, import_path13.join)(__dirname, "..", "package.json"), "utf-8"));
|
|
126878
127457
|
var LICENSE_FREE_COMMANDS = ["license", "help", "--help", "-h", "--version", "-v"];
|
|
126879
127458
|
async function main2() {
|
|
126880
127459
|
const program2 = new Command();
|
|
@@ -126893,6 +127472,7 @@ async function main2() {
|
|
|
126893
127472
|
program2.addCommand(adminCommand);
|
|
126894
127473
|
program2.addCommand(mcpCommand);
|
|
126895
127474
|
program2.addCommand(derivePrdCommand);
|
|
127475
|
+
program2.addCommand(tmuxCommand);
|
|
126896
127476
|
const args = process.argv.slice(2);
|
|
126897
127477
|
const commandName = args[0] || "";
|
|
126898
127478
|
const requiresLicense = !LICENSE_FREE_COMMANDS.some(
|