From ebd8778007679f082df9ccc7d8ceb565bbc56afa Mon Sep 17 00:00:00 2001 From: Andre Padez Date: Wed, 4 Mar 2026 02:09:47 +0000 Subject: [PATCH] fix: refactor setup scripts for system-wide Node.js (no nvm) BREAKING: Officer now uses system Node.js via NodeSource instead of nvm. Changes: - Removed nvm sourcing from setup.sh - Updated Node installation to use NodeSource repository - All npm global packages installed system-wide with sudo - Updated PTY sidecar setup to use /usr/bin/node (system node) - Added Pi validation (test --list-models) - System packages now available to all users automatically Benefits: - Multi-user friendly: all users get same Node version - No per-user environment setup needed - Simpler troubleshooting (one node version) - Services use consistent node binary - Prevents snap node incompatibility issues Fixes: - 'node not found' for secondary users - systemd services finding correct node - Pi installation consistency across users New Files: - SETUP_GUIDE.md: Comprehensive installation guide - SETUP_ANALYSIS.md: Technical analysis of previous issues Migration: - Remove nvm if installed (optional) - Run: curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - - Run: sudo apt-get install -y nodejs - Run: bash scripts/setup.sh --- SETUP_ANALYSIS.md | 310 +++++++++++++++++++++++++++++++++++ SETUP_GUIDE.md | 289 ++++++++++++++++++++++++++++++++ scripts/setup-pty-sidecar.sh | 14 +- scripts/setup.sh | 133 ++++++++------- 4 files changed, 681 insertions(+), 65 deletions(-) create mode 100644 SETUP_ANALYSIS.md create mode 100644 SETUP_GUIDE.md diff --git a/SETUP_ANALYSIS.md b/SETUP_ANALYSIS.md new file mode 100644 index 00000000..02b4d632 --- /dev/null +++ b/SETUP_ANALYSIS.md @@ -0,0 +1,310 @@ +# Officer Setup Flow Analysis + +## Overview +The setup.sh script installs all dependencies for Officer, but there are several issues that can cause problems, especially with nvm Node.js environments. + +## Setup Flow + +``` +1. Detect package manager (apt/pacman/brew) + ↓ +2. Install core system packages (git, zip, curl, zsh, build-essential, etc.) + ↓ +3. Install archive utilities (7z, unrar) + ↓ +4. Install ffmpeg + ↓ +5. Configure sudoers for service user + ↓ +6. Install Node.js 22 (or warn if not found) + ↓ +7. Configure npm global prefix (~/.npm-global) + ↓ +8. Install Bun + ↓ +9. Install Go 1.23.6 + ↓ +10. Install Rust + ↓ +11. Install PulseAudio (for audio) + ↓ +12. Build cliamp from source (Go music player) + ↓ +13. Install Neovim + ↓ +14. Install terminal tools (starship, oh-my-zsh, eza, lazygit) + ↓ +15. Install yt-dlp (optional) + ↓ +16. Install npm global packages (Pi, Claude Code, pm2) + ↓ +17. Run bun install (project dependencies) + ↓ +18. Setup remote desktop (XFCE + VNC) + ↓ +19. Setup PTY sidecar (systemd service) + ↓ +20. Verification +``` + +## Issues Found + +### 1. **nvm Node.js Not Properly Documented** + +**Location:** `scripts/setup.sh` (line ~238) + +**Problem:** +```bash +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" + else + warn "Node $NODE_VER found but v22 is required" + warn "Use nvm: nvm install 22 && nvm use 22" + fi +else + warn "Node.js not found — install v22 via nvm:" + warn " curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash" + warn " nvm install 22" +fi +``` + +**Issue:** +- Only warns about nvm but doesn't ensure it's sourced in the current shell +- When installing pm2 and other npm global packages, nvm might not be available +- When services (pm2, systemd) later run, they won't have nvm initialized + +**Impact:** +- Users install nvm, run setup.sh in that shell, but when pm2/systemd runs later, it uses the wrong node or no node + +--- + +### 2. **PTY Sidecar Service Uses Unbounded `which node`** + +**Location:** `scripts/setup-pty-sidecar.sh` (line ~16) + +**Problem:** +```bash +NODE_BIN="$(which node)" +``` + +**Issue:** +- If nvm is not sourced in the current shell, `which node` returns nothing or the system node +- The systemd service will run with the wrong node binary +- When systemd runs, nvm environment is not available anyway + +**Impact:** +- PTY sidecar service fails to start or runs with wrong node +- Terminal functionality breaks in Officer + +--- + +### 3. **PM2/Ecosystem Config Doesn't Handle nvm** + +**Location:** `ecosystem.config.cjs` + +**Problem:** +```javascript +module.exports = { + apps: [ + { + name: 'officer', + script: 'bun', + args: 'start', + watch: false, + }, + ], +}; +``` + +**Issue:** +- No environment setup for nvm +- PM2 runs with whatever node is in system PATH +- If user installed node via nvm, PM2 won't find it +- This is why you had to restart the server after installing nvm + +**Impact:** +- Officer server fails to start after fresh nvm installation +- No clear error message about nvm not being available + +--- + +### 4. **No Documentation on Node Installation Methods** + +**Location:** `scripts/setup.sh` (lines 238-250) + +**Problem:** +- Script warns about nvm but doesn't explain the workflow +- No mention of snap node incompatibility +- No mention of system apt/NodeSource installation +- No guidance on which method to use when + +**Impact:** +- Users can choose any installation method +- Some methods (snap) don't work with Officer +- New issues arise from incompatible setups + +--- + +### 5. **Pi Installation Doesn't Validate nvm Environment** + +**Location:** `scripts/setup.sh` (lines ~408-420) + +**Problem:** +```bash +if has pi; then + skip "pi (@mariozechner/pi-coding-agent)" +else + npm install -g @mariozechner/pi-coding-agent + if has pi; then ok "pi installed"; else warn "pi install failed"; fi +fi +``` + +**Issue:** +- Installs pi with `npm install -g`, but npm might be different than later shells +- No validation that pi works (should test `pi --list-models`) +- No check that Pi was installed to the right npm location + +**Impact:** +- Pi appears installed but fails at runtime when shell environment differs + +--- + +## Fixes Required + +### Fix 1: Source nvm Before Installing Global Packages + +```bash +# At the start of setup.sh, after detecting package manager +echo "" +echo "── Node.js Environment ──" + +# Check if nvm needs to be sourced +if [ -s "$HOME/.nvm/nvm.sh" ]; then + source "$HOME/.nvm/nvm.sh" + nvm use 22 || nvm install 22 + ok "nvm activated: $(node -v)" +elif ! has node; then + fail "Node.js not found and nvm not installed" + fail "Install nvm first: curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash" + exit 1 +fi +``` + +### Fix 2: Update PTY Sidecar Setup to Use Correct Node + +```bash +# In scripts/setup-pty-sidecar.sh +if [ -s "$HOME/.nvm/nvm.sh" ]; then + source "$HOME/.nvm/nvm.sh" + nvm use 22 2>/dev/null || true +fi + +NODE_BIN="$(which node)" +if [ ! -f "$NODE_BIN" ]; then + echo "ERROR: Node.js not found in PATH" + exit 1 +fi +``` + +### Fix 3: Update PM2 Ecosystem Config + +```javascript +module.exports = { + apps: [ + { + name: 'officer', + script: 'bun', + args: 'start', + watch: false, + // Source nvm before running + exec_mode: 'cluster', + instances: 1, + env: { + NODE_ENV: 'production', + // This helps systemd find the right node + NVM_DIR: '$HOME/.nvm', + }, + // For systemd service, use a wrapper script + }, + ], +}; +``` + +Or better: Create a wrapper script for PM2: + +```bash +#!/bin/bash +# bin/start.sh +set -euo pipefail + +# Source nvm if available +if [ -s "$HOME/.nvm/nvm.sh" ]; then + source "$HOME/.nvm/nvm.sh" +fi + +# Now start Officer +NODE_ENV=production bun src/server.tsx +``` + +Then in ecosystem.config.cjs: +```javascript +{ + name: 'officer', + script: 'bin/start.sh', + // ... +} +``` + +### Fix 4: Validate Pi Installation + +```bash +# After installing Pi +if has pi; then + if pi --list-models > /dev/null 2>&1; then + ok "pi installed and working" + else + warn "pi installed but --list-models failed" + warn "Try: nvm use && npm install -g @mariozechner/pi-coding-agent" + fi +else + warn "pi install failed" +fi +``` + +### Fix 5: Add Setup Documentation + +Create `SETUP_GUIDE.md` with clear instructions on: +1. Choose ONE Node installation method (recommend nvm) +2. Source nvm in shell before running setup.sh +3. Setup.sh will validate node and npm are available +4. Services (PM2, systemd) will inherit nvm environment + +--- + +## Recommendations + +1. **Make nvm sourcing automatic** at the start of setup.sh +2. **Add environment wrapper script** for PM2 that sources nvm +3. **Document the three Node installation options** with pros/cons: + - nvm (recommended, flexible versions) + - NodeSource (system package, simple) + - apt (if available in repo) + - ❌ snap (broken, don't use) +4. **Validate Pi works** before marking setup complete +5. **Create a post-setup check script** that verifies everything works + +--- + +## Current Workaround + +If setup.sh already ran with snap node: +1. Remove snap: `sudo snap remove node` +2. Install nvm: `curl -o- ... | bash` (reload shell) +3. Install node: `nvm install 22 && nvm use 22` +4. Reinstall pm2 packages: `npm install -g pm2` +5. Restart pm2/officer + +This is what you just did! diff --git a/SETUP_GUIDE.md b/SETUP_GUIDE.md new file mode 100644 index 00000000..99946461 --- /dev/null +++ b/SETUP_GUIDE.md @@ -0,0 +1,289 @@ +# Officer Setup Guide + +## Overview + +Officer is a self-hosted AI intranet for teams. This guide covers fresh installation on Ubuntu/Debian servers. + +## Architecture + +Officer uses **system-wide Node.js** to ensure all users have consistent access to tools: + +``` +System Node.js (v22, system-wide) + ↓ +npm global packages → /usr/local/lib/node_modules/ + ├── pi (coding agent) + ├── claude (Claude Code) + └── (available to all users) + +Systemd Services + ├── officer-pty-sidecar (terminal backend) + └── (other services) +``` + +This is **not** an nvm-based setup. Each user doesn't install their own Node version. Instead: +- One system Node.js for everyone +- All npm packages installed system-wide +- Simple, predictable, production-friendly + +--- + +## Installation Steps + +### 1. Install Node.js 22 (System-Wide) + +**On fresh Ubuntu/Debian:** + +```bash +# Add NodeSource repository for Node 22 LTS +curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - + +# Install Node.js and npm +sudo apt-get install -y nodejs + +# Verify for all users +node --version +npm --version + +# Both should work regardless of which user runs it +``` + +**Already have an older Node version?** + +```bash +# upgrade it +curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - +sudo apt-get install -y nodejs + +# verify +node --version # Should be v22.x.x +``` + +**Coming from nvm?** + +```bash +# If you installed via nvm before, remove it +# Then install system Node as above +# nvm is NOT needed for Officer production setup +``` + +### 2. Run Setup Script + +```bash +cd /path/to/officer/monorepo +bash scripts/setup.sh +``` + +This will: +- Install all system dependencies (git, build tools, ffmpeg, etc.) +- Install Bun, Go, Rust +- Install npm global packages (pi, claude-code, etc.) +- Setup PulseAudio for audio +- Setup remote desktop (XFCE + VNC) +- Configure PTY sidecar systemd service +- Verify everything works + +**Note:** Setup script uses `sudo` for system-level installations. You'll be prompted for your password. + +### 3. Verify Installation + +```bash +# Everyone can use these (all users) +which node # /usr/bin/node +which pi # /usr/bin/pi +which claude # /usr/bin/claude +which bun # /home/user/.bun/bin/bun (or /usr/local/bin/bun) + +# Test that pi works +pi --version +pi --list-models + +# Test that Officer can start +bun dev + +# In another terminal +curl http://localhost:5000/api/pi/models +``` + +### 4. Start Officer + +**Development:** +```bash +bun dev +``` + +**Production (with PM2):** +```bash +pm2 start ecosystem.config.cjs +pm2 logs officer +``` + +**Production (with systemd):** +```bash +sudo systemctl start officer +sudo systemctl status officer +``` + +--- + +## Multi-User Scenarios + +### Scenario A: Server with Multiple Users + +All users automatically get access to: +- `node` command (system-wide) +- `pi`, `claude` (system-wide npm packages) +- Officer web UI (via port/proxy) + +**No setup needed per user.** Just install globally once as shown above. + +```bash +# User 1 +$ which node +/usr/bin/node + +# User 2 (different terminal/server) +$ which node +/usr/bin/node + +# Both work! +``` + +### Scenario B: Development User Wants nvm + +**Important:** For production, DON'T do this. But for dev, you can: + +```bash +# As a user (not system-wide) +curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash +nvm install 22 +nvm use 22 + +# Now you can use nvm locally, but make sure system Node is also installed for services +which node # /home/user/.nvm/versions/node/v22.x.x/bin/node (your local override) +``` + +The `officer-pty-sidecar` systemd service will still use `/usr/bin/node` (system-wide). + +--- + +## Troubleshooting + +### "node: command not found" + +**For a single user:** +```bash +# User's shell doesn't have node in PATH +# Make sure system Node is installed: +sudo apt-get install -y nodejs +node --version +``` + +**For systemd service:** +```bash +# Service can't find node +sudo systemctl status officer-pty-sidecar +journalctl -u officer-pty-sidecar + +# Fix: Install system Node +curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - +sudo apt-get install -y nodejs + +# Restart service +sudo systemctl restart officer-pty-sidecar +``` + +### "pi: command not found" + +```bash +# Pi not installed +sudo npm install -g @mariozechner/pi-coding-agent + +# Or use setup script +bash scripts/setup.sh +``` + +### "Pi process exited with code 1" in chat + +This usually means **snap node was used**. Don't use snap node for Officer. + +```bash +# Check if snap node is installed +which node +# If output contains "/snap/bin/node", remove it: + +sudo snap remove node + +# Then install system Node +curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - +sudo apt-get install -y nodejs + +# Verify +which node # /usr/bin/node (NOT /snap/bin/node) +``` + +### PTY Sidecar service won't start + +```bash +# Check status +sudo systemctl status officer-pty-sidecar + +# Check logs +journalctl -u officer-pty-sidecar -n 20 + +# Verify Node is installed +/usr/bin/node --version + +# Restart +sudo systemctl restart officer-pty-sidecar +``` + +--- + +## Files Changed/Created + +- `scripts/setup.sh` — Main installation script (updated to use system Node) +- `scripts/setup-pty-sidecar.sh` — PTY sidecar systemd service setup (updated) +- `ecosystem.config.cjs` — PM2 config (no changes, using systemd instead) +- `SETUP_GUIDE.md` — This file + +--- + +## What NOT To Do + +❌ **Don't use snap node** +- It has file descriptor issues with piped processes +- Use system Node via NodeSource instead + +❌ **Don't mix Node versions per user** +- For production: one Node version for everyone (system-wide) +- For dev: sure, use nvm, but keep system Node installed too + +❌ **Don't install npm packages locally for system services** +- Services need system-wide packages (`sudo npm install -g`) +- Or use absolute paths in service files + +✅ **Do:** +- Use system Node 22 via NodeSource +- Install global packages once with `sudo npm install -g` +- Use systemd services for daemons +- Let all users share the same tools + +--- + +## Next Steps + +1. Install Node.js: `curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - && sudo apt-get install -y nodejs` +2. Run setup: `bash scripts/setup.sh` +3. Start Officer: `bun dev` (or PM2/systemd in production) +4. Open browser: `http://localhost:5000` (or your configured port) + +--- + +## Support + +If you hit issues: +1. Check troubleshooting section above +2. Verify system Node is installed: `node --version` +3. Check service logs: `journalctl -u officer-pty-sidecar` +4. Re-run setup script: `bash scripts/setup.sh` diff --git a/scripts/setup-pty-sidecar.sh b/scripts/setup-pty-sidecar.sh index b0340f1c..e2709168 100755 --- a/scripts/setup-pty-sidecar.sh +++ b/scripts/setup-pty-sidecar.sh @@ -18,14 +18,24 @@ SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}.service" SERVICE_USER="$(whoami)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" PROJECT_DIR="$(dirname "$SCRIPT_DIR")" -NODE_BIN="$(which node)" + +# Use system node (not nvm) for systemd service +NODE_BIN="/usr/bin/node" + +if [ ! -f "$NODE_BIN" ]; then + fail "System Node.js not found at $NODE_BIN" + fail "Install Node.js 22 via NodeSource:" + fail " curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -" + fail " sudo apt-get install -y nodejs" + exit 1 +fi 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" - echo " Use 'bun run restart:sidecar' to restart" exit 0 fi diff --git a/scripts/setup.sh b/scripts/setup.sh index d40e6795..4d5fc60b 100755 --- a/scripts/setup.sh +++ b/scripts/setup.sh @@ -260,60 +260,66 @@ fi # ─── 5. Node.js 22 ──────────────────────────────────────────────────────────── echo "" -echo "── Node.js 22 ──" +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" + skip "node v$NODE_VER (system-wide)" else - warn "Node $NODE_VER found but v22 is required" - warn "Use nvm: nvm install 22 && nvm use 22" + warn "Node $NODE_VER found but v22 is required — upgrading via NodeSource..." + case $PM in + apt) + 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" + fi + ;; + *) + warn "Manual upgrade needed for $PM: install Node.js 22 from official sources" + ;; + esac fi else - warn "Node.js not found — install v22 via nvm:" - warn " curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash" - warn " nvm install 22" + warn "Node.js not found — installing v22 via NodeSource..." + case $PM in + apt) + curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - + sudo apt-get install -y nodejs + if has node; then ok "node v$(node -v) installed"; else fail "node install 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 -# ─── npm global prefix ───────────────────────────────────────────────────────── -# Set npm global prefix to a user-writable directory so npm install -g -# never requires sudo. This also lets the server install packages at runtime. +# ─── 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 prefix ──" +echo "── npm global packages (system-wide) ──" -if has npm; then - NPM_PREFIX=$(npm config get prefix 2>/dev/null) - NPM_GLOBAL="$HOME/.npm-global" +if ! has npm; then + warn "npm not found — skipping global package installs" + exit 1 +fi - if [ "$NPM_PREFIX" = "$NPM_GLOBAL" ]; then - skip "npm prefix already set to $NPM_GLOBAL" - else - mkdir -p "$NPM_GLOBAL" - npm config set prefix "$NPM_GLOBAL" - export PATH="$NPM_GLOBAL/bin:$PATH" - ok "Set npm global prefix to $NPM_GLOBAL" - - # Migrate existing global packages from system prefix if any - if [ -d "$NPM_PREFIX/lib/node_modules/@mariozechner" ] || [ -d "$NPM_PREFIX/lib/node_modules/@anthropic-ai" ]; then - warn "Removing stale system-level npm packages from $NPM_PREFIX (will reinstall to $NPM_GLOBAL)" - sudo rm -rf "$NPM_PREFIX/lib/node_modules/@mariozechner" "$NPM_PREFIX/lib/node_modules/@anthropic-ai" 2>/dev/null - sudo rm -f "$NPM_PREFIX/bin/pi" "$NPM_PREFIX/bin/claude" 2>/dev/null - fi - fi - - # Ensure ~/.npm-global/bin is in shell profiles - for profile in "$HOME/.bashrc" "$HOME/.zshrc" "$HOME/.profile"; do - if [ -f "$profile" ] && ! grep -q '.npm-global/bin' "$profile"; then - echo '' >> "$profile" - echo '# npm global packages' >> "$profile" - echo 'export PATH="$HOME/.npm-global/bin:$PATH"' >> "$profile" - ok "Added ~/.npm-global/bin to $(basename "$profile")" - fi - done -else - warn "npm not found — skipping prefix setup" +# 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 ─────────────────────────────────────────────────────────────────── @@ -557,35 +563,36 @@ else esac fi -# ─── 14. npm global packages ───────────────────────────────────────────────── +# ─── 14. npm global packages (system-wide) ────────────────────────────────── echo "" -echo "── npm global packages ──" +echo "── npm global packages (system-wide) ──" -if has npm; then +if ! has npm; then + warn "npm not found — skipping global package installs" +else # Pi (coding agent) if has pi; then skip "pi (@mariozechner/pi-coding-agent)" else - npm install -g @mariozechner/pi-coding-agent + echo " Installing pi..." + sudo npm install -g @mariozechner/pi-coding-agent if has pi; then ok "pi installed"; else warn "pi install failed"; fi fi - # Fix ~/.pi ownership (previous installs via sudo may have created root-owned dirs) - if [ -d "$HOME/.pi" ]; then - if find "$HOME/.pi" -not -user "$USER" -print -quit 2>/dev/null | grep -q .; then - sudo chown -R "$USER:$(id -gn)" "$HOME/.pi" - ok "Fixed ~/.pi ownership" + # Validate Pi works + if has pi; then + if pi --list-models > /dev/null 2>&1; then + ok "pi validated (--list-models works)" + else + warn "pi installed but --list-models failed — check API keys in ~/.pi/agent/auth.json" fi fi - # Patch Pi compaction bug: calculateContextTokens crashes when usage is undefined - PI_COMPACTION="$(npm root -g 2>/dev/null)/@mariozechner/pi-coding-agent/dist/core/compaction/compaction.js" - if [ -f "$PI_COMPACTION" ]; then - if grep -q "if (!usage) return 0;" "$PI_COMPACTION" 2>/dev/null; then - skip "pi compaction patch (already applied)" - else - sed -i '/^export function calculateContextTokens(usage) {$/a\ if (!usage) return 0;' "$PI_COMPACTION" - ok "Applied pi compaction bug patch" + # Fix ~/.pi ownership if needed (in case of mixed user/sudo installs) + if [ -d "$HOME/.pi" ]; then + if find "$HOME/.pi" -not -user "$USER" -print -quit 2>/dev/null | grep -q .; then + sudo chown -R "$USER:$(id -gn)" "$HOME/.pi" + ok "Fixed ~/.pi ownership to $USER" fi fi @@ -593,16 +600,16 @@ if has npm; then if has claude; then skip "claude (@anthropic-ai/claude-code)" else - npm install -g @anthropic-ai/claude-code + echo " Installing claude-code..." + sudo npm install -g @anthropic-ai/claude-code if has claude; then ok "claude-code installed"; else warn "claude-code install failed"; fi fi - # pm2 (process manager) + # pm2 (process manager) — now optional since we use systemd services if has pm2; then - skip "pm2" + skip "pm2 (optional, using systemd services instead)" else - npm install -g pm2 - if has pm2; then ok "pm2 installed"; else warn "pm2 install failed"; fi + warn "pm2 optional (Officer uses systemd services for main app and sidecar)" fi else warn "npm not found — skipping global package installs"