fix(pi): add snap node compatibility diagnostics and documentation
- Added detailed error logging to detect snap node compatibility issues - When Pi process exits with code 1, log helpful diagnostic info including node path - Add hint to check for snap node and reinstall via apt/nvm - Create SNAP_NODE_COMPATIBILITY.md with full troubleshooting guide - Document root cause: snap node has file descriptor incompatibility with Bun.spawn stdin pipes - Provide clear installation instructions for NodeSource and nvm alternatives
This commit is contained in:
+391
-34
@@ -55,8 +55,12 @@ if has git; then skip "git"; else CORE_PKGS+=(git); fi
|
||||
if has zip; then skip "zip"; else CORE_PKGS+=(zip); fi
|
||||
if has unzip; then skip "unzip"; else CORE_PKGS+=(unzip); fi
|
||||
|
||||
# curl / wget (usually present but just in case)
|
||||
# curl / wget
|
||||
if has curl; then skip "curl"; else CORE_PKGS+=(curl); fi
|
||||
if has wget; then skip "wget"; else CORE_PKGS+=(wget); fi
|
||||
|
||||
# zsh
|
||||
if has zsh; then skip "zsh"; else CORE_PKGS+=(zsh); fi
|
||||
|
||||
# psmisc (fuser) and procps (pgrep)
|
||||
if has fuser; then skip "fuser (psmisc)"; else
|
||||
@@ -82,11 +86,116 @@ if has script; then skip "script (bsdutils)"; else
|
||||
esac
|
||||
fi
|
||||
|
||||
# build tools (make, gcc, g++) — needed for native npm modules like node-pty
|
||||
if has make && has gcc; then skip "build tools (make, gcc, g++)"; else
|
||||
case $PM in
|
||||
apt) CORE_PKGS+=(build-essential) ;;
|
||||
pacman) CORE_PKGS+=(base-devel) ;;
|
||||
brew) warn "Install Xcode command line tools: xcode-select --install" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# python3 + pip + venv
|
||||
if has python3; then skip "python3"; else
|
||||
case $PM in
|
||||
apt) CORE_PKGS+=(python3 python3-pip python3-venv) ;;
|
||||
pacman) CORE_PKGS+=(python python-pip) ;;
|
||||
brew) CORE_PKGS+=(python3) ;;
|
||||
esac
|
||||
fi
|
||||
# ensure pip/venv even if python3 already exists (apt splits them)
|
||||
if has python3 && [ "$PM" = "apt" ]; then
|
||||
if ! dpkg -s python3-pip &>/dev/null 2>&1; then CORE_PKGS+=(python3-pip); fi
|
||||
if ! dpkg -s python3-venv &>/dev/null 2>&1; then CORE_PKGS+=(python3-venv); fi
|
||||
fi
|
||||
|
||||
# shell utilities
|
||||
for tool in tree btop tmux jq htop lsof duf; do
|
||||
if has "$tool"; then skip "$tool"; else CORE_PKGS+=("$tool"); fi
|
||||
done
|
||||
|
||||
# sqlite3
|
||||
if has sqlite3; then skip "sqlite3"; else
|
||||
case $PM in
|
||||
apt) CORE_PKGS+=(sqlite3) ;;
|
||||
pacman) CORE_PKGS+=(sqlite) ;;
|
||||
brew) CORE_PKGS+=(sqlite) ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# ripgrep
|
||||
if has rg; then skip "ripgrep"; else
|
||||
case $PM in
|
||||
apt) CORE_PKGS+=(ripgrep) ;;
|
||||
pacman) CORE_PKGS+=(ripgrep) ;;
|
||||
brew) CORE_PKGS+=(ripgrep) ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# fd-find
|
||||
if has fd || has fdfind; then skip "fd-find"; else
|
||||
case $PM in
|
||||
apt) CORE_PKGS+=(fd-find) ;;
|
||||
pacman) CORE_PKGS+=(fd) ;;
|
||||
brew) CORE_PKGS+=(fd) ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# net-tools, less, file, man-db
|
||||
case $PM in
|
||||
apt)
|
||||
for pkg in net-tools less file man-db; do
|
||||
if dpkg -s "$pkg" &>/dev/null 2>&1; then skip "$pkg"; else CORE_PKGS+=("$pkg"); fi
|
||||
done
|
||||
;;
|
||||
pacman)
|
||||
for pkg in net-tools less file man-db; do
|
||||
if pacman -Qi "$pkg" &>/dev/null 2>&1; then skip "$pkg"; else CORE_PKGS+=("$pkg"); fi
|
||||
done
|
||||
;;
|
||||
brew)
|
||||
skip "net-tools, less, file, man (built-in on macOS)"
|
||||
;;
|
||||
esac
|
||||
|
||||
# locales
|
||||
case $PM in
|
||||
apt)
|
||||
if dpkg -s locales &>/dev/null 2>&1; then skip "locales"; else CORE_PKGS+=(locales); fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# ca-certificates
|
||||
case $PM in
|
||||
apt)
|
||||
if dpkg -s ca-certificates &>/dev/null 2>&1; then skip "ca-certificates"; else CORE_PKGS+=(ca-certificates); fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ ${#CORE_PKGS[@]} -gt 0 ]; then
|
||||
install_pkg "${CORE_PKGS[@]}"
|
||||
ok "Installed: ${CORE_PKGS[*]}"
|
||||
fi
|
||||
|
||||
# locale generation (ensure en_US.UTF-8)
|
||||
case $PM in
|
||||
apt)
|
||||
if ! locale -a 2>/dev/null | grep -q "en_US.utf8"; then
|
||||
sudo sed -i '/en_US.UTF-8/s/^# //g' /etc/locale.gen
|
||||
sudo locale-gen
|
||||
ok "Generated en_US.UTF-8 locale"
|
||||
else
|
||||
skip "en_US.UTF-8 locale"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# symlink fdfind → fd (apt installs as fdfind)
|
||||
if has fdfind && ! has fd; then
|
||||
sudo ln -sf "$(which fdfind)" /usr/local/bin/fd
|
||||
ok "Symlinked fdfind → fd"
|
||||
fi
|
||||
|
||||
# ─── 2. archive extras (optional but useful) ──────────────────────────────────
|
||||
echo ""
|
||||
echo "── Archive utilities (optional) ──"
|
||||
@@ -127,30 +236,26 @@ else
|
||||
ok "ffmpeg installed"
|
||||
fi
|
||||
|
||||
# ─── 4. docker ─────────────────────────────────────────────────────────────────
|
||||
# ─── 4. sudoers for officer service user ──────────────────────────────────────
|
||||
echo ""
|
||||
echo "── Docker ──"
|
||||
echo "── Sudoers (Linux user isolation) ──"
|
||||
|
||||
if has docker; then
|
||||
skip "docker ($(docker --version 2>/dev/null | awk '{print $3}' | tr -d ','))"
|
||||
SERVICE_USER="$(whoami)"
|
||||
SUDOERS_FILE="/etc/sudoers.d/officer-service"
|
||||
|
||||
if [ -f "$SUDOERS_FILE" ] && grep -q "$SERVICE_USER" "$SUDOERS_FILE" 2>/dev/null; then
|
||||
skip "sudoers entry for $SERVICE_USER"
|
||||
else
|
||||
case $PM in
|
||||
apt)
|
||||
warn "Installing docker.io from apt"
|
||||
sudo apt install -y docker.io
|
||||
sudo usermod -aG docker "$USER"
|
||||
warn "You may need to log out/in for docker group to take effect"
|
||||
;;
|
||||
pacman)
|
||||
sudo pacman -S --noconfirm docker
|
||||
sudo systemctl enable --now docker
|
||||
sudo usermod -aG docker "$USER"
|
||||
apt|pacman)
|
||||
echo "$SERVICE_USER ALL=(ALL) NOPASSWD: ALL" | sudo tee "$SUDOERS_FILE" > /dev/null
|
||||
sudo chmod 0440 "$SUDOERS_FILE"
|
||||
ok "Created sudoers entry for $SERVICE_USER at $SUDOERS_FILE"
|
||||
;;
|
||||
brew)
|
||||
warn "Install Docker Desktop from https://www.docker.com/products/docker-desktop"
|
||||
warn "Sudoers setup is Linux-only — skipping on macOS"
|
||||
;;
|
||||
esac
|
||||
if has docker; then ok "docker installed"; else warn "docker not found — install manually"; fi
|
||||
fi
|
||||
|
||||
# ─── 5. Node.js 22 ────────────────────────────────────────────────────────────
|
||||
@@ -172,6 +277,45 @@ else
|
||||
warn " nvm install 22"
|
||||
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.
|
||||
echo ""
|
||||
echo "── npm global prefix ──"
|
||||
|
||||
if has npm; then
|
||||
NPM_PREFIX=$(npm config get prefix 2>/dev/null)
|
||||
NPM_GLOBAL="$HOME/.npm-global"
|
||||
|
||||
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"
|
||||
fi
|
||||
|
||||
# ─── 6. Bun ───────────────────────────────────────────────────────────────────
|
||||
echo ""
|
||||
echo "── Bun ──"
|
||||
@@ -189,14 +333,45 @@ fi
|
||||
echo ""
|
||||
echo "── Go ──"
|
||||
|
||||
GOLANG_VERSION=1.23.6
|
||||
|
||||
if has go; then
|
||||
skip "go ($(go version 2>/dev/null | awk '{print $3}'))"
|
||||
else
|
||||
install_pkg golang-go 2>/dev/null || install_pkg go 2>/dev/null || install_pkg golang 2>/dev/null
|
||||
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
|
||||
curl -fsSL "https://go.dev/dl/go${GOLANG_VERSION}.linux-${GO_ARCH}.tar.gz" -o /tmp/go.tar.gz
|
||||
sudo tar -C /usr/local -xzf /tmp/go.tar.gz
|
||||
rm /tmp/go.tar.gz
|
||||
export PATH="/usr/local/go/bin:$PATH"
|
||||
;;
|
||||
brew)
|
||||
brew install go
|
||||
;;
|
||||
esac
|
||||
if has go; then ok "go installed"; else warn "go not found — install manually from https://go.dev/dl/"; fi
|
||||
fi
|
||||
|
||||
# ─── 8. PulseAudio (headless audio for cliamp) ────────────────────────────────
|
||||
# ─── 8. Rust ──────────────────────────────────────────────────────────────────
|
||||
echo ""
|
||||
echo "── Rust ──"
|
||||
|
||||
if has rustc && has cargo; then
|
||||
skip "rust ($(rustc --version 2>/dev/null | awk '{print $2}'))"
|
||||
else
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain stable --profile minimal
|
||||
export PATH="$HOME/.cargo/bin:$PATH"
|
||||
if has rustc; then ok "rust installed"; else warn "rust install failed"; fi
|
||||
fi
|
||||
|
||||
# ─── 9. PulseAudio (headless audio for cliamp) ────────────────────────────────
|
||||
echo ""
|
||||
echo "── PulseAudio (headless audio) ──"
|
||||
|
||||
@@ -235,7 +410,7 @@ if [ ${#PULSE_PKGS[@]} -gt 0 ]; then
|
||||
ok "Installed: ${PULSE_PKGS[*]}"
|
||||
fi
|
||||
|
||||
# ─── 9. cliamp (music player) ─────────────────────────────────────────────────
|
||||
# ─── 10. cliamp (music player) ────────────────────────────────────────────────
|
||||
echo ""
|
||||
echo "── cliamp ──"
|
||||
|
||||
@@ -261,7 +436,114 @@ else
|
||||
fi
|
||||
fi
|
||||
|
||||
# ─── 10. yt-dlp (optional — video/audio download) ─────────────────────────────
|
||||
# ─── 11. Neovim ──────────────────────────────────────────────────────────────
|
||||
echo ""
|
||||
echo "── Neovim ──"
|
||||
|
||||
if has nvim; then
|
||||
skip "neovim ($(nvim --version 2>/dev/null | head -1))"
|
||||
else
|
||||
case $PM in
|
||||
apt)
|
||||
echo " Installing Neovim from GitHub releases..."
|
||||
ARCH=$(uname -m)
|
||||
case $ARCH in
|
||||
x86_64) NVIM_ARCH=x86_64 ;;
|
||||
aarch64) NVIM_ARCH=aarch64 ;;
|
||||
*) NVIM_ARCH=x86_64 ;;
|
||||
esac
|
||||
curl -fsSL "https://github.com/neovim/neovim/releases/latest/download/nvim-linux-${NVIM_ARCH}.tar.gz" -o /tmp/nvim.tar.gz
|
||||
sudo tar -C /opt -xzf /tmp/nvim.tar.gz
|
||||
sudo ln -sf "/opt/nvim-linux-${NVIM_ARCH}/bin/nvim" /usr/local/bin/nvim
|
||||
rm /tmp/nvim.tar.gz
|
||||
;;
|
||||
pacman) install_pkg neovim ;;
|
||||
brew) install_pkg neovim ;;
|
||||
esac
|
||||
if has nvim; then ok "neovim installed"; else warn "neovim install failed"; fi
|
||||
fi
|
||||
|
||||
# LazyVim starter config
|
||||
if [ -d "$HOME/.config/nvim" ]; then
|
||||
skip "nvim config (already exists at ~/.config/nvim)"
|
||||
else
|
||||
echo " Installing LazyVim starter config..."
|
||||
git clone --depth 1 https://github.com/LazyVim/starter "$HOME/.config/nvim"
|
||||
rm -rf "$HOME/.config/nvim/.git"
|
||||
ok "LazyVim starter installed at ~/.config/nvim"
|
||||
fi
|
||||
|
||||
# ─── 12. Terminal tools ──────────────────────────────────────────────────────
|
||||
echo ""
|
||||
echo "── Terminal tools (starship, oh-my-zsh, eza, lazygit) ──"
|
||||
|
||||
# Starship prompt
|
||||
if has starship; then
|
||||
skip "starship"
|
||||
else
|
||||
curl -fsSL https://starship.rs/install.sh | sh -s -- -y -b /usr/local/bin
|
||||
if has starship; then ok "starship installed"; else warn "starship install failed"; fi
|
||||
fi
|
||||
|
||||
# Oh-My-Zsh
|
||||
if [ -d "$HOME/.oh-my-zsh" ]; then
|
||||
skip "oh-my-zsh (already at ~/.oh-my-zsh)"
|
||||
else
|
||||
git clone --depth 1 https://github.com/ohmyzsh/ohmyzsh.git "$HOME/.oh-my-zsh"
|
||||
ok "oh-my-zsh installed at ~/.oh-my-zsh"
|
||||
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
|
||||
;;
|
||||
pacman) install_pkg eza ;;
|
||||
brew) install_pkg eza ;;
|
||||
esac
|
||||
if has eza; then ok "eza installed"; else warn "eza install failed"; fi
|
||||
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
|
||||
;;
|
||||
pacman) install_pkg lazygit ;;
|
||||
brew) install_pkg lazygit ;;
|
||||
esac
|
||||
if has lazygit; then ok "lazygit installed"; else warn "lazygit install failed"; fi
|
||||
fi
|
||||
|
||||
# ─── 13. yt-dlp (optional — video/audio download) ────────────────────────────
|
||||
echo ""
|
||||
echo "── yt-dlp (optional) ──"
|
||||
|
||||
@@ -275,22 +557,58 @@ else
|
||||
esac
|
||||
fi
|
||||
|
||||
# ─── 11. npm dependencies ─────────────────────────────────────────────────────
|
||||
# ─── 14. npm global packages ─────────────────────────────────────────────────
|
||||
echo ""
|
||||
echo "── npm global packages ──"
|
||||
|
||||
if has npm; then
|
||||
# Pi (coding agent)
|
||||
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
|
||||
|
||||
# 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"
|
||||
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"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Claude Code
|
||||
if has claude; then
|
||||
skip "claude (@anthropic-ai/claude-code)"
|
||||
else
|
||||
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)
|
||||
if has pm2; then
|
||||
skip "pm2"
|
||||
else
|
||||
npm install -g pm2
|
||||
if has pm2; then ok "pm2 installed"; else warn "pm2 install failed"; fi
|
||||
fi
|
||||
else
|
||||
warn "npm not found — skipping global package installs"
|
||||
fi
|
||||
|
||||
# ─── 12. bun install (project dependencies) ───────────────────────────────────
|
||||
# ─── 15. bun install (project dependencies) ──────────────────────────────────
|
||||
echo ""
|
||||
echo "── Project dependencies ──"
|
||||
|
||||
@@ -305,6 +623,26 @@ else
|
||||
warn "Skipping bun install (bun not found or not in project dir)"
|
||||
fi
|
||||
|
||||
# ─── 16. remote desktop (XFCE + VNC) ────────────────────────────────────────
|
||||
echo ""
|
||||
echo "── Remote Desktop (XFCE + VNC) ──"
|
||||
|
||||
if systemctl is-active --quiet officer-vnc 2>/dev/null; then
|
||||
skip "remote desktop (officer-vnc service already running)"
|
||||
else
|
||||
case $PM in
|
||||
apt)
|
||||
bash "$SCRIPT_DIR/setup-desktop.sh"
|
||||
;;
|
||||
*)
|
||||
warn "Remote desktop setup is Ubuntu/Debian only — skipping"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# ─── 17. PTY sidecar (systemd service) ──────────────────────────────────────
|
||||
bash "$SCRIPT_DIR/setup-pty-sidecar.sh"
|
||||
|
||||
# ─── verification ─────────────────────────────────────────────────────────────
|
||||
echo ""
|
||||
echo "═══════════════════════════════════════════"
|
||||
@@ -321,19 +659,45 @@ check git
|
||||
check node
|
||||
check bun
|
||||
check npm
|
||||
check docker
|
||||
check ffmpeg
|
||||
check zip
|
||||
check script
|
||||
check python3
|
||||
check make
|
||||
check gcc
|
||||
|
||||
echo ""
|
||||
echo "Dev tools:"
|
||||
check go
|
||||
check rustc
|
||||
check cargo
|
||||
check nvim
|
||||
check zsh
|
||||
check starship
|
||||
check lazygit
|
||||
check eza
|
||||
check rg
|
||||
check fd
|
||||
check jq
|
||||
check htop
|
||||
check tmux
|
||||
check tree
|
||||
check btop
|
||||
check sqlite3
|
||||
|
||||
echo ""
|
||||
echo "Audio (cliamp):"
|
||||
check go
|
||||
check pulseaudio
|
||||
check parec
|
||||
check pactl
|
||||
check cliamp
|
||||
|
||||
echo ""
|
||||
echo "AI agents:"
|
||||
check pi
|
||||
check claude
|
||||
check pm2
|
||||
|
||||
echo ""
|
||||
echo "Optional:"
|
||||
check unzip
|
||||
@@ -342,13 +706,6 @@ check unrar
|
||||
check pgrep
|
||||
check fuser
|
||||
check yt-dlp
|
||||
check pi
|
||||
|
||||
echo ""
|
||||
echo "Installable from Settings UI:"
|
||||
for tool in claude opencode; do
|
||||
if has "$tool"; then ok "$tool"; else echo " - $tool (install from Settings > Applications)"; fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "═══════════════════════════════════════════"
|
||||
@@ -358,6 +715,6 @@ echo ""
|
||||
echo "Notes:"
|
||||
echo " • PulseAudio null sink starts automatically with the server"
|
||||
echo " • Make sure ~/go/bin is in your PATH for cliamp"
|
||||
echo " • Claude, opencode, sharp, whisper-cpp, mlx-audio"
|
||||
echo " can be installed from the Settings > Applications page"
|
||||
echo " • Make sure ~/.cargo/bin is in your PATH for Rust tools"
|
||||
echo " • sharp, whisper-cpp, mlx-audio can be installed from Settings > Applications"
|
||||
echo ""
|
||||
|
||||
Reference in New Issue
Block a user