From ba36629cdc2bf0b71781935d384f0ae795993dd5 Mon Sep 17 00:00:00 2001 From: Andre Padez Date: Wed, 4 Mar 2026 18:05:50 +0000 Subject: [PATCH] better startup scripts --- scripts/setup-pty-sidecar.sh | 19 +-- scripts/setup.sh | 282 +++++++++++++++++++++-------------- scripts/starship.toml | 45 ++++++ 3 files changed, 222 insertions(+), 124 deletions(-) create mode 100644 scripts/starship.toml diff --git a/scripts/setup-pty-sidecar.sh b/scripts/setup-pty-sidecar.sh index 5cfad01a..cb0ac1b8 100755 --- a/scripts/setup-pty-sidecar.sh +++ b/scripts/setup-pty-sidecar.sh @@ -36,11 +36,6 @@ echo "" echo "── PTY Sidecar (systemd service) ──" echo " Node: $NODE_BIN ($("$NODE_BIN" -v))" -if systemctl is-active --quiet "$SERVICE_NAME" 2>/dev/null; then - skip "$SERVICE_NAME service already running" - exit 0 -fi - sudo tee "$SERVICE_FILE" > /dev/null << EOF [Unit] Description=Officer PTY Sidecar @@ -60,10 +55,16 @@ WantedBy=multi-user.target EOF sudo systemctl daemon-reload -sudo systemctl enable --now "$SERVICE_NAME" +sudo systemctl enable "$SERVICE_NAME" -if systemctl is-active --quiet "$SERVICE_NAME"; then - ok "$SERVICE_NAME service installed and running" +if systemctl is-active --quiet "$SERVICE_NAME" 2>/dev/null; then + sudo systemctl restart "$SERVICE_NAME" + ok "$SERVICE_NAME service updated and restarted" else - warn "$SERVICE_NAME service failed to start — check 'journalctl -u $SERVICE_NAME'" + sudo systemctl start "$SERVICE_NAME" + if systemctl is-active --quiet "$SERVICE_NAME"; then + ok "$SERVICE_NAME service installed and running" + else + warn "$SERVICE_NAME service failed to start — check 'journalctl -u $SERVICE_NAME'" + fi fi diff --git a/scripts/setup.sh b/scripts/setup.sh index a92cc104..0756bb1d 100755 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -95,6 +95,15 @@ if has make && has gcc; then skip "build tools (make, gcc, g++)"; else esac fi +# pkg-config — needed by cgo-based Go packages (e.g. ebitengine/oto for cliamp) +if has pkg-config; then skip "pkg-config"; else + case $PM in + apt) CORE_PKGS+=(pkg-config) ;; + pacman) CORE_PKGS+=(pkgconf) ;; + brew) CORE_PKGS+=(pkg-config) ;; + esac +fi + # python3 + pip + venv if has python3; then skip "python3"; else case $PM in @@ -270,130 +279,139 @@ else skip "sleep targets already masked" fi -# Configure logind to ignore idle -sudo tee /etc/systemd/logind.conf > /dev/null << 'LOGIND_EOF' -[Login] -HandleLidSwitch=ignore -HandleLidSwitchExternalPower=ignore -HandlePowerKey=ignore -IdleAction=none -RuntimeDirectorySize=10% -LOGIND_EOF +# Configure logind to ignore idle — patch individual keys, don't overwrite the file +set_logind_key() { + local key="$1" val="$2" file="/etc/systemd/logind.conf" + if grep -qE "^${key}=" "$file" 2>/dev/null; then + sudo sed -i "s|^${key}=.*|${key}=${val}|" "$file" + elif grep -qE "^#${key}=" "$file" 2>/dev/null; then + sudo sed -i "s|^#${key}=.*|${key}=${val}|" "$file" + else + echo "${key}=${val}" | sudo tee -a "$file" > /dev/null + fi +} + +set_logind_key HandleLidSwitch ignore +set_logind_key HandleLidSwitchExternalPower ignore +set_logind_key HandlePowerKey ignore +set_logind_key IdleAction none +set_logind_key RuntimeDirectorySize 10% sudo systemctl restart systemd-logind ok "Configured logind to disable auto-suspend" -# ─── 5. Node.js 22 ──────────────────────────────────────────────────────────── +# ─── 5. Node.js 22 (system-wide) ───────────────────────────────────────────── echo "" echo "── Node.js 22 (system-wide) ──" -if has node; then - NODE_VER=$(node -v 2>/dev/null | tr -d 'v') - NODE_MAJOR=$(echo "$NODE_VER" | cut -d. -f1) - if [ "$NODE_MAJOR" = "22" ]; then - skip "node v$NODE_VER (system-wide)" - else - warn "Node $NODE_VER found but v22 is required — upgrading..." - case $PM in - apt) - echo " Setting up NodeSource repository..." - curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - - sudo apt-get install -y nodejs - if has node && [ "$(node -v | cut -d. -f1 | tr -d 'v')" = "22" ]; then - ok "Upgraded to node v$(node -v)" - else - fail "Node.js upgrade failed" +# Always check the canonical system path, not `which node` (which may resolve nvm). +SYSTEM_NODE="/usr/bin/node" + +install_node22_apt() { + echo " Setting up NodeSource repository..." + curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - + echo " Installing nodejs..." + sudo apt-get install -y nodejs +} + +case $PM in + apt) + NEED_INSTALL=0 + if [ -f "$SYSTEM_NODE" ]; then + SYS_MAJOR=$("$SYSTEM_NODE" -v 2>/dev/null | cut -d. -f1 | tr -d 'v') + if [ "$SYS_MAJOR" = "22" ]; then + skip "node v$("$SYSTEM_NODE" -v) (system-wide at $SYSTEM_NODE)" + else + warn "System node v$("$SYSTEM_NODE" -v) at $SYSTEM_NODE is not v22 — upgrading..." + NEED_INSTALL=1 + fi + else + if has node; then + warn "node found at $(which node) (not system-wide, likely nvm) — installing Node 22 system-wide..." + else + echo " Node.js not found — installing v22..." + fi + NEED_INSTALL=1 + fi + if [ "$NEED_INSTALL" = "1" ]; then + install_node22_apt + if [ -f "$SYSTEM_NODE" ] && [ "$("$SYSTEM_NODE" -v 2>/dev/null | cut -d. -f1 | tr -d 'v')" = "22" ]; then + ok "node v$("$SYSTEM_NODE" -v) installed at $SYSTEM_NODE" + if has node && [ "$(which node)" != "$SYSTEM_NODE" ]; then + warn "Shell resolves 'node' to $(which node) — system node is at $SYSTEM_NODE" + warn "nvm may shadow it in interactive shells; systemd services will use $SYSTEM_NODE" fi - ;; - pacman) - install_pkg nodejs npm - if has node; then ok "node v$(node -v) installed"; else fail "node install failed"; fi - ;; - brew) - install_pkg node - if has node; then ok "node v$(node -v) installed"; else fail "node install failed"; fi - ;; - esac - fi -else - echo " Node.js not found — installing v22..." - case $PM in - apt) - echo " Setting up NodeSource repository (this may take a moment)..." - curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - - echo " Installing nodejs from apt..." - sudo apt-get install -y nodejs - if has node; then - ok "node v$(node -v) installed from NodeSource" - else - fail "Node.js install failed" + else + fail "Node.js 22 install failed — $SYSTEM_NODE not found or wrong version" exit 1 fi - ;; - pacman) - echo " Installing nodejs from pacman..." + fi + ;; + pacman) + if has node && [ "$(node -v 2>/dev/null | cut -d. -f1 | tr -d 'v')" = "22" ]; then + skip "node v$(node -v)" + else install_pkg nodejs npm if has node; then ok "node v$(node -v) installed"; else fail "node install failed"; exit 1; fi - ;; - brew) - echo " Installing node from brew..." + fi + ;; + brew) + if has node && [ "$(node -v 2>/dev/null | cut -d. -f1 | tr -d 'v')" = "22" ]; then + skip "node v$(node -v)" + else install_pkg node if has node; then ok "node v$(node -v) installed"; else fail "node install failed"; exit 1; fi - ;; - esac -fi - -# ─── npm global packages (system-wide) ───────────────────────────────────────── -# Install npm global packages to system /usr/local so all users can access them. -# This is safer for multi-user production setups. -echo "" -echo "── npm global packages (system-wide) ──" - -if ! has npm; then - warn "npm not found — skipping global package installs" - exit 1 -fi - -# Verify npm is pointing to system node (not user-local nvm) -NPM_BIN=$(which npm) -if echo "$NPM_BIN" | grep -q '.nvm'; then - warn "npm is from nvm ($NPM_BIN), but setup.sh expects system npm" - warn "This is fine — packages will be installed to your nvm, but won't be available to other users" - warn "For production: all users should use the same system Node.js (no nvm)" -fi + fi + ;; +esac # ─── 6. Bun ─────────────────────────────────────────────────────────────────── echo "" echo "── Bun ──" -if has bun; then +export BUN_INSTALL="$HOME/.bun" +export PATH="$BUN_INSTALL/bin:$PATH" + +if [ -f "$BUN_INSTALL/bin/bun" ]; then skip "bun ($(bun --version 2>/dev/null))" else curl -fsSL https://bun.sh/install | bash - export BUN_INSTALL="$HOME/.bun" - export PATH="$BUN_INSTALL/bin:$PATH" - if has bun; then ok "bun installed"; else fail "bun install failed"; fi + if [ ! -f "$BUN_INSTALL/bin/bun" ]; then fail "bun install failed"; exit 1; fi + ok "bun $(bun --version) installed" +fi + +# Symlink to system-wide path so all users and systemd services can access it +if [ ! -L /usr/local/bin/bun ] || [ "$(readlink /usr/local/bin/bun)" != "$BUN_INSTALL/bin/bun" ]; then + sudo ln -sf "$BUN_INSTALL/bin/bun" /usr/local/bin/bun + ok "bun symlinked to /usr/local/bin/bun" +else + skip "bun symlink at /usr/local/bin/bun" fi # ─── 7. Go ───────────────────────────────────────────────────────────────────── echo "" echo "── Go ──" -GOLANG_VERSION=1.23.6 +echo " Fetching latest Go version..." +GOLANG_VERSION=$(curl -fsSL "https://go.dev/dl/?mode=json" | jq -r '.[0].version' | tr -d 'go') +if [ -z "$GOLANG_VERSION" ]; then + warn "Could not fetch latest Go version — falling back to 1.23.6" + GOLANG_VERSION=1.23.6 +fi +echo " Latest Go: $GOLANG_VERSION" -if has go; then - skip "go ($(go version 2>/dev/null | awk '{print $3}'))" -else +install_go() { case $PM in apt|pacman) - echo " Installing Go ${GOLANG_VERSION} from official tarball..." ARCH=$(uname -m) case $ARCH in x86_64) GO_ARCH=amd64 ;; aarch64) GO_ARCH=arm64 ;; *) GO_ARCH=amd64 ;; esac + echo " Installing Go ${GOLANG_VERSION} from official tarball..." curl -fsSL "https://go.dev/dl/go${GOLANG_VERSION}.linux-${GO_ARCH}.tar.gz" -o /tmp/go.tar.gz + sudo rm -rf /usr/local/go sudo tar -C /usr/local -xzf /tmp/go.tar.gz rm /tmp/go.tar.gz export PATH="/usr/local/go/bin:$PATH" @@ -402,7 +420,20 @@ else brew install go ;; esac - if has go; then ok "go installed"; else warn "go not found — install manually from https://go.dev/dl/"; fi +} + +if has go; then + INSTALLED_GO=$(go version 2>/dev/null | awk '{print $3}' | tr -d 'go') + if [ "$INSTALLED_GO" = "$GOLANG_VERSION" ]; then + skip "go $INSTALLED_GO" + else + warn "go $INSTALLED_GO installed but latest is $GOLANG_VERSION — upgrading..." + install_go + if has go; then ok "go $(go version | awk '{print $3}') installed"; else warn "go upgrade failed"; fi + fi +else + install_go + if has go; then ok "go $(go version | awk '{print $3}') installed"; else warn "go not found — install manually from https://go.dev/dl/"; fi fi # ─── 8. Rust ────────────────────────────────────────────────────────────────── @@ -531,6 +562,11 @@ else if has starship; then ok "starship installed"; else warn "starship install failed"; fi fi +# Deploy starship config +mkdir -p "$HOME/.config" +cp "$SCRIPT_DIR/starship.toml" "$HOME/.config/starship.toml" +ok "starship config deployed" + # Oh-My-Zsh if [ -d "$HOME/.oh-my-zsh" ]; then skip "oh-my-zsh (already at ~/.oh-my-zsh)" @@ -540,23 +576,26 @@ else fi # eza -EZA_VERSION=0.18.15 if has eza; then skip "eza" else case $PM in apt) - ARCH=$(uname -m) - case $ARCH in - x86_64) EZA_ARCH=x86_64 ;; - aarch64) EZA_ARCH=aarch64 ;; - *) EZA_ARCH=x86_64 ;; - esac - curl -fsSL "https://github.com/eza-community/eza/releases/download/v${EZA_VERSION}/eza_${EZA_ARCH}-unknown-linux-gnu.tar.gz" -o /tmp/eza.tar.gz - tar -xzf /tmp/eza.tar.gz -C /tmp - sudo mv /tmp/eza /usr/local/bin/eza - sudo chmod +x /usr/local/bin/eza - rm -rf /tmp/eza.tar.gz + echo " Fetching latest eza version..." + EZA_VERSION=$(curl -fsSL "https://api.github.com/repos/eza-community/eza/releases/latest" | jq -r '.tag_name' | tr -d 'v') + if [ -z "$EZA_VERSION" ]; then warn "Could not fetch eza version — skipping"; else + ARCH=$(uname -m) + case $ARCH in + x86_64) EZA_ARCH=x86_64 ;; + aarch64) EZA_ARCH=aarch64 ;; + *) EZA_ARCH=x86_64 ;; + esac + curl -fsSL "https://github.com/eza-community/eza/releases/download/v${EZA_VERSION}/eza_${EZA_ARCH}-unknown-linux-gnu.tar.gz" -o /tmp/eza.tar.gz + tar -xzf /tmp/eza.tar.gz -C /tmp + sudo mv /tmp/eza /usr/local/bin/eza + sudo chmod +x /usr/local/bin/eza + rm -f /tmp/eza.tar.gz + fi ;; pacman) install_pkg eza ;; brew) install_pkg eza ;; @@ -565,23 +604,26 @@ else fi # lazygit -LAZYGIT_VERSION=0.44.1 if has lazygit; then skip "lazygit" else case $PM in apt) - ARCH=$(uname -m) - case $ARCH in - x86_64) LG_ARCH=x86_64 ;; - aarch64) LG_ARCH=arm64 ;; - *) LG_ARCH=x86_64 ;; - esac - curl -fsSL "https://github.com/jesseduffield/lazygit/releases/download/v${LAZYGIT_VERSION}/lazygit_${LAZYGIT_VERSION}_Linux_${LG_ARCH}.tar.gz" -o /tmp/lazygit.tar.gz - tar -xzf /tmp/lazygit.tar.gz -C /tmp - sudo mv /tmp/lazygit /usr/local/bin/lazygit - sudo chmod +x /usr/local/bin/lazygit - rm -rf /tmp/lazygit.tar.gz /tmp/LICENSE /tmp/README.md + echo " Fetching latest lazygit version..." + LAZYGIT_VERSION=$(curl -fsSL "https://api.github.com/repos/jesseduffield/lazygit/releases/latest" | jq -r '.tag_name' | tr -d 'v') + if [ -z "$LAZYGIT_VERSION" ]; then warn "Could not fetch lazygit version — skipping"; else + ARCH=$(uname -m) + case $ARCH in + x86_64) LG_ARCH=x86_64 ;; + aarch64) LG_ARCH=arm64 ;; + *) LG_ARCH=x86_64 ;; + esac + curl -fsSL "https://github.com/jesseduffield/lazygit/releases/download/v${LAZYGIT_VERSION}/lazygit_${LAZYGIT_VERSION}_Linux_${LG_ARCH}.tar.gz" -o /tmp/lazygit.tar.gz + tar -xzf /tmp/lazygit.tar.gz -C /tmp + sudo mv /tmp/lazygit /usr/local/bin/lazygit + sudo chmod +x /usr/local/bin/lazygit + rm -f /tmp/lazygit.tar.gz /tmp/LICENSE /tmp/README.md + fi ;; pacman) install_pkg lazygit ;; brew) install_pkg lazygit ;; @@ -620,7 +662,12 @@ else echo " Configuring npm global prefix to /usr/local..." sudo "$SYSTEM_NPM" config set prefix /usr/local ok "npm prefix set to /usr/local" - + + # Update npm itself to latest + echo " Updating npm to latest..." + sudo "$SYSTEM_NPM" install -g npm@latest + ok "npm updated to v$(npm --version 2>/dev/null)" + # Pi (coding agent) if has pi; then skip "pi (@mariozechner/pi-coding-agent)" @@ -656,11 +703,13 @@ else if has claude; then ok "claude-code installed"; else warn "claude-code install failed"; fi fi - # pm2 (process manager) — now optional since we use systemd services + # pm2 (process manager) if has pm2; then - skip "pm2 (optional, using systemd services instead)" + skip "pm2" else - warn "pm2 optional (Officer uses systemd services for main app and sidecar)" + echo " Installing pm2..." + sudo "$SYSTEM_NPM" install -g pm2 + if has pm2; then ok "pm2 installed"; else warn "pm2 install failed"; fi fi fi @@ -752,6 +801,9 @@ echo "" echo "AI agents:" check pi check claude + +echo "" +echo "Process manager:" check pm2 echo "" diff --git a/scripts/starship.toml b/scripts/starship.toml new file mode 100644 index 00000000..e741e219 --- /dev/null +++ b/scripts/starship.toml @@ -0,0 +1,45 @@ +add_newline = true +command_timeout = 200 +format = """ +$username$hostname:[$directory$git_branch$git_status]($style) +$character""" + +[username] +format = "[$user]($style)@" +style_user = "bold green" +show_always = true + +[hostname] +format = "[$hostname]($style)" +style = "bold yellow" +ssh_only = false + +[character] +error_symbol = "[✗](bold #61afef)" +success_symbol = "[❯](bold #61afef)" + +[directory] +home_symbol = "~" +truncation_length = 0 +truncate_to_repo = false + +[git_branch] +format = " [$branch]($style) " +style = "italic #61afef" + + +[git_status] +format = '[$all_status]($style)' +style = "#61afef" +ahead = "⇡${count} " +diverged = "⇕⇡${ahead_count}⇣${behind_count} " +behind = "⇣${count} " +conflicted = " " +up_to_date = " " +untracked = "? " +modified = " " +stashed = "" +staged = "" +renamed = "" +deleted = "" +