internals

A look under the hood

internals

Curious how gaur works? Here’s the technical breakdown.

architecture

gaur follows the Elm Architecture via Bubble Tea. The codebase is modular and readable.

core components

FilePurpose
model.goCentral state: config, packages, selections, UI state
update.goEvent handling: keyboard, mouse, messages
view.goMain rendering logic and layout
styles.goThemes, colors, and Lip Gloss styles
commands.goSystem interaction: pacman, AUR helpers, fzf
config.goConfiguration loading and validation
settings.goIn-app settings overlay
feature_dashboard.goDashboard stats and widgets
feature_install.goInstall mode logic
feature_remove.goRemove mode logic
feature_update.goUpdate mode logic
cache_views.goCache management UI
utils.goHelpers: fuzzy matching, highlighting, validation
types.goType definitions and constants

aur helper integration

gaur doesn’t replace your package manager. It wraps it.

search pipeline

  1. Local query: Searches the pacman sync database for official packages
  2. AUR query: Queries AUR through your configured helper (debounced to avoid hammering)
  3. Fuzzy filter: Results pipe through fzf --filter for relevance-ranked matching
  4. Merge: Official and AUR results are combined and deduplicated

interactive handoff

Operations requiring user input use tea.ExecProcess to hand control to the terminal:

  • Password prompts (sudo)
  • Conflict resolution
  • License acceptance
  • Build confirmations (AUR)

This keeps the terminal fully interactive. gaur resumes after the operation completes.

real-time state sync

After every install, remove, or update:

  1. gaur runs a full system scan
  2. Dashboard statistics update
  3. Package lists refresh
  4. Cache sizes recalculate

The UI always reflects reality. No stale data.

security measures

gaur is careful about what it executes:

package name validation

Every package name is validated before being passed to commands:

// Only allows: a-z, A-Z, 0-9, @, ., _, +, -
func isValidPackageName(name string) bool

This prevents shell injection through malicious package names.

config validation

Configuration values are validated and sanitized:

  • AUR helper: Only paru or yay allowed
  • Cache tool: Only paccache allowed
  • Cache directory: Must be an absolute path, no .. traversal
  • File permissions: Config files created with 0600 (owner-only)

command building

Commands are built using structured argument arrays, never string concatenation:

cmd := exec.Command(helper, "-S", "--noconfirm", pkg1, pkg2)

No shell interpretation, no injection vectors.

file locations

PathPurpose
~/.config/gaur/config.tomlUser configuration
~/.config/gaur/gaur.logError logging
/var/cache/pacman/pkgPacman package cache
~/.cache/paru/cloneParu build directory
~/.cache/yayYay build directory

gaur respects $XDG_CONFIG_HOME and $XDG_CACHE_HOME if set.

dependencies

gaur shells out to these tools:

ToolPackagePurpose
pacmanpacmanPackage database queries
paru or yayAUR helperInstall, remove, update, AUR search
fzffzfFuzzy filtering
paccachepacman-contribCache management

performance notes

  • Debouncing: Package detail fetches are debounced (default 150ms) to reduce system calls
  • Caching: Package details are cached in memory to avoid repeat lookups
  • Lazy loading: AUR search only triggers after the local search completes
  • Batch operations: Multiple packages are passed to a single command, not one-by-one