Skip to content

πŸ“₯ ZSHAND Installer Development GuideΒΆ

πŸ“‹ This guide covers how installers work, how to add a new platform, and package management conventions.

🧠 Philosophy

Installers should be idempotent, non-destructive, and informative. Running an installer twice should produce the same result. Always check before installing and report what was done.


πŸ—οΈ ArchitectureΒΆ

πŸ“ Directory StructureΒΆ

installers/
β”œβ”€β”€ πŸ“‹ README.md                      This guide (overview)
β”œβ”€β”€ πŸ“₯ setup.zsh                      Bootstrap script (source β€” edit this)
β”œβ”€β”€ πŸ“₯ debian.sh                      Debian installer (bash)
β”œβ”€β”€ πŸ“₯ ubuntu.sh                      Ubuntu installer (bash)
β”œβ”€β”€ πŸ“₯ wsl.sh                         WSL installer (bash)
β”œβ”€β”€ πŸ“₯ manjaro.zsh                    Manjaro/Arch installer (zsh)
β”œβ”€β”€ πŸ“₯ osx.zsh                        macOS installer (zsh)
β”œβ”€β”€ πŸ“₯ manjaro-optional-installer.zsh Optional packages for Manjaro
β”œβ”€β”€ πŸ“₯ Install-zshand.ps1            PowerShell installer (Windows/WSL)
β”œβ”€β”€ πŸ“¦ general/                       Cross-platform utilities
β”‚   β”œβ”€β”€ gum_helpers.sh               Shared gum TUI helpers (bash/zsh)
β”‚   β”œβ”€β”€ environment.zsh              Environment setup
β”‚   β”œβ”€β”€ links.zsh                    Symlink management
β”‚   β”œβ”€β”€ logger.zsh                   Installer logging
β”‚   β”œβ”€β”€ permissions.zsh              File permissions
β”‚   └── required_dirs.zsh           Required directory creation
β”œβ”€β”€ πŸ“¦ packages/                      Package lists by platform
β”‚   β”œβ”€β”€ debian-packages.zsh          Debian required packages
β”‚   β”œβ”€β”€ debian-optional.zsh          Debian optional packages
β”‚   β”œβ”€β”€ manjaro-packages.zsh         Manjaro required packages
β”‚   └── manjaro-optional.zsh         Manjaro optional packages
└── πŸ”§ utilities/                     Tool-specific installers
    β”œβ”€β”€ atuin-setup.zsh              Atuin history sync setup
    └── powershell-linux.zsh         PowerShell Core on Linux

Note: The top-level setup.zsh is a compiled single-file version (auto-generated by just setup). Edit installers/setup.zsh instead.

πŸ”„ How Installers Are CalledΒΆ

setup.zsh (compiled)  ←  built from installers/setup.zsh + gum_helpers.sh
  β”‚
  β”œβ”€β”€ Detects OS (from /etc/os-release or user selection)
  β”‚
  β”œβ”€β”€ Looks for: installers/${os_id}.sh  OR  installers/${os_id}.zsh
  β”‚
  └── Runs the matching installer via bash or zsh

πŸ“ Writing a New InstallerΒΆ

🧱 Template¢

#!/usr/bin/env bash
# ── ${os_id}.sh β€” ZSHAND system installer for ${OS_NAME} ───────────────────
#
# Called by setup.zsh during first-time framework installation.
# Installs system dependencies required by the ZSHAND framework.
#
# USAGE:
#   bash installers/${os_id}.sh
#
# ─────────────────────────────────────────────────────────────────────────────

set -euo pipefail

echo "πŸ“¦ Installing ZSHAND dependencies for ${OS_NAME}..."

# ── Required Packages ───────────────────────────────────────────────────────

REQUIRED=(
    zsh
    git
    curl
    jq
    fzf
    ripgrep
    fd-find
    bat
    eza
)

echo "πŸ“‹ Installing required packages..."
for pkg in "${REQUIRED[@]}"; do
    if command -v "$pkg" &>/dev/null || dpkg -l "$pkg" &>/dev/null 2>&1; then
        echo "  βœ“ $pkg (already installed)"
    else
        echo "  πŸ“₯ Installing $pkg..."
        sudo apt install -y "$pkg" 2>/dev/null || echo "  ⚠️  Failed: $pkg"
    fi
done

# ── Optional Packages ──────────────────────────────────────────────────────

OPTIONAL=(
    htop
    duf
    tree
    micro
)

echo ""
echo "πŸ“‹ Installing optional packages..."
for pkg in "${OPTIONAL[@]}"; do
    if command -v "$pkg" &>/dev/null; then
        echo "  βœ“ $pkg (already installed)"
    else
        echo "  πŸ“₯ Installing $pkg..."
        sudo apt install -y "$pkg" 2>/dev/null || echo "  ⚠️  Skipped: $pkg"
    fi
done

echo ""
echo "βœ“ ${OS_NAME} system dependencies installed."

πŸ“ RulesΒΆ

  1. Idempotent β€” safe to run multiple times
  2. Check before install β€” skip if already present
  3. Report status β€” show βœ“ for existing, πŸ“₯ for installing, ⚠️ for failures
  4. Non-fatal failures β€” optional packages can fail silently
  5. No interactive prompts β€” use -y flags for package managers
  6. Separate required/optional β€” clearly distinguish must-have from nice-to-have

πŸ“¦ Package ListsΒΆ

Package lists live in installers/packages/ as zsh arrays:

# packages/debian-packages.zsh
# Required packages for Debian/Ubuntu

typeset -ga ZSHAND_REQUIRED_PACKAGES=(
    zsh
    git
    curl
    jq
    fzf
    ripgrep        # provides rg
    fd-find        # provides fd (may need alias)
    bat            # may be batcat on Debian
    eza
)

πŸ”„ Package Name MappingΒΆ

Some tools have different package names across distros:

Tool Debian/Ubuntu Arch/Manjaro Homebrew
fd fd-find fd fd
bat bat (or batcat) bat bat
rg ripgrep ripgrep ripgrep
eza eza (PPA) eza eza
wl-copy wl-clipboard wl-clipboard N/A

πŸ§ͺ Testing InstallersΒΆ

βœ… Manual TestingΒΆ

# Test in a fresh container
docker run -it debian:latest bash
apt update && apt install -y curl git zsh
# Clone and run
git clone <repo> ~/zshand && cd ~/zshand
bash installers/debian.sh

βœ… VerificationΒΆ

After installation, run auditenv to verify:

auditenv  # Checks all required tools are present and meet version requirements

The minimum versions are defined in dependency-version-reqs.toml.


🌐 Adding a New Platform¢

  1. Create the installer: installers/<os_id>.sh or .zsh
  2. Create package lists: installers/packages/<os_id>-packages.zsh
  3. Update OS detection in installers/setup.zsh (if the OS isn't auto-detected), then run just setup
  4. Test in a fresh environment (container or VM)
  5. Update dependency-version-reqs.toml if minimum versions differ
  6. Document any platform-specific quirks

Document Purpose
πŸ—οΈ ARCHITECTURE.md Framework structure and setup flow
🀝 CONTRIBUTING.md Contribution workflow
πŸ‘€ USER_CONFIG.md Post-install configuration