lacy 1.8.25 → 1.8.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/index.mjs +48 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@ npx lacy
|
|
|
11
11
|
- Installs the latest Lacy Shell release into `~/.lacy` and adds it to your zsh, Bash or fish config
|
|
12
12
|
- Uses your AI CLI tool without asking when exactly one is installed
|
|
13
13
|
- Asks which one to use when several are installed
|
|
14
|
-
- Offers to install
|
|
14
|
+
- Offers to install Claude Code when none is found
|
|
15
15
|
- Asks nothing when there is no terminal (CI, Docker)
|
|
16
16
|
|
|
17
17
|
Run `npx lacy` again after installing to change the tool or mode, edit the config, update, reinstall, or uninstall. Without a terminal it updates to the latest release instead.
|
|
@@ -49,7 +49,7 @@ $ git status runs in shell
|
|
|
49
49
|
? fix the build error AI answers
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
Works with lash, claude, opencode, gemini, codex, hermes, copilot, goose,
|
|
52
|
+
Works with lash, claude, opencode, gemini, codex, hermes, copilot, goose, aider, or a custom command.
|
|
53
53
|
|
|
54
54
|
## Other install methods
|
|
55
55
|
|
package/index.mjs
CHANGED
|
@@ -39,21 +39,33 @@ const GIT_ENV = { ...process.env, GIT_TERMINAL_PROMPT: "0" };
|
|
|
39
39
|
const STATE_FILES = ["config.yaml", "current_mode", "logs", ".last_session", ".server.pid"];
|
|
40
40
|
|
|
41
41
|
// Keep in sync with LACY_TOOL_LIST in lib/core/constants.sh (tests check).
|
|
42
|
-
const TOOL_LIST = ["
|
|
42
|
+
const TOOL_LIST = ["claude", "lash", "opencode", "gemini", "codex", "hermes", "copilot", "goose", "aider"];
|
|
43
43
|
|
|
44
44
|
const TOOL_HINTS = {
|
|
45
|
-
lash: "AI coding agent, lash.lacy.sh
|
|
46
|
-
claude: "Claude Code CLI",
|
|
45
|
+
lash: "AI coding agent, lash.lacy.sh",
|
|
46
|
+
claude: "Claude Code CLI (recommended)",
|
|
47
47
|
opencode: "OpenCode CLI",
|
|
48
48
|
gemini: "Google Gemini CLI",
|
|
49
49
|
codex: "OpenAI Codex CLI",
|
|
50
50
|
hermes: "Hermes Agent by Nous Research",
|
|
51
51
|
copilot: "GitHub Copilot CLI",
|
|
52
52
|
goose: "Goose agent by Block",
|
|
53
|
-
amp: "Sourcegraph Amp CLI",
|
|
54
53
|
aider: "Aider pair programming",
|
|
55
54
|
};
|
|
56
55
|
|
|
56
|
+
// Keep in sync with lacy_tool_install_cmd in lib/core/mcp.sh (tests check).
|
|
57
|
+
const INSTALL_CMDS = {
|
|
58
|
+
lash: "npm install -g lashcode",
|
|
59
|
+
claude: "npm install -g @anthropic-ai/claude-code",
|
|
60
|
+
opencode: "npm install -g opencode-ai",
|
|
61
|
+
gemini: "npm install -g @google/gemini-cli",
|
|
62
|
+
codex: "npm install -g @openai/codex",
|
|
63
|
+
hermes: "curl -fsSL https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh | bash",
|
|
64
|
+
copilot: "npm install -g @github/copilot",
|
|
65
|
+
goose: "brew install block-goose-cli",
|
|
66
|
+
aider: "pipx install aider-chat",
|
|
67
|
+
};
|
|
68
|
+
|
|
57
69
|
const MODES = [
|
|
58
70
|
{ value: "auto", label: "Auto", hint: "smart detection (recommended)" },
|
|
59
71
|
{ value: "shell", label: "Shell", hint: "all commands execute directly" },
|
|
@@ -282,7 +294,7 @@ function defaultConfig(active = "", customCommand = "") {
|
|
|
282
294
|
: ' # custom_command: "your-command --flags"';
|
|
283
295
|
return `# Lacy Shell configuration
|
|
284
296
|
agent_tools:
|
|
285
|
-
# lash, claude, opencode, gemini, codex, hermes, copilot, goose,
|
|
297
|
+
# lash, claude, opencode, gemini, codex, hermes, copilot, goose, aider, custom
|
|
286
298
|
# Leave empty to auto-detect.
|
|
287
299
|
${activeLine}
|
|
288
300
|
${customLine}
|
|
@@ -293,6 +305,7 @@ modes:
|
|
|
293
305
|
# preheat:
|
|
294
306
|
# eager: false
|
|
295
307
|
# server_port: 4096
|
|
308
|
+
# claude_idle_minutes: 15 # keep claude running between questions; 0 turns it off
|
|
296
309
|
|
|
297
310
|
# logging:
|
|
298
311
|
# queries: false # true writes ~/.lacy/logs/queries.log (owner-only)
|
|
@@ -515,27 +528,27 @@ function checkPrerequisites(shell) {
|
|
|
515
528
|
return missing;
|
|
516
529
|
}
|
|
517
530
|
|
|
518
|
-
function
|
|
531
|
+
function installClaude() {
|
|
519
532
|
const s = spinner();
|
|
520
|
-
s.start("Installing
|
|
533
|
+
s.start("Installing Claude Code");
|
|
521
534
|
try {
|
|
522
535
|
if (commandExists("npm")) {
|
|
523
|
-
execSync(
|
|
536
|
+
execSync(INSTALL_CMDS.claude, { stdio: "pipe" });
|
|
524
537
|
} else if (commandExists("brew")) {
|
|
525
|
-
execSync("brew
|
|
538
|
+
execSync("brew install --cask claude-code", { stdio: "pipe" });
|
|
526
539
|
} else {
|
|
527
|
-
s.stop("Could not install
|
|
540
|
+
s.stop("Could not install Claude Code: npm or Homebrew is needed");
|
|
528
541
|
return false;
|
|
529
542
|
}
|
|
530
543
|
} catch {
|
|
531
|
-
s.stop("
|
|
544
|
+
s.stop("Claude Code did not install");
|
|
532
545
|
return false;
|
|
533
546
|
}
|
|
534
|
-
s.stop("
|
|
535
|
-
return commandExists("
|
|
547
|
+
s.stop("Claude Code installed. Sign in once by running: claude");
|
|
548
|
+
return commandExists("claude");
|
|
536
549
|
}
|
|
537
550
|
|
|
538
|
-
// One tool installed: use it. None: offer
|
|
551
|
+
// One tool installed: use it. None: offer Claude Code. Several: ask which.
|
|
539
552
|
// Without a terminal nothing is asked and the default is used.
|
|
540
553
|
async function chooseTool() {
|
|
541
554
|
const detected = detectTools();
|
|
@@ -556,18 +569,18 @@ async function chooseTool() {
|
|
|
556
569
|
}
|
|
557
570
|
|
|
558
571
|
if (!isInteractive()) {
|
|
559
|
-
p.log.warn(
|
|
572
|
+
p.log.warn(`No AI CLI tool found. Install one later, for example: ${INSTALL_CMDS.claude}`);
|
|
560
573
|
return "";
|
|
561
574
|
}
|
|
562
575
|
|
|
563
576
|
p.log.warn("No AI CLI tool found. Lacy needs one to answer questions.");
|
|
564
577
|
const yes = await p.confirm({
|
|
565
|
-
message: `Install ${pc.green("
|
|
578
|
+
message: `Install ${pc.green("Claude Code")} (claude)?`,
|
|
566
579
|
initialValue: true,
|
|
567
580
|
});
|
|
568
581
|
if (p.isCancel(yes)) cancelled("Installation cancelled");
|
|
569
|
-
if (yes &&
|
|
570
|
-
p.log.info(
|
|
582
|
+
if (yes && installClaude()) return "claude";
|
|
583
|
+
p.log.info(`Install one later, for example: ${INSTALL_CMDS.claude}`);
|
|
571
584
|
return "";
|
|
572
585
|
}
|
|
573
586
|
|
|
@@ -727,6 +740,23 @@ async function dashboard() {
|
|
|
727
740
|
writeConfigValue("active", "");
|
|
728
741
|
p.log.success(`Tool set to: ${pc.cyan("auto-detect")}`);
|
|
729
742
|
} else {
|
|
743
|
+
// Every query would fail with a missing tool: offer to install it
|
|
744
|
+
if (!commandExists(selectedTool)) {
|
|
745
|
+
const cmd = INSTALL_CMDS[selectedTool];
|
|
746
|
+
const install = await p.confirm({
|
|
747
|
+
message: `${selectedTool} is not installed. Install it now? (${cmd})`,
|
|
748
|
+
});
|
|
749
|
+
if (p.isCancel(install) || !install) {
|
|
750
|
+
p.log.error(`${selectedTool} is not installed, so the tool was not changed.`);
|
|
751
|
+
continue;
|
|
752
|
+
}
|
|
753
|
+
const result = spawnSync("sh", ["-c", cmd], { stdio: "inherit" });
|
|
754
|
+
if (result.status !== 0 || !commandExists(selectedTool)) {
|
|
755
|
+
p.log.error(`Installing ${selectedTool} failed, so the tool was not changed. To try it yourself: ${cmd}`);
|
|
756
|
+
continue;
|
|
757
|
+
}
|
|
758
|
+
p.log.success(`${selectedTool} installed. If it asks you to sign in, run: ${selectedTool}`);
|
|
759
|
+
}
|
|
730
760
|
writeConfigValue("active", selectedTool);
|
|
731
761
|
p.log.success(`Tool set to: ${pc.cyan(selectedTool)}`);
|
|
732
762
|
}
|