@arkhera30/cli 0.1.11 → 0.1.12

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.
Files changed (2) hide show
  1. package/dist/index.js +156 -81
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -15,14 +15,20 @@ import { join as join4 } from "path";
15
15
  import { input, confirm, number, select, password } from "@inquirer/prompts";
16
16
 
17
17
  // src/lib/config.ts
18
- import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
19
- import { resolve } from "path";
18
+ import { readFileSync as readFileSync2, writeFileSync, mkdirSync, existsSync, readdirSync, statSync } from "fs";
19
+ import { resolve, join as pathJoin, relative } from "path";
20
20
  import { homedir as homedir2 } from "os";
21
21
  import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
22
22
 
23
23
  // src/lib/constants.ts
24
24
  import { homedir } from "os";
25
- import { join } from "path";
25
+ import { join, dirname } from "path";
26
+ import { readFileSync } from "fs";
27
+ import { fileURLToPath } from "url";
28
+ var __pkg_dirname = dirname(fileURLToPath(import.meta.url));
29
+ var pkgPath = join(__pkg_dirname, "..", "..", "package.json");
30
+ var pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
31
+ var CLI_VERSION = pkg.version;
26
32
  var HORUS_DIR = join(homedir(), ".horus");
27
33
  var CONFIG_PATH = join(HORUS_DIR, "config.yaml");
28
34
  var ENV_PATH = join(HORUS_DIR, ".env");
@@ -72,7 +78,7 @@ function loadConfig() {
72
78
  if (!existsSync(CONFIG_PATH)) {
73
79
  return defaultConfig();
74
80
  }
75
- const raw = readFileSync(CONFIG_PATH, "utf-8");
81
+ const raw = readFileSync2(CONFIG_PATH, "utf-8");
76
82
  const parsed = parseYaml(raw);
77
83
  const defaults = defaultConfig();
78
84
  return {
@@ -107,12 +113,54 @@ function resolvePath(p) {
107
113
  }
108
114
  return resolve(p);
109
115
  }
116
+ function discoverRepoDirs(rootDir, maxDepth = 4) {
117
+ const repoDirs = /* @__PURE__ */ new Set();
118
+ function walk(dir, depth) {
119
+ if (depth > maxDepth) return;
120
+ let entries;
121
+ try {
122
+ entries = readdirSync(dir);
123
+ } catch {
124
+ return;
125
+ }
126
+ for (const entry of entries) {
127
+ if (entry === "node_modules" || entry === ".git") continue;
128
+ const full = pathJoin(dir, entry);
129
+ try {
130
+ if (!statSync(full).isDirectory()) continue;
131
+ } catch {
132
+ continue;
133
+ }
134
+ if (existsSync(pathJoin(full, ".git"))) {
135
+ repoDirs.add(dir);
136
+ }
137
+ walk(full, depth + 1);
138
+ }
139
+ }
140
+ if (existsSync(rootDir)) {
141
+ walk(rootDir, 0);
142
+ }
143
+ return [...repoDirs];
144
+ }
110
145
  function generateEnv(config) {
111
146
  const dataDir = resolvePath(config.data_dir);
112
147
  const hostReposPath = config.host_repos_path ? resolvePath(config.host_repos_path) : "";
113
148
  const baseScanPath = "/data/repos";
114
- const extraScanPaths = (config.host_repos_extra_scan_dirs ?? []).map((d) => d.trim()).filter(Boolean).map((d) => `${baseScanPath}/${d}`);
115
- const forgeScanPaths = [baseScanPath, ...extraScanPaths].join(":");
149
+ let forgeScanPaths;
150
+ if (hostReposPath) {
151
+ const discoveredDirs = discoverRepoDirs(hostReposPath);
152
+ const containerPaths = discoveredDirs.map((dir) => {
153
+ const rel = relative(hostReposPath, dir);
154
+ return rel ? `${baseScanPath}/${rel}` : baseScanPath;
155
+ });
156
+ const allPaths = [baseScanPath, ...containerPaths];
157
+ const extraScanPaths = (config.host_repos_extra_scan_dirs ?? []).map((d) => d.trim()).filter(Boolean).map((d) => `${baseScanPath}/${d}`);
158
+ const uniquePaths = [.../* @__PURE__ */ new Set([...allPaths, ...extraScanPaths])];
159
+ forgeScanPaths = uniquePaths.join(":");
160
+ } else {
161
+ const extraScanPaths = (config.host_repos_extra_scan_dirs ?? []).map((d) => d.trim()).filter(Boolean).map((d) => `${baseScanPath}/${d}`);
162
+ forgeScanPaths = [baseScanPath, ...extraScanPaths].join(":");
163
+ }
116
164
  const lines = [
117
165
  "# \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500",
118
166
  "# Horus \u2014 Generated .env file",
@@ -299,6 +347,9 @@ function createRuntime(name) {
299
347
  const result = await execa(bin, ["inspect", "--format", format, container], {
300
348
  reject: false
301
349
  });
350
+ if (result.exitCode !== 0) {
351
+ throw new Error(`inspect failed: ${result.stderr}`);
352
+ }
302
353
  return result.stdout?.toString().trim() ?? "";
303
354
  },
304
355
  async isRunning() {
@@ -315,6 +366,24 @@ function createRuntime(name) {
315
366
  }
316
367
  };
317
368
  }
369
+ function parseComposeJson(output) {
370
+ const trimmed = output.trim();
371
+ if (!trimmed) return [];
372
+ if (trimmed.startsWith("[")) {
373
+ try {
374
+ const parsed = JSON.parse(trimmed);
375
+ if (Array.isArray(parsed)) return parsed;
376
+ } catch {
377
+ }
378
+ }
379
+ return trimmed.split("\n").filter((line) => line.trim()).map((line) => {
380
+ try {
381
+ return JSON.parse(line);
382
+ } catch {
383
+ return null;
384
+ }
385
+ }).filter((item) => item !== null);
386
+ }
318
387
  async function checkRuntime(name) {
319
388
  return tryCommand(name, ["compose", "version"]);
320
389
  }
@@ -358,14 +427,22 @@ async function composeStreaming(runtime, args) {
358
427
 
359
428
  // src/lib/health.ts
360
429
  async function checkContainerHealth(runtime, service) {
361
- const containerName = `horus-${service}-1`;
362
- try {
363
- const status = await runtime.inspect(containerName, "{{.State.Health.Status}}");
364
- const mappedStatus = mapStatus(status);
365
- return { name: service, status: mappedStatus };
366
- } catch {
367
- return { name: service, status: "stopped" };
430
+ const candidates = [`horus-${service}-1`, `horus_${service}_1`];
431
+ for (const containerName of candidates) {
432
+ try {
433
+ const healthStatus = await runtime.inspect(containerName, "{{.State.Health.Status}}");
434
+ if (healthStatus && !healthStatus.includes("<nil>") && healthStatus.trim() !== "") {
435
+ return { name: service, status: mapStatus(healthStatus) };
436
+ }
437
+ const stateStatus = await runtime.inspect(containerName, "{{.State.Status}}");
438
+ if (stateStatus && stateStatus.trim() !== "") {
439
+ return { name: service, status: mapStateStatus(stateStatus) };
440
+ }
441
+ } catch {
442
+ continue;
443
+ }
368
444
  }
445
+ return { name: service, status: "stopped" };
369
446
  }
370
447
  function mapStatus(raw) {
371
448
  switch (raw.trim().toLowerCase()) {
@@ -379,13 +456,28 @@ function mapStatus(raw) {
379
456
  return "unknown";
380
457
  }
381
458
  }
459
+ function mapStateStatus(raw) {
460
+ switch (raw.trim().toLowerCase()) {
461
+ case "running":
462
+ return "healthy";
463
+ case "created":
464
+ case "restarting":
465
+ return "starting";
466
+ case "exited":
467
+ case "dead":
468
+ case "removing":
469
+ return "unhealthy";
470
+ default:
471
+ return "unknown";
472
+ }
473
+ }
382
474
  async function checkAllHealth(runtime) {
383
475
  const results = await Promise.all(
384
476
  SERVICES.map((service) => checkContainerHealth(runtime, service))
385
477
  );
386
478
  return results;
387
479
  }
388
- async function pollUntilHealthy(runtime, onUpdate, timeoutMs = 6e5, intervalMs = 5e3) {
480
+ async function pollUntilHealthy(runtime, onUpdate, timeoutMs = 3e5, intervalMs = 5e3) {
389
481
  const startTime = Date.now();
390
482
  while (true) {
391
483
  const states = await checkAllHealth(runtime);
@@ -401,7 +493,7 @@ async function pollUntilHealthy(runtime, onUpdate, timeoutMs = 6e5, intervalMs =
401
493
  const unhealthyServices = states.filter((s) => s.status === "unhealthy").map((s) => s.name).join(", ");
402
494
  throw new Error(
403
495
  `Services failed health check: ${unhealthyServices}
404
- Run 'docker compose logs <service>' from ~/.horus/ to investigate.`
496
+ Run '${runtime.name} compose logs <service>' from ~/.horus/ to investigate.`
405
497
  );
406
498
  }
407
499
  const elapsed = Date.now() - startTime;
@@ -409,7 +501,7 @@ Run 'docker compose logs <service>' from ~/.horus/ to investigate.`
409
501
  const notReady = states.filter((s) => s.status !== "healthy").map((s) => `${s.name} (${s.status})`).join(", ");
410
502
  throw new Error(
411
503
  `Timed out after ${Math.round(timeoutMs / 1e3)}s waiting for services: ${notReady}
412
- Run 'docker compose logs' from ~/.horus/ to investigate.`
504
+ Run '${runtime.name} compose logs' from ~/.horus/ to investigate.`
413
505
  );
414
506
  }
415
507
  await new Promise((resolve2) => setTimeout(resolve2, intervalMs));
@@ -417,11 +509,11 @@ Run 'docker compose logs' from ~/.horus/ to investigate.`
417
509
  }
418
510
 
419
511
  // src/lib/compose.ts
420
- import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, existsSync as existsSync2 } from "fs";
421
- import { join as join2, dirname } from "path";
422
- import { fileURLToPath } from "url";
423
- var __filename = fileURLToPath(import.meta.url);
424
- var __dirname = dirname(__filename);
512
+ import { readFileSync as readFileSync3, writeFileSync as writeFileSync2, existsSync as existsSync2 } from "fs";
513
+ import { join as join2, dirname as dirname2 } from "path";
514
+ import { fileURLToPath as fileURLToPath2 } from "url";
515
+ var __filename = fileURLToPath2(import.meta.url);
516
+ var __dirname = dirname2(__filename);
425
517
  function getBundledComposePath() {
426
518
  const candidates = [
427
519
  join2(__dirname, "..", "..", "compose", "docker-compose.yml"),
@@ -449,7 +541,7 @@ function composeFileExists() {
449
541
  function installComposeFile(runtime) {
450
542
  ensureHorusDir();
451
543
  const bundledPath = getBundledComposePath();
452
- let content = readFileSync2(bundledPath, "utf-8");
544
+ let content = readFileSync3(bundledPath, "utf-8");
453
545
  if (runtime === "podman") {
454
546
  content = applyPodmanUserOverride(content);
455
547
  }
@@ -461,7 +553,7 @@ import { Command } from "commander";
461
553
  import chalk from "chalk";
462
554
  import ora from "ora";
463
555
  import { checkbox } from "@inquirer/prompts";
464
- import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync2, existsSync as existsSync3 } from "fs";
556
+ import { readFileSync as readFileSync4, writeFileSync as writeFileSync3, mkdirSync as mkdirSync2, existsSync as existsSync3 } from "fs";
465
557
  import { join as join3 } from "path";
466
558
  import { homedir as homedir3 } from "os";
467
559
  import { execa as execa2 } from "execa";
@@ -498,7 +590,7 @@ function mergeAndWriteConfig(configPath, mcpServers) {
498
590
  let existing = {};
499
591
  if (existsSync3(configPath)) {
500
592
  try {
501
- const raw = readFileSync3(configPath, "utf-8");
593
+ const raw = readFileSync4(configPath, "utf-8");
502
594
  existing = JSON.parse(raw);
503
595
  } catch {
504
596
  existing = {};
@@ -821,11 +913,7 @@ var setupCommand = new Command2("setup").description("Interactive first-run setu
821
913
  message: "Host repos path (for Forge repo scanning, leave empty to skip):",
822
914
  default: ""
823
915
  });
824
- const extra_scan_dirs_raw = await input({
825
- message: "Extra subdirectories to scan within repos path (comma-separated, e.g. ArjunKhera \u2014 leave empty to skip):",
826
- default: ""
827
- });
828
- const host_repos_extra_scan_dirs = extra_scan_dirs_raw.split(",").map((d) => d.trim()).filter(Boolean);
916
+ const host_repos_extra_scan_dirs = [];
829
917
  const customize_ports = await confirm({
830
918
  message: "Customize port assignments?",
831
919
  default: false
@@ -939,7 +1027,7 @@ ${example("forge-registry")}
939
1027
  console.error(error.message);
940
1028
  process.exit(1);
941
1029
  }
942
- const dataDir = config.data_dir.startsWith("~") ? join4(process.env.HOME || "", config.data_dir.slice(1)) : config.data_dir;
1030
+ const dataDir = resolvePath(config.data_dir);
943
1031
  const reposToClone = [
944
1032
  { url: config.repos.anvil_notes, dest: join4(dataDir, "notes"), label: "Anvil notes" },
945
1033
  { url: config.repos.vault_knowledge, dest: join4(dataDir, "knowledge-base"), label: "Vault knowledge-base" },
@@ -1173,17 +1261,14 @@ var statusCommand = new Command5("status").description("Show status of Horus ser
1173
1261
  let containers = [];
1174
1262
  try {
1175
1263
  const result = await runtime.compose("ps", "--format", "json");
1176
- const output = result.stdout.trim();
1177
- if (output) {
1178
- containers = output.split("\n").filter((line) => line.trim()).map((line) => JSON.parse(line));
1179
- }
1264
+ containers = parseComposeJson(result.stdout);
1180
1265
  } catch {
1181
1266
  }
1182
1267
  spinner.stop();
1183
1268
  console.log("");
1184
1269
  console.log(chalk5.bold("Horus Status"));
1185
1270
  console.log(chalk5.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
1186
- console.log(` ${chalk5.bold("Version:")} ${config.version}`);
1271
+ console.log(` ${chalk5.bold("Version:")} ${CLI_VERSION}`);
1187
1272
  console.log(` ${chalk5.bold("Runtime:")} ${runtime.name}`);
1188
1273
  console.log(` ${chalk5.bold("Config:")} ~/.horus/config.yaml`);
1189
1274
  console.log("");
@@ -1348,7 +1433,7 @@ import { Command as Command7 } from "commander";
1348
1433
  import chalk7 from "chalk";
1349
1434
  import ora6 from "ora";
1350
1435
  import { select as select2, confirm as confirm3 } from "@inquirer/prompts";
1351
- import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, readdirSync, existsSync as existsSync5 } from "fs";
1436
+ import { readFileSync as readFileSync5, writeFileSync as writeFileSync4, mkdirSync as mkdirSync4, readdirSync as readdirSync2, existsSync as existsSync5 } from "fs";
1352
1437
  import { join as join5 } from "path";
1353
1438
  import { createHash } from "crypto";
1354
1439
  import { stringify as stringifyYaml2, parse as parseYaml2 } from "yaml";
@@ -1358,7 +1443,7 @@ function ensureSnapshotsDir() {
1358
1443
  }
1359
1444
  function composeFileHash() {
1360
1445
  if (!existsSync5(COMPOSE_PATH)) return "";
1361
- const content = readFileSync4(COMPOSE_PATH, "utf-8");
1446
+ const content = readFileSync5(COMPOSE_PATH, "utf-8");
1362
1447
  return createHash("sha256").update(content).digest("hex").slice(0, 12);
1363
1448
  }
1364
1449
  async function captureCurrentImages(runtime) {
@@ -1393,9 +1478,9 @@ function saveSnapshot(images) {
1393
1478
  }
1394
1479
  function listSnapshots() {
1395
1480
  if (!existsSync5(SNAPSHOTS_DIR)) return [];
1396
- return readdirSync(SNAPSHOTS_DIR).filter((f) => f.endsWith(".yaml")).sort().reverse().map((f) => {
1481
+ return readdirSync2(SNAPSHOTS_DIR).filter((f) => f.endsWith(".yaml")).sort().reverse().map((f) => {
1397
1482
  const file = join5(SNAPSHOTS_DIR, f);
1398
- const snapshot = parseYaml2(readFileSync4(file, "utf-8"));
1483
+ const snapshot = parseYaml2(readFileSync5(file, "utf-8"));
1399
1484
  return { file, snapshot };
1400
1485
  });
1401
1486
  }
@@ -1626,41 +1711,38 @@ function colorMessage(status, msg) {
1626
1711
  return chalk8.red(msg);
1627
1712
  }
1628
1713
  }
1629
- async function checkRuntime2() {
1630
- try {
1631
- execSync2("docker info", { stdio: "ignore" });
1632
- return { status: "pass", label: "Runtime", message: "Docker is running" };
1633
- } catch {
1714
+ async function checkRuntimeAvailability(preferred) {
1715
+ const order = preferred === "podman" ? ["podman", "docker"] : ["docker", "podman"];
1716
+ for (const rt of order) {
1634
1717
  try {
1635
- execSync2("podman info", { stdio: "ignore" });
1636
- return { status: "pass", label: "Runtime", message: "Podman is running" };
1718
+ execSync2(`${rt} info`, { stdio: "ignore" });
1719
+ return { status: "pass", label: "Runtime", message: `${rt === "docker" ? "Docker" : "Podman"} is running` };
1637
1720
  } catch {
1638
- return {
1639
- status: "fail",
1640
- label: "Runtime",
1641
- message: "Docker/Podman is not running",
1642
- hint: "Start Docker Desktop or Podman Desktop"
1643
- };
1644
1721
  }
1645
1722
  }
1723
+ return {
1724
+ status: "fail",
1725
+ label: "Runtime",
1726
+ message: "Docker/Podman is not running",
1727
+ hint: "Start Docker Desktop or Podman Desktop"
1728
+ };
1646
1729
  }
1647
- async function checkCompose() {
1648
- try {
1649
- execSync2("docker compose version", { stdio: "ignore" });
1650
- return { status: "pass", label: "Compose", message: "Compose plugin available" };
1651
- } catch {
1730
+ async function checkCompose(preferred) {
1731
+ const order = preferred === "podman" ? ["podman", "docker"] : ["docker", "podman"];
1732
+ for (const rt of order) {
1652
1733
  try {
1653
- execSync2("podman compose version", { stdio: "ignore" });
1654
- return { status: "pass", label: "Compose", message: "Compose plugin available (podman)" };
1734
+ execSync2(`${rt} compose version`, { stdio: "ignore" });
1735
+ const label = rt === "podman" ? "Compose plugin available (podman)" : "Compose plugin available";
1736
+ return { status: "pass", label: "Compose", message: label };
1655
1737
  } catch {
1656
- return {
1657
- status: "fail",
1658
- label: "Compose",
1659
- message: "Compose plugin not found",
1660
- hint: "Install Docker Compose plugin: https://docs.docker.com/compose/install/"
1661
- };
1662
1738
  }
1663
1739
  }
1740
+ return {
1741
+ status: "fail",
1742
+ label: "Compose",
1743
+ message: "Compose plugin not found",
1744
+ hint: "Install Docker Compose plugin or podman-compose"
1745
+ };
1664
1746
  }
1665
1747
  function checkConfig() {
1666
1748
  if (configExists()) {
@@ -1760,8 +1842,8 @@ async function checkServices(runtime) {
1760
1842
  const results = [];
1761
1843
  try {
1762
1844
  const psResult = await runtime.compose("ps", "--format", "json");
1763
- const lines = psResult.stdout.trim().split("\n").filter(Boolean);
1764
- if (lines.length === 0) {
1845
+ const containers = parseComposeJson(psResult.stdout);
1846
+ if (containers.length === 0) {
1765
1847
  return [
1766
1848
  {
1767
1849
  status: "warn",
@@ -1771,17 +1853,10 @@ async function checkServices(runtime) {
1771
1853
  }
1772
1854
  ];
1773
1855
  }
1774
- const containers = lines.map((l) => {
1775
- try {
1776
- return JSON.parse(l);
1777
- } catch {
1778
- return null;
1779
- }
1780
- }).filter((c) => c !== null);
1781
1856
  for (const c of containers) {
1782
- const name = c.Service ?? "unknown";
1857
+ const name = c.Service ?? c.Name ?? "unknown";
1783
1858
  const health = (c.Health || c.State || "unknown").toLowerCase();
1784
- if (health === "healthy" || health === "running") {
1859
+ if (health === "healthy" || health === "running" || health === "up") {
1785
1860
  results.push({ status: "pass", label: `Service: ${name}`, message: `${name} is ${health}` });
1786
1861
  } else if (health === "starting") {
1787
1862
  results.push({
@@ -1814,11 +1889,11 @@ var doctorCommand = new Command8("doctor").description("Diagnose common Horus is
1814
1889
  console.log(chalk8.bold("Horus Doctor"));
1815
1890
  console.log(chalk8.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"));
1816
1891
  const allResults = [];
1817
- allResults.push(await checkRuntime2());
1818
- allResults.push(await checkCompose());
1892
+ const config = configExists() ? loadConfig() : null;
1893
+ allResults.push(await checkRuntimeAvailability(config?.runtime));
1894
+ allResults.push(await checkCompose(config?.runtime));
1819
1895
  allResults.push(checkConfig());
1820
1896
  allResults.push(checkComposeFile());
1821
- const config = configExists() ? loadConfig() : null;
1822
1897
  const ports = config?.ports ?? DEFAULT_PORTS;
1823
1898
  const dataDir = config?.data_dir ?? join6(process.env.HOME ?? "~", ".horus", "data");
1824
1899
  allResults.push(checkPort(ports.anvil, "Anvil"));
@@ -1875,7 +1950,7 @@ import { Command as Command9 } from "commander";
1875
1950
  import chalk9 from "chalk";
1876
1951
  import ora7 from "ora";
1877
1952
  import { confirm as confirm4 } from "@inquirer/prompts";
1878
- import { mkdirSync as mkdirSync5, statSync, existsSync as existsSync7, writeFileSync as writeFileSync5 } from "fs";
1953
+ import { mkdirSync as mkdirSync5, statSync as statSync2, existsSync as existsSync7, writeFileSync as writeFileSync5 } from "fs";
1879
1954
  import { join as join7, basename } from "path";
1880
1955
  import { execSync as execSync3 } from "child_process";
1881
1956
  import { stringify as stringifyYaml3 } from "yaml";
@@ -1943,7 +2018,7 @@ async function createBackup(yes) {
1943
2018
  }
1944
2019
  let sizeBytes = 0;
1945
2020
  try {
1946
- sizeBytes = statSync(tarFile).size;
2021
+ sizeBytes = statSync2(tarFile).size;
1947
2022
  } catch {
1948
2023
  }
1949
2024
  const meta = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arkhera30/cli",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "description": "CLI for managing the Horus AI development stack",
5
5
  "type": "module",
6
6
  "bin": {