Skip to content

Commit aa4e658

Browse files
committed
AI CLIs: fix resolver returning early on empty + add nodejs/npm/nano/npm_globals to [packages.ai]
Operator-flagged 2026-05-10: ╰─❯ gemini -bash: gemini: command not found ╰─❯ claude -bash: claude: command not found ╰─❯ nano mios.toml -bash: nano: command not found Two coupled bugs + a missing-pkg: 1. install-ai-clis.sh's _resolve_npm_globals() short-circuited on empty awk output. The form `awk | grep | tr && return 0` always returns 0 because tr (last cmd in pipe) exits 0 regardless of input. Result: function exits without echoing the vendor fallback, install loop sees EOF from while-read, no packages ever get `npm install -g`'d. Fix: capture pipe output into a var and `[ -n "$extracted" ] && echo "$extracted" && return 0`. Only return EARLY when output actually exists; otherwise fall through to the vendor fallback (claude-code + gemini-cli). 2. mios.git's /usr/share/mios/mios.toml [packages.ai] section was missing the nodejs + npm packages + npm_globals list. (mios-bootstrap had them but the runtime resolver reads mios.git's copy because / IS mios.git's working tree.) Added: pkgs: + nodejs + npm + nano npm_globals: ["@anthropic-ai/claude-code", "@google/gemini-cli"] 3. nano: added to [packages.ai].pkgs since the dev VM ships without a baseline text editor and operators need to edit mios.toml from the terminal. Operator-flagged: "nano: command not found". Verified live 2026-05-10: after deploying the fixed script + running it manually on the running dev VM, claude + gemini binstubs landed at /usr/local/bin/{claude,gemini} as expected.
1 parent 9154abf commit aa4e658

2 files changed

Lines changed: 26 additions & 5 deletions

File tree

usr/libexec/mios/install-ai-clis.sh

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,22 +29,26 @@ fi
2929
# Vendor fallback if the toml lookup fails: the two operator-canonical
3030
# AI CLIs.
3131
_resolve_npm_globals() {
32-
local toml
32+
local toml extracted
3333
for toml in \
3434
"${HOME:-/var/home/mios}/.config/mios/mios.toml" \
3535
/etc/mios/mios.toml \
3636
/usr/share/mios/mios.toml; do
3737
[ -r "$toml" ] || continue
3838
# Extract npm_globals = [ "...", "..." ] from [packages.ai] section.
39-
awk '
39+
# Capture into a var so we can check if any content was produced.
40+
# Previous form `awk | grep | tr && return 0` always returned 0
41+
# because tr (last cmd in the pipe) exits 0 on empty input -- the
42+
# function short-circuited before reaching the vendor fallback,
43+
# leaving the install loop with zero packages to install.
44+
extracted=$(awk '
4045
/^\[/ {
4146
line=$0; sub(/[[:space:]]*#.*$/, "", line)
4247
in_ai = (line == "[packages.ai]") ? 1 : 0
4348
next
4449
}
4550
in_ai && /^[[:space:]]*npm_globals[[:space:]]*=[[:space:]]*\[/ {
4651
capturing = 1
47-
# On the same line?
4852
if (match($0, /\[.*\]/)) {
4953
body = substr($0, RSTART+1, RLENGTH-2)
5054
print body
@@ -55,9 +59,14 @@ _resolve_npm_globals() {
5559
}
5660
capturing { buf = buf $0 "\n" }
5761
capturing && /^[[:space:]]*\][[:space:]]*$/ { print buf; capturing = 0; in_ai = 0; exit }
58-
' "$toml" | grep -oE '"[^"]+"' | tr -d '"' && return 0
62+
' "$toml" | grep -oE '"[^"]+"' | tr -d '"')
63+
if [ -n "$extracted" ]; then
64+
echo "$extracted"
65+
return 0
66+
fi
5967
done
60-
# Vendor fallback
68+
# Vendor fallback -- claude-code + gemini-cli are the operator-canonical
69+
# AI CLIs (defaults ON per mios.toml [packages.ai].npm_globals).
6170
echo "@anthropic-ai/claude-code"
6271
echo "@google/gemini-cli"
6372
}

usr/share/mios/mios.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1380,6 +1380,18 @@ pkgs = [
13801380
enable = true # default ON; toggle via /configurator.html (configurator.packages.<section>.enable)
13811381
pkgs = [
13821382
"python3-openai",
1383+
"nodejs", # required by claude-code + gemini-cli (npm-installed)
1384+
"npm",
1385+
"nano", # baseline text editor for operator config edits (operator-flagged: "nano: command not found")
1386+
]
1387+
# AI assistant CLIs installed globally via npm. ON by default --
1388+
# operator can remove from this list to skip. Each entry is an npm
1389+
# package id (passed to `npm install -g`). Installed by
1390+
# /usr/libexec/mios/install-ai-clis.sh which runs during the overlay
1391+
# phase (build-mios.ps1) and is operator-re-runnable any time.
1392+
npm_globals = [
1393+
"@anthropic-ai/claude-code", # Anthropic Claude Code CLI
1394+
"@google/gemini-cli", # Google Gemini CLI
13831395
]
13841396

13851397
[packages.critical]

0 commit comments

Comments
 (0)