sisyphi 1.1.35 → 1.1.36
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/dist/cli.js
CHANGED
|
@@ -539,14 +539,14 @@ __export(creds_exports, {
|
|
|
539
539
|
readTailscaleEnv: () => readTailscaleEnv,
|
|
540
540
|
writeTailscaleEnv: () => writeTailscaleEnv
|
|
541
541
|
});
|
|
542
|
-
import { chmodSync as chmodSync3, existsSync as existsSync27, mkdirSync as
|
|
542
|
+
import { chmodSync as chmodSync3, existsSync as existsSync27, mkdirSync as mkdirSync15, readFileSync as readFileSync31 } from "fs";
|
|
543
543
|
import { createInterface as createInterface4 } from "readline";
|
|
544
544
|
function isValidProvider(value) {
|
|
545
545
|
return PROVIDERS.includes(value);
|
|
546
546
|
}
|
|
547
547
|
function ensureDeployDir() {
|
|
548
548
|
const dir = deployDir();
|
|
549
|
-
if (!existsSync27(dir))
|
|
549
|
+
if (!existsSync27(dir)) mkdirSync15(dir, { recursive: true, mode: 448 });
|
|
550
550
|
}
|
|
551
551
|
function parseEnvFile(text) {
|
|
552
552
|
const out = {};
|
|
@@ -573,7 +573,7 @@ function serializeEnvFile(values) {
|
|
|
573
573
|
}
|
|
574
574
|
function readEnvFile(path) {
|
|
575
575
|
if (!existsSync27(path)) return null;
|
|
576
|
-
return parseEnvFile(
|
|
576
|
+
return parseEnvFile(readFileSync31(path, "utf-8"));
|
|
577
577
|
}
|
|
578
578
|
function writeEnvFile(path, values) {
|
|
579
579
|
ensureDeployDir();
|
|
@@ -668,8 +668,8 @@ var init_creds = __esm({
|
|
|
668
668
|
|
|
669
669
|
// src/cli/index.ts
|
|
670
670
|
import { Command } from "commander";
|
|
671
|
-
import { existsSync as existsSync33, mkdirSync as
|
|
672
|
-
import { dirname as
|
|
671
|
+
import { existsSync as existsSync33, mkdirSync as mkdirSync17, readFileSync as readFileSync35 } from "fs";
|
|
672
|
+
import { dirname as dirname13, join as join31 } from "path";
|
|
673
673
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
674
674
|
|
|
675
675
|
// src/cli/commands/start.ts
|
|
@@ -4559,16 +4559,55 @@ function readFileSafe(filePath) {
|
|
|
4559
4559
|
function escapeXml(s) {
|
|
4560
4560
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
4561
4561
|
}
|
|
4562
|
-
function
|
|
4562
|
+
function buildSessionBlock(cwd, session2) {
|
|
4563
|
+
const lines = [];
|
|
4564
|
+
const nameAttr = session2.name ? ` name="${escapeXml(session2.name)}"` : "";
|
|
4565
|
+
lines.push(` <session id="${escapeXml(session2.id)}"${nameAttr} status="${escapeXml(session2.status)}">`);
|
|
4566
|
+
lines.push(` <task>${escapeXml(session2.task)}</task>`);
|
|
4567
|
+
lines.push(` <created>${escapeXml(session2.createdAt)}</created>`);
|
|
4568
|
+
lines.push(` <cycles>${session2.orchestratorCycles.length}</cycles>`);
|
|
4569
|
+
if (session2.status === "completed") {
|
|
4570
|
+
if (session2.completionReport) {
|
|
4571
|
+
const snippet = session2.completionReport.slice(0, 300).replace(/\n+/g, " ").trim();
|
|
4572
|
+
lines.push(` <completion-report>${escapeXml(snippet)}${session2.completionReport.length > 300 ? "\u2026" : ""}</completion-report>`);
|
|
4573
|
+
}
|
|
4574
|
+
} else {
|
|
4575
|
+
if (session2.agents.length > 0) {
|
|
4576
|
+
const counts = /* @__PURE__ */ new Map();
|
|
4577
|
+
for (const agent2 of session2.agents) {
|
|
4578
|
+
counts.set(agent2.status, (counts.get(agent2.status) ?? 0) + 1);
|
|
4579
|
+
}
|
|
4580
|
+
const summary = [...counts.entries()].map(([status, n]) => `${n} ${status}`).join(", ");
|
|
4581
|
+
lines.push(` <agents>${escapeXml(summary)}</agents>`);
|
|
4582
|
+
}
|
|
4583
|
+
const goalContent = readFileSafe(goalPath(cwd, session2.id));
|
|
4584
|
+
if (goalContent) {
|
|
4585
|
+
const firstLine = goalContent.split("\n").map((l) => l.trim()).find((l) => l.length > 0 && !l.startsWith("#"));
|
|
4586
|
+
if (firstLine) lines.push(` <goal>${escapeXml(firstLine)}</goal>`);
|
|
4587
|
+
}
|
|
4588
|
+
const roadmapContent = readFileSafe(roadmapPath(cwd, session2.id));
|
|
4589
|
+
if (roadmapContent) {
|
|
4590
|
+
const todos = roadmapContent.split("\n").filter((l) => l.includes("- [ ]")).slice(0, 5).map((l) => l.trim());
|
|
4591
|
+
if (todos.length > 0) {
|
|
4592
|
+
lines.push(" <todos>");
|
|
4593
|
+
for (const todo of todos) lines.push(` ${escapeXml(todo)}`);
|
|
4594
|
+
lines.push(" </todos>");
|
|
4595
|
+
}
|
|
4596
|
+
}
|
|
4597
|
+
}
|
|
4598
|
+
lines.push(" </session>");
|
|
4599
|
+
return lines.join("\n");
|
|
4600
|
+
}
|
|
4601
|
+
function buildCompanionContextBlocks(cwd) {
|
|
4563
4602
|
let sessionDirs;
|
|
4564
4603
|
try {
|
|
4565
4604
|
sessionDirs = readdirSync4(sessionsDir(cwd));
|
|
4566
4605
|
} catch {
|
|
4567
|
-
return
|
|
4606
|
+
return {};
|
|
4568
4607
|
}
|
|
4569
4608
|
const now = Date.now();
|
|
4570
4609
|
const sevenDaysMs = 7 * 24 * 60 * 60 * 1e3;
|
|
4571
|
-
const
|
|
4610
|
+
const blocks = {};
|
|
4572
4611
|
for (const sessionId of sessionDirs) {
|
|
4573
4612
|
const stateRaw = readFileSafe(statePath(cwd, sessionId));
|
|
4574
4613
|
if (!stateRaw) continue;
|
|
@@ -4581,48 +4620,31 @@ function buildCompanionContext(cwd) {
|
|
|
4581
4620
|
if (session2.status === "completed" && session2.completedAt) {
|
|
4582
4621
|
if (now - new Date(session2.completedAt).getTime() > sevenDaysMs) continue;
|
|
4583
4622
|
}
|
|
4584
|
-
|
|
4585
|
-
const nameAttr = session2.name ? ` name="${escapeXml(session2.name)}"` : "";
|
|
4586
|
-
lines.push(` <session id="${escapeXml(session2.id)}"${nameAttr} status="${escapeXml(session2.status)}">`);
|
|
4587
|
-
lines.push(` <task>${escapeXml(session2.task)}</task>`);
|
|
4588
|
-
lines.push(` <created>${escapeXml(session2.createdAt)}</created>`);
|
|
4589
|
-
lines.push(` <cycles>${session2.orchestratorCycles.length}</cycles>`);
|
|
4590
|
-
if (session2.status === "completed") {
|
|
4591
|
-
if (session2.completionReport) {
|
|
4592
|
-
const snippet = session2.completionReport.slice(0, 300).replace(/\n+/g, " ").trim();
|
|
4593
|
-
lines.push(` <completion-report>${escapeXml(snippet)}${session2.completionReport.length > 300 ? "\u2026" : ""}</completion-report>`);
|
|
4594
|
-
}
|
|
4595
|
-
} else {
|
|
4596
|
-
if (session2.agents.length > 0) {
|
|
4597
|
-
const counts = /* @__PURE__ */ new Map();
|
|
4598
|
-
for (const agent2 of session2.agents) {
|
|
4599
|
-
counts.set(agent2.status, (counts.get(agent2.status) ?? 0) + 1);
|
|
4600
|
-
}
|
|
4601
|
-
const summary = [...counts.entries()].map(([status, n]) => `${n} ${status}`).join(", ");
|
|
4602
|
-
lines.push(` <agents>${escapeXml(summary)}</agents>`);
|
|
4603
|
-
}
|
|
4604
|
-
const goalContent = readFileSafe(goalPath(cwd, session2.id));
|
|
4605
|
-
if (goalContent) {
|
|
4606
|
-
const firstLine = goalContent.split("\n").map((l) => l.trim()).find((l) => l.length > 0 && !l.startsWith("#"));
|
|
4607
|
-
if (firstLine) lines.push(` <goal>${escapeXml(firstLine)}</goal>`);
|
|
4608
|
-
}
|
|
4609
|
-
const roadmapContent = readFileSafe(roadmapPath(cwd, session2.id));
|
|
4610
|
-
if (roadmapContent) {
|
|
4611
|
-
const todos = roadmapContent.split("\n").filter((l) => l.includes("- [ ]")).slice(0, 5).map((l) => l.trim());
|
|
4612
|
-
if (todos.length > 0) {
|
|
4613
|
-
lines.push(" <todos>");
|
|
4614
|
-
for (const todo of todos) lines.push(` ${escapeXml(todo)}`);
|
|
4615
|
-
lines.push(" </todos>");
|
|
4616
|
-
}
|
|
4617
|
-
}
|
|
4618
|
-
}
|
|
4619
|
-
lines.push(" </session>");
|
|
4620
|
-
sessionBlocks.push(lines.join("\n"));
|
|
4623
|
+
blocks[session2.id] = buildSessionBlock(cwd, session2);
|
|
4621
4624
|
}
|
|
4622
|
-
|
|
4623
|
-
|
|
4625
|
+
return blocks;
|
|
4626
|
+
}
|
|
4627
|
+
function renderFullContext(blocks) {
|
|
4628
|
+
const entries = Object.values(blocks);
|
|
4629
|
+
if (entries.length === 0) return "<sessions>No sessions found.</sessions>";
|
|
4630
|
+
return ["<sessions>", ...entries, "</sessions>"].join("\n");
|
|
4631
|
+
}
|
|
4632
|
+
function renderContextDelta(prev, next) {
|
|
4633
|
+
const ids = /* @__PURE__ */ new Set([...Object.keys(prev), ...Object.keys(next)]);
|
|
4634
|
+
const entries = [];
|
|
4635
|
+
for (const id of ids) {
|
|
4636
|
+
const p = prev[id];
|
|
4637
|
+
const n = next[id];
|
|
4638
|
+
if (p === void 0 && n !== void 0) {
|
|
4639
|
+
entries.push(n.replace(/^(\s*)<session /, `$1<session change="added" `));
|
|
4640
|
+
} else if (p !== void 0 && n === void 0) {
|
|
4641
|
+
entries.push(` <session id="${escapeXml(id)}" change="removed" />`);
|
|
4642
|
+
} else if (p !== n && n !== void 0) {
|
|
4643
|
+
entries.push(n.replace(/^(\s*)<session /, `$1<session change="updated" `));
|
|
4644
|
+
}
|
|
4624
4645
|
}
|
|
4625
|
-
|
|
4646
|
+
if (entries.length === 0) return null;
|
|
4647
|
+
return ["<sessions-changed-since-last-prompt>", ...entries, "</sessions-changed-since-last-prompt>"].join("\n");
|
|
4626
4648
|
}
|
|
4627
4649
|
function buildSessionContext(session2, cwd) {
|
|
4628
4650
|
const goal = readFileSafe(goalPath(cwd, session2.id));
|
|
@@ -8996,7 +9018,9 @@ function renderRequirementsMarkdown(json) {
|
|
|
8996
9018
|
}
|
|
8997
9019
|
|
|
8998
9020
|
// src/cli/commands/companion.ts
|
|
8999
|
-
import { basename as basename5 } from "path";
|
|
9021
|
+
import { basename as basename5, dirname as dirname11, join as join28 } from "path";
|
|
9022
|
+
import { mkdirSync as mkdirSync14, readFileSync as readFileSync30, writeFileSync as writeFileSync17 } from "fs";
|
|
9023
|
+
init_paths();
|
|
9000
9024
|
|
|
9001
9025
|
// src/shared/companion-render.ts
|
|
9002
9026
|
import stringWidth from "string-width";
|
|
@@ -10678,9 +10702,25 @@ function registerCompanion(program2) {
|
|
|
10678
10702
|
companion.command("memory").description("Show accumulated companion observations grouped by category").option("--repo <path>", "Filter observations by repo path").action(async (opts) => {
|
|
10679
10703
|
await runCompanionMemory(opts);
|
|
10680
10704
|
});
|
|
10681
|
-
companion.command("context").description("
|
|
10682
|
-
const
|
|
10683
|
-
|
|
10705
|
+
companion.command("context").description("Emit per-prompt context for the companion plugin hook. Caches the last emission per claude session and writes only the delta on subsequent calls (or nothing, when unchanged).").requiredOption("--cwd <path>", "Project directory whose sessions to summarise").requiredOption("--session-id <id>", "Claude session id (from the UserPromptSubmit stdin payload) \u2014 keys the per-session cache").action((opts) => {
|
|
10706
|
+
const cachePath = join28(globalDir(), "companion-context-cache", `${opts.sessionId}.json`);
|
|
10707
|
+
let prev = {};
|
|
10708
|
+
try {
|
|
10709
|
+
prev = JSON.parse(readFileSync30(cachePath, "utf-8"));
|
|
10710
|
+
} catch {
|
|
10711
|
+
prev = {};
|
|
10712
|
+
}
|
|
10713
|
+
const next = buildCompanionContextBlocks(opts.cwd);
|
|
10714
|
+
const hadPrev = Object.keys(prev).length > 0;
|
|
10715
|
+
if (hadPrev) {
|
|
10716
|
+
const delta = renderContextDelta(prev, next);
|
|
10717
|
+
if (delta === null) return;
|
|
10718
|
+
process.stdout.write(delta);
|
|
10719
|
+
} else {
|
|
10720
|
+
process.stdout.write(renderFullContext(next));
|
|
10721
|
+
}
|
|
10722
|
+
mkdirSync14(dirname11(cachePath), { recursive: true });
|
|
10723
|
+
writeFileSync17(cachePath, JSON.stringify(next), "utf-8");
|
|
10684
10724
|
});
|
|
10685
10725
|
companion.command("pane").description("Open (or focus) a side claude pane next to the dashboard").option("--cwd <path>", "Project directory", process.cwd()).action(async (opts) => {
|
|
10686
10726
|
const { openCompanionPane: openCompanionPane2 } = await Promise.resolve().then(() => (init_tmux(), tmux_exports));
|
|
@@ -10703,14 +10743,14 @@ function registerCompanion(program2) {
|
|
|
10703
10743
|
|
|
10704
10744
|
// src/cli/commands/deploy.ts
|
|
10705
10745
|
import { homedir as homedir13 } from "os";
|
|
10706
|
-
import { join as
|
|
10746
|
+
import { join as join29 } from "path";
|
|
10707
10747
|
|
|
10708
10748
|
// src/cli/deploy/runner.ts
|
|
10709
10749
|
init_paths();
|
|
10710
10750
|
init_exec();
|
|
10711
10751
|
init_creds();
|
|
10712
10752
|
import { spawn as spawn2, spawnSync as spawnSync3 } from "child_process";
|
|
10713
|
-
import { copyFileSync as copyFileSync2, existsSync as existsSync30, mkdirSync as
|
|
10753
|
+
import { copyFileSync as copyFileSync2, existsSync as existsSync30, mkdirSync as mkdirSync16, readFileSync as readFileSync33 } from "fs";
|
|
10714
10754
|
|
|
10715
10755
|
// src/cli/deploy/pricing.ts
|
|
10716
10756
|
var LAST_VERIFIED = "2026-05-06";
|
|
@@ -10745,12 +10785,12 @@ function formatCostLine(provider, instanceType) {
|
|
|
10745
10785
|
// src/cli/deploy/runtime.ts
|
|
10746
10786
|
init_atomic();
|
|
10747
10787
|
init_paths();
|
|
10748
|
-
import { existsSync as existsSync28, readFileSync as
|
|
10788
|
+
import { existsSync as existsSync28, readFileSync as readFileSync32, unlinkSync as unlinkSync4 } from "fs";
|
|
10749
10789
|
function readRuntimeState(provider) {
|
|
10750
10790
|
const path = deployRuntimePath(provider);
|
|
10751
10791
|
if (!existsSync28(path)) return null;
|
|
10752
10792
|
try {
|
|
10753
|
-
return JSON.parse(
|
|
10793
|
+
return JSON.parse(readFileSync32(path, "utf-8"));
|
|
10754
10794
|
} catch {
|
|
10755
10795
|
return null;
|
|
10756
10796
|
}
|
|
@@ -10811,10 +10851,10 @@ function isTailscaleAvailable() {
|
|
|
10811
10851
|
|
|
10812
10852
|
// src/cli/deploy/templates.ts
|
|
10813
10853
|
import { existsSync as existsSync29 } from "fs";
|
|
10814
|
-
import { dirname as
|
|
10854
|
+
import { dirname as dirname12, resolve as resolve10 } from "path";
|
|
10815
10855
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
10816
10856
|
function deployRoot() {
|
|
10817
|
-
const here =
|
|
10857
|
+
const here = dirname12(fileURLToPath4(import.meta.url));
|
|
10818
10858
|
const bundled = resolve10(here, "..", "deploy");
|
|
10819
10859
|
if (existsSync29(bundled)) return bundled;
|
|
10820
10860
|
const sourceRoot = resolve10(here, "..", "..", "..", "deploy");
|
|
@@ -11002,7 +11042,7 @@ function ensureTerraformInstalled() {
|
|
|
11002
11042
|
function ensureProviderStateDir(provider) {
|
|
11003
11043
|
ensureDeployDir();
|
|
11004
11044
|
const dir = deployProviderDir(provider);
|
|
11005
|
-
if (!existsSync30(dir))
|
|
11045
|
+
if (!existsSync30(dir)) mkdirSync16(dir, { recursive: true, mode: 448 });
|
|
11006
11046
|
}
|
|
11007
11047
|
function backupState(provider) {
|
|
11008
11048
|
const src = deployStatePath(provider);
|
|
@@ -11017,7 +11057,7 @@ function readSshPubkey(path) {
|
|
|
11017
11057
|
or pass --ssh-key <path>.`
|
|
11018
11058
|
);
|
|
11019
11059
|
}
|
|
11020
|
-
return
|
|
11060
|
+
return readFileSync33(path, "utf-8").trim();
|
|
11021
11061
|
}
|
|
11022
11062
|
function readOutputs(provider) {
|
|
11023
11063
|
const result = spawnSync3("terraform", ["output", "-json", `-state=${deployStatePath(provider)}`], {
|
|
@@ -11295,7 +11335,7 @@ function registerDeploy(program2) {
|
|
|
11295
11335
|
});
|
|
11296
11336
|
for (const provider of PROVIDERS) {
|
|
11297
11337
|
const sub = deploy.command(provider).description(`${provider} commands.`);
|
|
11298
|
-
sub.command("up").description(`Provision the ${provider} box (terraform init \u2192 plan \u2192 apply).`).option("--region <region>", `Provider region (defaults: hetzner=nbg1, aws=us-east-1).`).option("--arch <arch>", "'arm' (default) or 'x86'. Picks the default --size and image.", "arm").option("--size <size>", "Instance type override (defaults follow --arch).").option("--ssh-key <path>", "Path to SSH public key.",
|
|
11338
|
+
sub.command("up").description(`Provision the ${provider} box (terraform init \u2192 plan \u2192 apply).`).option("--region <region>", `Provider region (defaults: hetzner=nbg1, aws=us-east-1).`).option("--arch <arch>", "'arm' (default) or 'x86'. Picks the default --size and image.", "arm").option("--size <size>", "Instance type override (defaults follow --arch).").option("--ssh-key <path>", "Path to SSH public key.", join29(homedir13(), ".ssh", "id_ed25519.pub")).option("--no-chromium", "Skip headless Chromium install.").option("--no-auto-update", "Skip the daily auto-update systemd timer.").option("--name <name>", "Box hostname / Tailscale node name.", "sisyphus").option("-y, --yes", "Skip the re-provision confirmation prompt when state already exists.").action(async (raw) => {
|
|
11299
11339
|
const opts = resolveUpOptions(provider, raw);
|
|
11300
11340
|
await deployUp(provider, opts);
|
|
11301
11341
|
});
|
|
@@ -11380,7 +11420,7 @@ function ensureGroveRegistered(provider, repo, instancePath) {
|
|
|
11380
11420
|
init_exec();
|
|
11381
11421
|
import { spawnSync as spawnSync5 } from "child_process";
|
|
11382
11422
|
import { existsSync as existsSync31 } from "fs";
|
|
11383
|
-
import { basename as basename6, join as
|
|
11423
|
+
import { basename as basename6, join as join30 } from "path";
|
|
11384
11424
|
function captureGit(args2) {
|
|
11385
11425
|
const result = spawnSync5("git", args2, {
|
|
11386
11426
|
encoding: "utf-8",
|
|
@@ -11431,10 +11471,10 @@ function buildRsyncArgs(localDir, remoteTarget) {
|
|
|
11431
11471
|
];
|
|
11432
11472
|
}
|
|
11433
11473
|
function detectPackageManager(toplevel) {
|
|
11434
|
-
if (existsSync31(
|
|
11435
|
-
if (existsSync31(
|
|
11436
|
-
if (existsSync31(
|
|
11437
|
-
if (existsSync31(
|
|
11474
|
+
if (existsSync31(join30(toplevel, "pnpm-lock.yaml"))) return "pnpm";
|
|
11475
|
+
if (existsSync31(join30(toplevel, "bun.lockb"))) return "bun";
|
|
11476
|
+
if (existsSync31(join30(toplevel, "yarn.lock"))) return "yarn";
|
|
11477
|
+
if (existsSync31(join30(toplevel, "package-lock.json"))) return "npm";
|
|
11438
11478
|
return null;
|
|
11439
11479
|
}
|
|
11440
11480
|
function packageManagerInstallCmd(pm) {
|
|
@@ -11719,7 +11759,7 @@ function attachNotify(diagnostic2) {
|
|
|
11719
11759
|
// src/cli/commands/tmux-sessions.ts
|
|
11720
11760
|
init_paths();
|
|
11721
11761
|
import { execSync as execSync18 } from "child_process";
|
|
11722
|
-
import { readFileSync as
|
|
11762
|
+
import { readFileSync as readFileSync34, existsSync as existsSync32 } from "fs";
|
|
11723
11763
|
var DOT_MAP = {
|
|
11724
11764
|
"orchestrator:processing": { icon: "\u25CF", color: "#d4ad6a" },
|
|
11725
11765
|
"orchestrator:idle": { icon: "\u25CF", color: "#d47766" },
|
|
@@ -11732,7 +11772,7 @@ function readManifest() {
|
|
|
11732
11772
|
const p = sessionsManifestPath();
|
|
11733
11773
|
if (!existsSync32(p)) return null;
|
|
11734
11774
|
try {
|
|
11735
|
-
return JSON.parse(
|
|
11775
|
+
return JSON.parse(readFileSync34(p, "utf-8"));
|
|
11736
11776
|
} catch {
|
|
11737
11777
|
return null;
|
|
11738
11778
|
}
|
|
@@ -11778,7 +11818,7 @@ if (nodeVersion < 22) {
|
|
|
11778
11818
|
var program = new Command();
|
|
11779
11819
|
program.name("sis").description("tmux-integrated orchestration daemon for Claude Code").version(
|
|
11780
11820
|
JSON.parse(
|
|
11781
|
-
|
|
11821
|
+
readFileSync35(join31(dirname13(fileURLToPath5(import.meta.url)), "..", "package.json"), "utf-8")
|
|
11782
11822
|
).version
|
|
11783
11823
|
);
|
|
11784
11824
|
program.configureHelp({
|
|
@@ -11853,7 +11893,7 @@ var args = process.argv.slice(2);
|
|
|
11853
11893
|
var firstArg = args[0];
|
|
11854
11894
|
var skipWelcome = ["admin", "help", "--help", "-h", "--version", "-V"];
|
|
11855
11895
|
if (!existsSync33(globalDir()) && firstArg && !skipWelcome.includes(firstArg)) {
|
|
11856
|
-
|
|
11896
|
+
mkdirSync17(globalDir(), { recursive: true });
|
|
11857
11897
|
console.log("");
|
|
11858
11898
|
console.log(" Welcome to Sisyphus. Run 'sis admin setup' to get started.");
|
|
11859
11899
|
console.log("");
|