better startup scripts
This commit is contained in:
@@ -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" 2>/dev/null; then
|
||||
sudo systemctl restart "$SERVICE_NAME"
|
||||
ok "$SERVICE_NAME service updated and restarted"
|
||||
else
|
||||
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
|
||||
|
||||
+134
-82
@@ -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)
|
||||
# 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
|
||||
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"
|
||||
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"
|
||||
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
|
||||
fail "Node.js install failed"
|
||||
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
|
||||
else
|
||||
fail "Node.js 22 install failed — $SYSTEM_NODE not found or wrong version"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
pacman)
|
||||
echo " Installing nodejs from 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
|
||||
fi
|
||||
;;
|
||||
brew)
|
||||
echo " Installing node from 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
|
||||
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
|
||||
|
||||
# ─── 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 ──"
|
||||
|
||||
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,12 +576,14 @@ else
|
||||
fi
|
||||
|
||||
# eza
|
||||
EZA_VERSION=0.18.15
|
||||
if has eza; then
|
||||
skip "eza"
|
||||
else
|
||||
case $PM in
|
||||
apt)
|
||||
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 ;;
|
||||
@@ -556,7 +594,8 @@ else
|
||||
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
|
||||
rm -f /tmp/eza.tar.gz
|
||||
fi
|
||||
;;
|
||||
pacman) install_pkg eza ;;
|
||||
brew) install_pkg eza ;;
|
||||
@@ -565,12 +604,14 @@ else
|
||||
fi
|
||||
|
||||
# lazygit
|
||||
LAZYGIT_VERSION=0.44.1
|
||||
if has lazygit; then
|
||||
skip "lazygit"
|
||||
else
|
||||
case $PM in
|
||||
apt)
|
||||
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 ;;
|
||||
@@ -581,7 +622,8 @@ else
|
||||
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
|
||||
rm -f /tmp/lazygit.tar.gz /tmp/LICENSE /tmp/README.md
|
||||
fi
|
||||
;;
|
||||
pacman) install_pkg lazygit ;;
|
||||
brew) install_pkg lazygit ;;
|
||||
@@ -621,6 +663,11 @@ else
|
||||
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 ""
|
||||
|
||||
@@ -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 = ""
|
||||
|
||||
Reference in New Issue
Block a user