firstrun: track omaterm install changes — drop redundant AI-agent step, run OMATERM last

omaterm.org/install now installs the AI agents itself (node/opencode/
claude-code/codex/gemini are in its mise.packages) and its installer ends
with `exec bash -l`, which re-sources ~/.bash_profile.

- Remove our now-redundant "Install AI agents via mise" prompt and its
  stale comment (omaterm provides them).
- Guard against the re-sourced .bash_profile re-firing the welcome: the
  firstrun script removes itself up-front, so the one-shot stays one-shot.
- Reorder so OMATERM runs last (Once + Omarchy-Send first), since its
  `exec bash -l` hijacks the shell and drops the user into their session.
- Update welcome banner + in-script docs to list the bundled AI agents
  and the new ordering. Also gitignore build.log.

Verified: pty-backed logic harness (ordering, one-shot, no recursion) and
a full VM boot of the rebuilt ISO (welcome + Once-first + clean no-recursion
shell on omaterm's failure path).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
28allday 2026-05-29 15:54:53 +01:00
parent ac6f23ded5
commit 3cb0c3e0ed
2 changed files with 36 additions and 54 deletions

1
.gitignore vendored
View file

@ -5,3 +5,4 @@ omalocal-arch-*.iso
omaterm-arch-*.iso omaterm-arch-*.iso
*.ppm *.ppm
*.png *.png
build.log

View file

@ -364,8 +364,12 @@ chmod 644 /mnt/etc/profile.d/mise-shims.sh
echo "==> Installing omalocal first-login prompt for $USERNAME..." echo "==> Installing omalocal first-login prompt for $USERNAME..."
cat > "/mnt/home/$USERNAME/.omalocal-firstrun.sh" <<'OMALOCAL_FIRSTRUN' cat > "/mnt/home/$USERNAME/.omalocal-firstrun.sh" <<'OMALOCAL_FIRSTRUN'
#!/usr/bin/env bash #!/usr/bin/env bash
# Shown once, on first interactive login. The .bash_profile hook removes this # Shown once, on first interactive login. Remove ourselves up-front: OMATERM's
# file after it runs, so the prompt never appears again. # installer ends with `exec bash -l`, which re-sources ~/.bash_profile. If this
# file still existed at that point the first-run hook would re-fire and we'd
# recurse into the welcome prompt. Deleting it now (rather than letting the
# .bash_profile hook delete it after we return) makes the prompt strictly once.
rm -f "$HOME/.omalocal-firstrun.sh"
clear clear
cat <<'BANNER' cat <<'BANNER'
@ -379,7 +383,8 @@ cat <<'BANNER'
Setting up the server installs two things: Setting up the server installs two things:
OMATERM — a terminal-first toolkit: starship, neovim, tmux, OMATERM — a terminal-first toolkit: starship, neovim, tmux,
mise, docker, lazygit, claude-code, yay, etc. mise, docker, lazygit, yay, plus AI agents
(claude-code, codex, opencode, gemini), etc.
Once — Basecamp's self-hosted app deployment platform. Once — Basecamp's self-hosted app deployment platform.
Optional extra: Optional extra:
@ -394,61 +399,24 @@ cat <<'BANNER'
BANNER BANNER
setup_server=0
read -rp " Set up this server (OMATERM + Once) now? [Y/n] " ans </dev/tty read -rp " Set up this server (OMATERM + Once) now? [Y/n] " ans </dev/tty
case "$ans" in case "$ans" in
[Nn]*) [Nn]*)
echo echo
echo " Skipped. To set up later, run:" echo " Skipped. To set up later, run:"
echo " curl -fsSL https://omaterm.org/install | bash"
echo " curl https://get.once.com | ONCE_INTERACTIVE=false sh" echo " curl https://get.once.com | ONCE_INTERACTIVE=false sh"
echo " curl -fsSL https://omaterm.org/install | bash"
echo echo
;; ;;
*) *)
setup_server=1
# Install Once FIRST. OMATERM is deferred to the very end of this script
# because its installer finishes with `exec bash -l`, hijacking this shell
# and dropping the user straight into their new tmux session — nothing after
# that call would ever run. So Once (and Omarchy-Send below) go first.
echo echo
echo " [1/2] Installing OMATERM..." echo " [1/2] Installing Once..."
omaterm_ok=0
if curl -fsSL https://omaterm.org/install | bash; then
echo " OMATERM installed."
omaterm_ok=1
else
echo " OMATERM install did not complete — retry later with:"
echo " curl -fsSL https://omaterm.org/install | bash"
fi
# AI agents (opencode, claude-code, codex, gemini) are NOT installed by the
# bare-metal omaterm.org installer — they're mise tools that only the Docker
# image bakes in. Offer to add them here via mise. mise itself comes with
# OMATERM (pacman), so it's on PATH even before this shell sources its hooks.
# gemini (@google/gemini-cli) is an npm package, so it needs Node — which the
# bare-metal OMATERM install does NOT provide. Install node@latest first or
# gemini fails with "npm not found"; the other three are standalone binaries.
if [ "$omaterm_ok" = 1 ] && command -v mise >/dev/null 2>&1; then
echo
read -rp " Install AI agents (opencode, claude-code, codex, gemini) via mise? [Y/n] " ans </dev/tty
case "$ans" in
[Nn]*)
echo " Skipped. Add later with: mise use -g node@latest opencode claude-code codex gemini"
;;
*)
echo " Installing agents (this can take a while)..."
# node@latest first: gemini-cli is npm-based and needs it.
if mise use -g -y node@latest opencode claude-code codex gemini; then
# Generate shims so claude/codex/opencode/gemini land on PATH (the
# /etc/profile.d/mise-shims.sh snippet adds the shims dir next login).
mise reshim 2>/dev/null || true
echo " Agents installed."
echo " Runnable as: claude, codex, opencode, gemini"
echo " (start a fresh shell / re-login to pick them up on PATH)"
else
echo " Some agents did not install — retry later with:"
echo " mise use -g node@latest opencode claude-code codex gemini"
fi
;;
esac
fi
echo
echo " [2/2] Installing Once..."
if curl https://get.once.com | ONCE_INTERACTIVE=false sh; then if curl https://get.once.com | ONCE_INTERACTIVE=false sh; then
echo " Once installed." echo " Once installed."
else else
@ -467,10 +435,6 @@ case "$ans" in
echo " once-add book ghcr.io/basecamp/writebook # non-interactive" echo " once-add book ghcr.io/basecamp/writebook # non-interactive"
echo " -> reachable at http://book.local from any machine on the LAN." echo " -> reachable at http://book.local from any machine on the LAN."
echo " Use a single-label name; it serves over http:// (no TLS on a LAN box)." echo " Use a single-label name; it serves over http:// (no TLS on a LAN box)."
echo
echo " Done. Start a fresh shell to pick up OMATERM's changes."
echo
;; ;;
esac esac
@ -499,6 +463,23 @@ case "$ans" in
echo echo
;; ;;
esac esac
# OMATERM goes LAST. Its installer (omaterm.org/install) ends with `exec bash -l`,
# which replaces this shell and drops the user into their configured tmux session
# — so nothing after this call would run, which is exactly why it's the closer.
# OMATERM now also installs the AI agents itself (node, opencode, claude-code,
# codex, gemini are in its mise.packages), so there's no separate agent step.
if [ "$setup_server" = 1 ]; then
echo
echo " [2/2] Installing OMATERM (toolkit + AI agents: claude-code, codex,"
echo " opencode, gemini)... when it finishes you'll be dropped straight"
echo " into your new shell."
echo
curl -fsSL https://omaterm.org/install | bash || {
echo " OMATERM install did not complete — retry later with:"
echo " curl -fsSL https://omaterm.org/install | bash"
}
fi
OMALOCAL_FIRSTRUN OMALOCAL_FIRSTRUN
# Append the one-shot hook. Only fires on an interactive login shell, and only # Append the one-shot hook. Only fires on an interactive login shell, and only
@ -680,10 +661,10 @@ Installed by `omalocal.sh`, a single-script patcher that takes a stock Arch ISO
- **Bootloader**: systemd-boot at `/boot/loader/`. - **Bootloader**: systemd-boot at `/boot/loader/`.
- **Login banner**: `/etc/issue` shows hostname + IPv4 + ssh hint above the console login prompt. - **Login banner**: `/etc/issue` shows hostname + IPv4 + ssh hint above the console login prompt.
On the user's first interactive login a self-removing `~/.bash_profile` hook offers to set up the server, which installs two things back-to-back: On the user's first interactive login a self-removing `~/.bash_profile` hook offers to set up the server. Once is installed first; OMATERM is installed last because its installer ends with `exec bash -l` and drops the user straight into their new shell:
- **Omaterm** (https://omaterm.org)`curl -fsSL https://omaterm.org/install | bash` — terminal-first toolkit: starship, neovim, tmux, mise, docker, lazygit, claude-code, yay, etc.
- **Once** (https://once.com)`curl https://get.once.com | ONCE_INTERACTIVE=false sh` — Basecamp's self-hosted app deployment platform. - **Once** (https://once.com)`curl https://get.once.com | ONCE_INTERACTIVE=false sh` — Basecamp's self-hosted app deployment platform.
- **Omaterm** (https://omaterm.org)`curl -fsSL https://omaterm.org/install | bash` — terminal-first toolkit: starship, neovim, tmux, mise, docker, lazygit, yay, plus AI agents (claude-code, codex, opencode, gemini), etc. OMATERM installs the AI agents itself (they're in its `mise.packages`), so there's no separate agent step.
If the user declined, install them manually with those same two commands. If the user declined, install them manually with those same two commands.