better startup scripts

This commit is contained in:
2026-03-04 18:05:50 +00:00
parent 98a6a69477
commit ba36629cdc
3 changed files with 222 additions and 124 deletions
+10 -9
View File
@@ -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
+167 -115
View File
@@ -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 ""
+45
View File
@@ -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 = ""