lacy 1.7.1 → 1.7.3

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/index.mjs +62 -47
  2. package/package.json +1 -1
package/index.mjs CHANGED
@@ -12,13 +12,38 @@ import {
12
12
  rmSync,
13
13
  } from "fs";
14
14
  import { homedir } from "os";
15
- import { join } from "path";
15
+ import { join, dirname } from "path";
16
+ import { fileURLToPath } from "url";
16
17
 
17
18
  const INSTALL_DIR = join(homedir(), ".lacy");
18
19
  const INSTALL_DIR_OLD = join(homedir(), ".lacy-shell");
19
20
  const CONFIG_FILE = join(INSTALL_DIR, "config.yaml");
20
21
  const REPO_URL = "https://github.com/lacymorrow/lacy.git";
21
22
 
23
+ // Version — read from installed package.json (single source of truth),
24
+ // fall back to this npm package's own package.json
25
+ function getVersion() {
26
+ // Try the installed copy first
27
+ for (const dir of [INSTALL_DIR, INSTALL_DIR_OLD]) {
28
+ const pkgPath = join(dir, "package.json");
29
+ if (existsSync(pkgPath)) {
30
+ try {
31
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
32
+ if (pkg.version) return pkg.version;
33
+ } catch {}
34
+ }
35
+ }
36
+ // Fall back to this package's own version
37
+ try {
38
+ const __dirname = dirname(fileURLToPath(import.meta.url));
39
+ const pkg = JSON.parse(readFileSync(join(__dirname, "package.json"), "utf-8"));
40
+ if (pkg.version) return pkg.version;
41
+ } catch {}
42
+ return "unknown";
43
+ }
44
+
45
+ const VERSION = getVersion();
46
+
22
47
  // ============================================================================
23
48
  // Terminal state safety net
24
49
  // ============================================================================
@@ -220,7 +245,7 @@ function removeLacyFromFile(filePath) {
220
245
  return true;
221
246
  }
222
247
 
223
- // Shared uninstall logic — removes RC lines and install dirs, optionally keeps config
248
+ // Shared uninstall logic — removes RC lines and install dirs completely
224
249
  async function doUninstall({ askConfirm = true } = {}) {
225
250
  if (askConfirm) {
226
251
  const confirm = await p.confirm({
@@ -234,24 +259,6 @@ async function doUninstall({ askConfirm = true } = {}) {
234
259
  }
235
260
  }
236
261
 
237
- // Ask about config
238
- let keepConfig = false;
239
- if (existsSync(CONFIG_FILE)) {
240
- const configChoice = await p.confirm({
241
- message: "Keep configuration for future reinstall?",
242
- initialValue: true,
243
- });
244
- if (!p.isCancel(configChoice)) {
245
- keepConfig = configChoice;
246
- }
247
- }
248
-
249
- // Backup config if keeping
250
- let configBackup = null;
251
- if (keepConfig && existsSync(CONFIG_FILE)) {
252
- configBackup = readFileSync(CONFIG_FILE, "utf-8");
253
- }
254
-
255
262
  // Remove from all possible RC files
256
263
  const rcSpinner = p.spinner();
257
264
  rcSpinner.start("Removing from shell configs");
@@ -280,15 +287,7 @@ async function doUninstall({ askConfirm = true } = {}) {
280
287
  rmSync(INSTALL_DIR_OLD, { recursive: true, force: true });
281
288
  }
282
289
 
283
- // Restore config if keeping
284
- if (configBackup) {
285
- mkdirSync(INSTALL_DIR, { recursive: true });
286
- writeFileSync(CONFIG_FILE, configBackup);
287
- }
288
-
289
- removeSpinner.stop(
290
- configBackup ? "Installation removed (config preserved)" : "Installation removed",
291
- );
290
+ removeSpinner.stop("Installation removed");
292
291
 
293
292
  p.log.success("Lacy Shell uninstalled");
294
293
 
@@ -299,7 +298,7 @@ async function doUninstall({ askConfirm = true } = {}) {
299
298
 
300
299
  async function uninstall() {
301
300
  console.clear();
302
- p.intro(pc.magenta(pc.bold(` Lacy Shell `)));
301
+ p.intro(pc.magenta(pc.bold(` Lacy Shell `)) + pc.dim(` v${VERSION}`));
303
302
 
304
303
  if (!isInstalled()) {
305
304
  p.log.warn("Lacy Shell is not installed");
@@ -318,7 +317,7 @@ async function uninstall() {
318
317
 
319
318
  async function install() {
320
319
  console.clear();
321
- p.intro(pc.magenta(pc.bold(` Lacy Shell `)));
320
+ p.intro(pc.magenta(pc.bold(` Lacy Shell `)) + pc.dim(` v${VERSION}`));
322
321
 
323
322
  // Detect shell
324
323
  const shell = detectShell();
@@ -396,7 +395,7 @@ async function install() {
396
395
 
397
396
  try {
398
397
  if (commandExists("npm")) {
399
- execSync("npm install -g lash-cli", { stdio: "pipe" });
398
+ execSync("npm install -g lashcode", { stdio: "pipe" });
400
399
  lashSpinner.stop("lash installed");
401
400
  detected.push("lash");
402
401
  } else if (commandExists("brew")) {
@@ -408,13 +407,13 @@ async function install() {
408
407
  } else {
409
408
  lashSpinner.stop("Could not install lash");
410
409
  p.log.warn(
411
- "Please install npm or homebrew, then run: npm install -g lash-cli",
410
+ "Please install npm or homebrew, then run: npm install -g lashcode",
412
411
  );
413
412
  }
414
413
  } catch (e) {
415
414
  lashSpinner.stop("lash installation failed");
416
415
  p.log.warn(
417
- "You can install it manually later: npm install -g lash-cli",
416
+ "You can install it manually later: npm install -g lashcode",
418
417
  );
419
418
  }
420
419
  }
@@ -457,10 +456,22 @@ async function install() {
457
456
  p.log.info(`Custom command: ${pc.cyan(customCommand)}`);
458
457
  }
459
458
 
460
- // Offer to install lash if selected but not installed
461
- if (selectedTool === "lash" && !commandExists("lash")) {
459
+ // Show which tool auto-detect resolves to
460
+ if (selectedTool === "auto" && detected.length > 0) {
461
+ p.log.info(`Using: ${pc.green("auto-detect")} (currently: ${pc.green(detected[0])})`);
462
+ }
463
+
464
+ // Offer to install lash if selected but not installed,
465
+ // or if auto-detect was chosen but no tools are available
466
+ const needsLashInstall =
467
+ (selectedTool === "lash" && !commandExists("lash")) ||
468
+ (selectedTool === "auto" && detected.length === 0);
469
+
470
+ if (needsLashInstall) {
462
471
  const installLash = await p.confirm({
463
- message: "lash is not installed. Would you like to install it now?",
472
+ message: selectedTool === "auto"
473
+ ? `No AI CLI tools are installed. Would you like to install ${pc.green("lash")} (recommended)?`
474
+ : "lash is not installed. Would you like to install it now?",
464
475
  initialValue: true,
465
476
  });
466
477
 
@@ -475,7 +486,7 @@ async function install() {
475
486
 
476
487
  try {
477
488
  if (commandExists("npm")) {
478
- execSync("npm install -g lash-cli", { stdio: "pipe" });
489
+ execSync("npm install -g lashcode", { stdio: "pipe" });
479
490
  lashSpinner.stop("lash installed");
480
491
  } else if (commandExists("brew")) {
481
492
  execSync("brew tap lacymorrow/tap && brew install lash", {
@@ -485,13 +496,13 @@ async function install() {
485
496
  } else {
486
497
  lashSpinner.stop("Could not install lash");
487
498
  p.log.warn(
488
- "Please install npm or homebrew, then run: npm install -g lash-cli",
499
+ "Please install npm or homebrew, then run: npm install -g lashcode",
489
500
  );
490
501
  }
491
502
  } catch (e) {
492
503
  lashSpinner.stop("lash installation failed");
493
504
  p.log.warn(
494
- "You can install it manually later: npm install -g lash-cli",
505
+ "You can install it manually later: npm install -g lashcode",
495
506
  );
496
507
  }
497
508
  }
@@ -616,8 +627,11 @@ auto_detection:
616
627
  configSpinner.stop("Configuration created");
617
628
  }
618
629
 
630
+ // Re-read version after install (repo was just cloned/updated)
631
+ const installedVersion = getVersion();
632
+
619
633
  // Success message
620
- p.log.success(pc.green("Installation complete!"));
634
+ p.log.success(pc.green(`Installation complete!`) + pc.dim(` v${installedVersion}`));
621
635
 
622
636
  p.note(
623
637
  `${pc.cyan("what files are here")} ${pc.dim("→ AI answers")}
@@ -636,7 +650,7 @@ Commands:
636
650
  (selectedTool === "auto" && detected.length === 0)
637
651
  ) {
638
652
  p.log.warn("Remember to install an AI CLI tool:");
639
- console.log(` ${pc.cyan("npm install -g lash-cli")}`);
653
+ console.log(` ${pc.cyan("npm install -g lashcode")}`);
640
654
  }
641
655
 
642
656
  await restartShell();
@@ -658,7 +672,7 @@ async function main() {
658
672
  const content = readFileSync(infoPath, "utf-8");
659
673
  console.log(content);
660
674
  } else {
661
- console.log(`\n${pc.magenta(pc.bold("🔧 Lacy Shell"))} v${require("./package.json").version || "1.6.5"}\n`);
675
+ console.log(`\n${pc.magenta(pc.bold("🔧 Lacy Shell"))} v${VERSION}\n`);
662
676
  console.log("Lacy Shell detects natural language and routes it to AI coding agents.\n");
663
677
  console.log("Quick tips:");
664
678
  console.log(" • Type normally for shell commands");
@@ -683,7 +697,7 @@ async function main() {
683
697
 
684
698
  if (args.includes("--help") || args.includes("-h")) {
685
699
  console.log(`
686
- ${pc.magenta(pc.bold("Lacy Shell"))} - Talk directly to your shell
700
+ ${pc.magenta(pc.bold("Lacy Shell"))} ${pc.dim(`v${VERSION}`)} - Talk directly to your shell
687
701
 
688
702
  ${pc.bold("Usage:")}
689
703
  npx lacy Install Lacy Shell
@@ -710,7 +724,7 @@ ${pc.dim("https://github.com/lacymorrow/lacy")}
710
724
  // If already installed, show dashboard + menu
711
725
  if (isInstalled()) {
712
726
  console.clear();
713
- p.intro(pc.magenta(pc.bold(` Lacy Shell `)));
727
+ p.intro(pc.magenta(pc.bold(` Lacy Shell `)) + pc.dim(` v${VERSION}`));
714
728
 
715
729
  // Show current status
716
730
  const active = readConfigValue("active");
@@ -870,7 +884,7 @@ ${pc.dim("https://github.com/lacymorrow/lacy")}
870
884
 
871
885
  const lines = [
872
886
  ` Installed: ${pc.green(dir)}`,
873
- sha ? ` Version: git ${pc.dim(sha)}` : null,
887
+ ` Version: ${pc.cyan("v" + VERSION)}${sha ? pc.dim(` (${sha})`) : ""}`,
874
888
  ` Shell: ${pc.cyan(shell)} ${rcConfigured ? pc.green("configured") : pc.yellow("not configured")}`,
875
889
  ` Config: ${hasConfig ? pc.green("exists") : pc.yellow("missing")}`,
876
890
  ` Tool: ${pc.cyan(active || "auto-detect")}`,
@@ -901,7 +915,8 @@ ${pc.dim("https://github.com/lacymorrow/lacy")}
901
915
  : INSTALL_DIR_OLD;
902
916
  try {
903
917
  execSync("git pull origin main", { cwd: updateDir, stdio: "pipe" });
904
- updateSpinner.stop("Lacy updated");
918
+ const updatedVersion = getVersion();
919
+ updateSpinner.stop(`Lacy updated to v${updatedVersion}`);
905
920
  p.log.success("Update complete!");
906
921
  await restartShell();
907
922
  p.outro("Restart your terminal to apply changes.");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lacy",
3
- "version": "1.7.1",
3
+ "version": "1.7.3",
4
4
  "description": "Install lacy — talk to your terminal",
5
5
  "type": "module",
6
6
  "bin": {