Package Management
This skill documents package installation patterns and conventions used in the dotfiles project for both Linux and Windows platforms.
Overview
The dotfiles project manages system packages declaratively through conf/packages.ini:
- •Linux: Uses
pacman(official Arch repos) andparu(AUR packages) - •Windows: Uses
winget(Windows Package Manager) - •Idempotent: All package checks prevent redundant installations
- •Profile-Based: Different package sets for different profiles (base, arch, arch-desktop, windows)
Configuration File Format
INI Structure
Package lists are organized by profile sections in conf/packages.ini:
# Linux packages - Official repositories [arch] git neovim zsh # Linux packages - Desktop-specific [arch,desktop] alacritty xmonad chromium # Linux packages - AUR (requires paru) [arch,aur] powershell-bin # Linux packages - AUR desktop-specific [arch,desktop,aur] visual-studio-code-insiders-bin spotify # Windows packages [windows] Git.Git Microsoft.PowerShell Microsoft.VisualStudioCode
Section Naming Convention
- •
[arch]- Base Arch Linux packages for all systems - •
[arch,desktop]- Desktop-specific packages (excludes headless servers) - •
[arch,aur]- AUR packages for all Arch systems - •
[arch,desktop,aur]- AUR packages for desktop systems only - •
[windows]- Windows packages
See the profile-system skill for details on profile filtering.
Linux Package Management
Package Managers
pacman (Official Repositories)
- •Command:
sudo pacman -S --quiet --needed --noconfirm <packages> - •Detection: Checks if package exists with
pacman -Qq <package> - •Flags:
- •
--needed: Skip already installed packages - •
--noconfirm: No prompts (for automation) - •
--quiet: Minimal output
- •
paru (AUR Helper)
- •Command:
paru -S --needed --noconfirm <packages> - •Installation: Automatically built from AUR if needed (requires git, base-devel, rust)
- •Detection: Checks if package exists with
pacman -Qq <package>(same as pacman) - •Note: paru handles sudo internally - do NOT prefix with sudo
Adding Linux Packages
- •Find the correct package name:
# Official repositories pacman -Ss <search-term> # AUR packages paru -Ss <search-term>
- •Add to appropriate section in
conf/packages.ini:
[arch] # Official repo packages my-package [arch,aur] # AUR packages my-aur-package-bin
- •Install:
./dotfiles.sh -I
Implementation Pattern (Shell)
# Check for package manager
if ! is_program_installed "sudo" || ! is_program_installed "pacman"; then
log_verbose "Skipping package installation: sudo or pacman not installed"
return
fi
# Build list of missing packages
packages=""
for package in $package_list; do
if ! pacman -Qq "$package" >/dev/null 2>&1; then
packages="$packages $package"
log_verbose "Package needs installation: $package"
else
log_verbose "Skipping package $package: already installed"
fi
done
# Install if any packages missing
if [ -n "$packages" ]; then
if ! is_dry_run; then
sudo pacman -S --quiet --needed --noconfirm $packages
# Increment counter for each package
for pkg in $packages; do
increment_counter "packages_installed"
done
else
log_dry_run "Would install packages: $packages"
fi
fi
Windows Package Management
Package Manager
winget (Windows Package Manager)
- •Built-in: Included in Windows 11 and modern Windows 10
- •Command:
winget install --id <PackageId> --silent --accept-package-agreements --accept-source-agreements - •Detection: Use
winget list --id <PackageId>to check if installed - •Flags:
- •
--silent: No UI, minimal output - •
--accept-package-agreements: Auto-accept licenses - •
--accept-source-agreements: Auto-accept source agreements
- •
Adding Windows Packages
- •Find the correct package ID:
winget search <search-term> # Note the exact Package ID (e.g., Microsoft.PowerShell)
- •Add to
conf/packages.ini:
[windows] Microsoft.PowerShell Git.Git Microsoft.VisualStudioCode
- •Install:
.\dotfiles.ps1 # Or from anywhere: Install-Dotfiles
Implementation Pattern (PowerShell)
function Test-PackageInstalled {
param ([string]$PackageId)
try {
$result = winget list --id $PackageId 2>&1
# Check if output contains the package ID
return ($result -match [regex]::Escape($PackageId))
}
catch {
return $false
}
}
# Check each package
foreach ($packageId in $packages) {
if (-not (Test-PackageInstalled -PackageId $packageId)) {
Write-VerboseMessage "Package needs installation: $packageId"
if (-not $DryRun) {
winget install --id $packageId --silent `
--accept-package-agreements `
--accept-source-agreements
Add-Counter -CounterName "packages_installed"
} else {
Write-DryRunMessage "Would install package: $packageId"
}
} else {
Write-VerboseMessage "Package already installed: $packageId"
}
}
Rules for Package Management
- •
Always check before installing: Use package manager's query commands to check if package is already installed
- •
Use batch installations when possible: Collect all missing packages and install in a single command for efficiency
- •
Use --needed flag: Prevents unnecessary reinstallation on Linux (
pacmanandparu) - •
No sudo for paru: The paru AUR helper manages elevation internally
- •
Handle missing package managers gracefully: Skip package installation with verbose message if package manager not found
- •
Increment counters: Track each installed package with
increment_counterorAdd-Counterfor summary statistics - •
Support dry-run mode: Show what would be installed without actually installing
- •
Use exact package IDs on Windows: Package IDs are case-sensitive and must match exactly (e.g.,
Microsoft.PowerShell, notpowershell) - •
Separate AUR packages: Use dedicated
[arch,aur]sections for AUR packages to keep them separate from official repo packages - •
Prerequisites for paru: Ensure git, base-devel, and rust are installed before building paru from AUR
Common Patterns
Installing paru (AUR Helper)
install_paru() {
if is_program_installed "paru"; then
log_verbose "Skipping paru installation: already installed"
return
fi
# Check prerequisites
if ! is_program_installed "git" || ! is_program_installed "makepkg" || ! is_program_installed "cargo"; then
log_verbose "Skipping paru installation: missing prerequisites"
return
fi
log_stage "Installing paru (AUR helper)"
if is_dry_run; then
log_dry_run "Would clone and build paru from AUR"
return
fi
# Create temp directory
tmp_dir="$(mktemp -d)"
trap 'rm -rf "$tmp_dir"' EXIT
# Clone and build
cd "$tmp_dir"
git clone https://aur.archlinux.org/paru-git.git .
makepkg -si --noconfirm
}
Batch Package Installation
# Build space-separated list of missing packages
packages=""
for package in $package_list; do
if ! pacman -Qq "$package" >/dev/null 2>&1; then
packages="$packages $package"
fi
done
# Install all at once (more efficient than individual installs)
if [ -n "$packages" ]; then
sudo pacman -S --quiet --needed --noconfirm $packages
fi
Cross-References
- •See the
profile-systemskill for profile filtering and section naming - •See the
ini-configurationskill for INI file format details - •See the
logging-patternsskill for logging and counter tracking - •See the
shell-patternsskill for shell script patterns - •See the
powershell-patternsskill for PowerShell patterns