zerb

module
v0.0.0-...-311dae5 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 25, 2025 License: MIT-0

README

ZERB

Zero-hassle Effortless Reproducible Builds

Development Status License Go Version

⚠️ ACTIVE DEVELOPMENT - PRE-PRE-ALPHA STAGE

ZERB is in early development and not yet ready for production use. APIs, commands, and configuration formats may change without notice. Use at your own risk and expect breaking changes.


What is ZERB?

ZERB is a single-binary tool that provides a declarative environment management by intelligently wrapping mature tools (mise for tools, chezmoi for configs) with git-native versioning and complete isolation. ZERB acts as the glue between these mature tools to make it much easier to manage your environment.

One config file. One command. Reproducible environments everywhere.

-- ~/.config/zerb/zerb.lua
zerb = {
  tools = {
    "node@20.11.0",
    "python@3.12.1",
    "cargo:ripgrep",
    "ubi:sharkdp/bat",
    platform.is_linux and "cargo:i3-msg" or nil,
  },
  
  configs = {
    "~/.zshrc",
    "~/.gitconfig",
    { path = "~/.config/nvim/", recursive = true },
  },
  
  git = {
    remote = "https://github.com/username/dotfiles",
    branch = "main",
  },
}
$ zerb sync  # Install tools, apply configs, sync across machines

Table of Contents

Getting Started:

Documentation:

Project Information:


Why ZERB?

The Problem

Managing development environments is fragile and time-consuming:

  • Tool chaos: Multiple version managers (nvm, pyenv, rbenv, etc.) with different interfaces
  • Config drift: Dotfiles scattered across machines, manually synced, easily out of date
  • System conflicts: Global installations interfere with each other
  • No reproducibility: "Works on my machine" because environments diverge
  • Manual tracking: No single source of truth for what's installed
The ZERB Solution

ZERB acts as intelligent glue between battle-tested tools:

  1. mise - Handles ALL user-space tools (dev tools, CLI utilities, binaries)
  2. chezmoi - Manages dotfiles, templates, and secrets
  3. ZERB - Provides unified config, git integration, drift detection, and UX

Key advantages:

  • Single declarative config - One Lua file defines your entire environment
  • Complete isolation - Never conflicts with system packages or other tools
  • Non-invasive - Manual shell setup with clear instructions, never auto-modifies rc files
  • Git-native versioning - Full history, rollback, sync across machines
  • Platform-aware - Conditional logic for Linux distros, macOS, Windows
  • Drift detection - Know when your environment diverges from declared state
  • Interactive UX - Smart prompts for version selection and conflict resolution
  • Security-first - GPG signature verification with SHA256 fallback
  • Transaction-based - Resume interrupted operations safely

Key Concepts

Wrapping, Not Reinventing

ZERB doesn't reimplement package management or config management. Instead, it wraps mature tools with complete isolation:

mise wrapper:

  • Installs tools via multiple backends (cargo, npm, ubi, github, core)
  • Complete isolation via environment variables (MISE_CONFIG_FILE, MISE_DATA_DIR, MISE_CACHE_DIR)
  • Shell integration via mise activate for global tool access
  • Never conflicts with system mise installations

chezmoi wrapper:

  • Manages dotfiles with template processing and secrets integration
  • Complete isolation via CLI flags (--source, --config)
  • Never touches existing chezmoi setups

ZERB's role:

  • Parse Lua config and generate mise/chezmoi configs
  • Manage git versioning with timestamped snapshots
  • Detect drift between declared and actual state
  • Provide unified, user-friendly interface
Declarative Configuration

Everything is declared in zerb.lua using Lua for cross-platform logic:

zerb = {
  tools = {
    -- Exact version pinning
    "node@20.11.0",
    "python@3.12.1",
    
    -- Multiple backends
    "cargo:ripgrep",              -- From crates.io
    "npm:prettier",               -- From npm
    "ubi:sharkdp/bat",           -- Binary from GitHub
    
    -- Platform-specific conditionals
    platform.is_linux and "cargo:i3-msg" or nil,
    platform.is_macos and "yabai" or nil,
    platform.is_debian_family and "ubi:sharkdp/fd" or nil,
    platform.is_arch_family and "yay" or nil,
  },
  
  configs = {
    "~/.zshrc",
    "~/.gitconfig",
    {
      path = "~/.ssh/config",
      template = true,
      secrets = true,
      private = true,  -- chmod 600
    },
  },
}
Git-Native Versioning

Every config change creates an immutable timestamped snapshot:

~/.config/zerb/
├── configs/
│   ├── zerb.lua.20250115T143022Z  # Latest
│   ├── zerb.lua.20250115T142510Z  # Previous
│   └── zerb.lua.20250115T141203Z  # Older
├── .zerb-active                    # Marker: "20250115T143022Z"
└── zerb.lua.active -> configs/...  # Symlink (local convenience)
  • All configs tracked in git
  • Full history and rollback capability
  • Sync across machines via git push/pull
  • Timestamped files never modified (immutable)
Complete Isolation

ZERB maintains complete isolation from system tools:

~/.config/zerb/
├── bin/                    # ZERB's private binaries
│   ├── mise               # Isolated mise binary
│   └── chezmoi            # Isolated chezmoi binary
├── mise/                   # mise data directory
│   ├── config.toml        # Auto-generated from zerb.lua
│   ├── installs/          # Tools installed here
│   └── shims/             # Added to PATH via shell activation
└── chezmoi/               # chezmoi data directory
    └── source/            # Dotfiles source

Benefits:

  • No conflicts with system package managers (apt, brew, etc.)
  • No conflicts with existing mise/chezmoi installations
  • Tools remain isolated but globally accessible via shell integration
  • Clean uninstall (just delete ~/.config/zerb/)
Drift Detection

ZERB performs three-way state comparison to detect drift:

  1. Baseline (declared): What's in zerb.lua
  2. Managed (ZERB): What ZERB has installed
  3. Active (environment): What's actually in PATH

This detects:

  • External package manager interference (apt, brew, nvm, etc.)
  • Version mismatches
  • Missing tools
  • Extra tools not in baseline
  • System installations taking precedence over ZERB's

Interactive resolution with three modes:

  • Individual: Choose action for each drift
  • Adopt all: Update baseline to match environment
  • Revert all: Restore environment to match baseline

Why Not Nix?

TL;DR: Nix and Home Manager are powerful and excellent for their use case, but they have a steep learning curve. ZERB prioritizes simplicity and wraps mature tools you may already know, making it accessible to developers who want declarative environment management without learning a new language and ecosystem.

When to Choose Nix/Home Manager

Nix is the better choice if you need:

  • System-level package management - Managing system packages, services, and kernel modules
  • Project-specific development environments - Nix dev shells provide isolated, reproducible environments per-project with declarative dependencies (e.g., nix develop, direnv integration)
  • Binary reproducibility - Bit-for-bit reproducible builds with cryptographic guarantees
  • Complex dependency graphs - Managing intricate package dependencies with precise control
  • Custom package definitions - Building packages from source with custom patches
  • NixOS integration - Full system configuration management on NixOS
  • Declarative system state - Managing everything from bootloader to desktop environment
  • Multi-user environments - Isolated environments for multiple users on the same system
  • Advanced rollback - Atomic system upgrades with instant rollback capability
When to Choose ZERB

ZERB is the better choice if you want:

  • Minimal learning curve - Familiar Lua syntax, wraps tools you may already use (mise, chezmoi)
  • User-space only - No system-level changes, no root required, no conflicts with system packages
  • Quick setup - Single binary, one config file, works in minutes, uses configuration files you already use
  • Git-native workflow - Standard git operations for versioning and syncing
  • Interactive UX - Smart prompts for version selection and drift resolution
  • Cross-distro portability - Works on any Linux distro without distro-specific knowledge (macos and windows coming soon!)
  • Lightweight configs - Small, readable Lua files vs. large Nix expressions
  • Tool-focused - Primarily for development tools and dotfiles, not system management
Key Differences
Aspect Nix/Home Manager ZERB
Learning Curve Steep (new language, concepts) Gentle (Lua, familiar tools)
Scope System + user packages User-space tools + dotfiles only
Config Size Large expressions (100s of lines) Small Lua files (10s of lines)
Tool Installation Nix packages (may build from source) mise backends (cargo, npm, ubi, github)
Dotfile Management Home Manager modules chezmoi (templates, secrets)
Platform Detection NixOS-centric Cross-distro Linux focus (macos and windows coming soon!)
Drift Detection Declarative state enforcement Interactive three-way comparison
Philosophy Pure functional, reproducible Pragmatic, wrapping mature tools
Setup Time Hours to days (learning required) Minutes (familiar concepts)
Root Required No (but system integration available) No (strictly user-space)
Example Comparison

Task: Install Node.js 20.11.0 and track your .zshrc file

Nix Home Manager:

# ~/.config/home-manager/home.nix
{ config, pkgs, ... }:

{
  home.username = "yourname";
  home.homeDirectory = "/home/yourname";
  home.stateVersion = "25.05";

  programs.home-manager.enable = true;

  home.packages = with pkgs; [
    nodejs_20
  ];

  # Maintain the .zshrc file yourself
  home.file.".zshrc".source = ./dotfiles/zshrc;
  # You could also use the pure nix way of setting the zsh home-manager options:
  # Example: programs.zsh.initContent = let zshConfigEarlyInit = lib.mkOrder 500 "do something"; zshConfig = lib.mkOrder 1000 "do something"; in lib.mkMerge [ zshConfigEarlyInit zshConfig ];

  # Optional: Use specific Node.js version
  # Requires overlay or custom package definition
}

Then run:

home-manager switch

ZERB:

-- ~/.config/zerb/zerb.lua
zerb = {
  tools = {
    "node@20.11.0",
  },
  
  configs = {
    "~/.zshrc",
  },
  
  git = {
    remote = "https://github.com/username/dotfiles",
    branch = "main",
  },
}

Then run:

zerb sync
Why ZERB Uses Nix for Development

But... ZERB itself uses Nix for its development environment (via flake.nix). Why?

  • Developer reproducibility - Ensures all contributors have identical toolchains (Go 1.22, golangci-lint, etc.)
  • CI/CD consistency - Same environment locally and in CI pipelines
  • Dependency management - Handles complex build-time dependencies (GPG tools, test utilities)
  • Zero setup friction - New contributors run nix develop and have everything they need

But here's the key difference: ZERB developers choose to use Nix because they value its power for development workflows. ZERB users don't need to learn Nix to get similar benefits for their own environments—ZERB provides declarative environment management, versioning, and reproducibility without requiring Nix knowledge.

Think of it this way: ZERB is built with Nix but doesn't require Nix. It's like how many Go programs are built with Make, but users don't need Make to run the compiled binary.

Can I Use Both?

Yes! Nix and ZERB can coexist peacefully:

  • Nix for system packages - Use Nix/Home Manager for system-level tools, services, and packages
  • ZERB for user-space tools - Use ZERB for development tools and dotfiles
  • No conflicts - ZERB maintains complete isolation in ~/.config/zerb/ and never touches system packages

Example hybrid setup:

# Nix manages system tools
home.packages = with pkgs; [
  firefox
  alacritty
  docker
];
-- ZERB manages dev tools
zerb = {
  tools = {
    "node@20.11.0",
    "python@3.12.1",
    "cargo:ripgrep",
  },
  configs = {
    "~/.zshrc",
    "~/.config/nvim/",
  },
}
Future: Enhanced Nix Awareness (Post-MVP)

Note on Project-Specific Environments: ZERB may explore project-specific environment support (similar to Nix dev shells or mise's .mise.toml project configs) in future versions, but the MVP focuses exclusively on global user-space tool and configuration management. For now, users needing per-project isolated environments should use Nix dev shells, mise's project-local configs, or similar tools.

After the MVP, ZERB will add Nix-aware drift detection to better support hybrid setups:

The Problem: Currently, if you have Node.js installed via Nix and also declare it in ZERB, drift detection will flag it as a conflict.

The Solution: Enhanced drift detection that recognizes Nix-managed tools and offers intelligent options:

$ zerb drift

Drift detected:

  node@20.11.0
    Declared:  node@20.11.0 (in zerb.lua)
    Managed:   not installed (ZERB)
    Active:    node@20.11.0 (detected: Nix/Home Manager)

What would you like to do?
  1. Acknowledge (mark as externally managed, skip in future checks)
  2. Take over (install via ZERB, may conflict with Nix)
  3. Ignore this time (ask again next drift check)

Choice [1-3]: 1

✓ Marked node@20.11.0 as externally managed (Nix)

Optional Config Syntax:

zerb = {
  tools = {
    -- Explicitly mark as externally managed
    { name = "node@20.11.0", source = "nix" },
    
    -- Or let drift detection discover it
    "python@3.12.1",  -- ZERB will install this
  },
}

Benefits:

  • No Nix dependency - ZERB users who don't use Nix are unaffected
  • Hybrid-friendly - Acknowledges that some users want both tools
  • Keeps ZERB simple - No Nix integration, just smarter drift detection
  • User choice - You decide which tool manages what

This feature respects ZERB's philosophy: simple, pragmatic, and user-focused—while acknowledging that power users may want to combine tools for different purposes.


Quick Start

Note: ZERB is in pre-pre-alpha development. Installation instructions below are for developers building from source.

Installation (Development Build)

Prerequisites: Go 1.21+ or Nix with flakes enabled

Option 1: Build from source

# Clone repository
git clone https://github.com/ZebulonRouseFrantzich/zerb.git
cd zerb

# Build binary
go build -o bin/zerb ./cmd/zerb

# Install to PATH (required for shell activation)
# Choose one:
mkdir -p ~/.local/bin
cp bin/zerb ~/.local/bin/zerb

# OR install system-wide:
sudo cp bin/zerb /usr/local/bin/zerb

Option 2: Nix development environment

git clone https://github.com/ZebulonRouseFrantzich/zerb.git
cd zerb
nix develop  # Enters dev shell with all tools
just build   # Builds to bin/zerb
cp bin/zerb ~/.local/bin/zerb  # Install to PATH

Ensure ~/.local/bin is on PATH (add to ~/.bashrc or ~/.zshrc if needed):

export PATH="$HOME/.local/bin:$PATH"

Verify installation:

which zerb     # Should show path to zerb binary
zerb --version # Should show version info
Usage
# Initialize ZERB
$ zerb init
# This creates the ZERB directory structure and downloads core components

# Add shell integration (follow instructions from init output)
$ echo 'eval "$(zerb activate bash)"' >> ~/.bashrc  # or ~/.zshrc
$ source ~/.bashrc  # Reload shell

# Verify ZERB is active
$ zerb --version

# Add tools interactively
$ zerb add python
# Select version from list, ZERB installs and updates baseline

# Add tools with specific versions
$ zerb add node@20.11.0 rust@1.75.0

# Track configuration files
$ zerb config add ~/.zshrc
$ zerb config add ~/.config/nvim/ --recursive

# Check for drift
$ zerb drift
# Interactive resolution of any differences

# Sync to remote
$ zerb push

# On another machine
$ zerb pull
# Automatically installs tools and applies configs

# Uninstall ZERB
$ zerb uninit
# Follow instructions to remove shell integration manually
Future: One-Line Installer (Pre-MVP)

Before the MVP release, ZERB will provide a one-line installer:

curl -fsSL https://zerb.dev/install.sh | sh

This will automatically:

  • Detect your platform (Linux amd64/arm64)
  • Download and verify the latest release
  • Install to ~/.local/bin/zerb
  • Configure PATH if needed

See Pre-MVP Tasks for installation roadmap.


Features

v1.0 Roadmap
Core Tool Management
  • Download and verify mise/chezmoi binaries (GPG + SHA256)
  • Install tools via mise (all backends: cargo, npm, ubi, github, core)
  • Complete isolation (environment variables + CLI flags)
  • Shell integration (mise activate)
  • Interactive version selection with caching (24-hour TTL)
  • Non-interactive version flags (@version, --latest)
  • Exact version pinning (no ranges in MVP)
  • Tool upgrade management
  • Tool removal
Configuration Management
  • Track dotfiles via chezmoi
  • Recursive directory tracking
  • Template processing support
  • Secrets integration (1Password, Bitwarden, age)
  • Private file permissions (chmod 600)
  • Config diff and preview
  • Config rollback
Platform Detection
  • Linux distro detection (Ubuntu, Arch, Fedora, Alpine, RHEL/CentOS, openSUSE, Gentoo)
  • Linux family detection (Debian, RHEL, Fedora, Arch, Alpine, SUSE, Gentoo)
  • Architecture detection and normalization (amd64, arm64 only in MVP)
  • Graceful fallback if distro detection fails
  • Platform-aware conditionals in Lua
  • Read-only platform table injection at VM initialization
  • zerb platform command for debugging
  • macOS detection (basic GOOS/GOARCH, post-MVP)
  • Windows detection (basic GOOS/GOARCH, post-MVP)
Git Integration
  • Automatic git initialization
  • Timestamped config snapshots in configs/ subdirectory
  • Simple, readable commit messages
  • Pre-commit hook with 5 integrity checks
  • Comprehensive .gitignore template
  • Config history and rollback
  • Remote sync (push/pull)
  • Stash recovery workflow
  • Baseline comparison
  • ZERB-guided conflict resolution
  • Stash management commands
  • Pre-push validation
Drift Detection & Resolution
  • Three-way state comparison (baseline, managed, active)
  • External override detection (system package managers)
  • Interactive drift resolution (individual mode)
  • Bulk resolution modes (adopt all, revert all)
  • Version detection caching (5-minute TTL)
  • User-facing terminology abstraction
  • Resume capability for interrupted operations
  • Drift-aware sync behavior
  • No persistent ignore (conscious decision-making)
Error Handling & Recovery
  • Transaction-based resume for multi-step operations
  • Active secret redaction in logs
  • Corrupted config recovery with rollback
  • Graceful offline degradation
  • Preflight checks (permissions, disk space, network)
  • Atomic writes for critical files
  • Consistent error messages and exit codes
  • Retry logic with exponential backoff
  • Config validation (zerb config validate)
  • Interactive repair tool (zerb config repair)
  • Log management and auto-cleanup (7-day retention)
Security Features
  • GPG signature verification (preferred)
  • SHA256 checksum verification (fallback)
  • Embedded GPG keyrings
  • No mirror fallback (security-first)
  • Hard-coded binary versions (reproducible builds)
  • Secret detection in pre-commit hook
  • Comprehensive .gitignore (prevent credential leaks)
  • Active secret redaction in logs
User Experience
  • Interactive version selection with pagination
  • Smart prompts for conflict resolution
  • Progress indicators for long operations
  • Helpful error messages with suggestions
  • Consistent command structure
  • Non-interactive mode support
  • Verbose logging flag
  • Dry-run mode
  • Shell completion (bash, zsh, fish)

Platform Support

MVP (v1.0)
  • Linux: Linux Mint (primary target)
    • Full distro detection (Ubuntu, Arch, Fedora, Alpine, RHEL/CentOS, openSUSE, Gentoo)
    • Family detection (Debian, RHEL, Fedora, Arch, Alpine, SUSE, Gentoo)
    • Platform-aware conditionals in Lua config
    • Architectures: amd64 and arm64 only (error on i386, arm 32-bit)
    • Graceful fallback if distro detection fails (continues with OS/arch only)
Post-MVP
  • macOS: Basic support (GOOS/GOARCH only)
    • No distro detection (distro field will be nil)
    • Apple Silicon detection via runtime.GOARCH
    • Rosetta 2: Reports binary's compiled architecture
  • Windows: Basic support (GOOS/GOARCH only)
    • No distro detection (distro field will be nil)

Configuration

Lua-Based Declarative Config

ZERB uses Lua for configuration, providing:

  • Cross-platform conditional logic
  • Programmatic generation (easy CLI modification)
  • Future-proof (can migrate implementations transparently)
  • Familiar syntax (used by Neovim, Hammerspoon, Nginx)
Platform API

Read-only platform table injected by ZERB:

platform = {
  os = "linux",            -- "linux" | "darwin" | "windows"
  arch = "amd64",          -- normalized: "amd64" | "arm64"
  arch_raw = "x86_64",     -- original GOARCH if needed
  
  -- Boolean helpers
  is_linux = true,
  is_macos = false,
  is_windows = false,
  is_amd64 = true,
  is_arm64 = false,
  is_apple_silicon = false,
  
  -- Linux-only (nil on macOS/Windows)
  distro = { id = "ubuntu", family = "debian", version = "22.04" },
  linux_family = "debian",
  
  -- Family booleans
  is_debian_family = true,
  is_rhel_family = false,
  is_arch_family = false,
  is_alpine = false,
  
  -- Helper function
  when = function(cond, value) return cond and value or nil end,
}
Configuration Schema
zerb = {
  -- Metadata
  meta = {
    name = "My Development Environment",
    description = "Full-stack web development setup",
  },
  
  -- Tool Management (via mise)
  tools = {
    "node@20.11.0",
    "python@3.12.1",
    "cargo:ripgrep",
    "npm:prettier",
    "ubi:sharkdp/bat",
    platform.is_linux and "cargo:i3-msg" or nil,
  },
  
  -- Configuration Files (via chezmoi)
  configs = {
    "~/.zshrc",
    "~/.gitconfig",
    {
      path = "~/.config/nvim/",
      recursive = true,
    },
    {
      path = "~/.ssh/config",
      template = true,
      secrets = true,
      private = true,
    },
  },
  
  -- Git Integration
  git = {
    remote = "https://github.com/username/dotfiles",
    branch = "main",
  },
  
  -- Configuration
  config = {
    backup_retention = 5,  -- Keep last 5 timestamped configs
  },
}

Architecture Overview

┌─────────────────────────────────────────────────────────────┐
│                     USER INTERFACE                          │
│  $ zerb add node@20                                         │
│  $ zerb config add ~/.zshrc                                 │
│  $ zerb sync                                                │
└──────────────────────┬──────────────────────────────────────┘
                       │
                       ▼
┌─────────────────────────────────────────────────────────────┐
│                    ZERB CORE (Go)                           │
│                                                             │
│  ┌──────────────┐  ┌──────────────┐  ┌──────────────────┐   │
│  │ CLI Handler  │  │  Lua Parser  │  │  Git Manager     │   │
│  │ (cobra)      │  │ (gopher-lua) │  │  (go-git)        │   │
│  └──────────────┘  └──────────────┘  └──────────────────┘   │
│                                                             │
│  ┌────────────────────────────────────────────────────────┐ │
│  │         Config Manager                                 │ │
│  │  - Parses zerb.lua                                     │ │
│  │  - Generates mise/chezmoi configs                      │ │
│  │  - Manages timestamped configs                         │ │
│  │  - Handles drift detection                             │ │
│  └────────────────────────────────────────────────────────┘ │
│                                                             │
│  ┌────────────────────────────────────────────────────────┐ │
│  │         Binary Manager                                 │ │
│  │  - Downloads mise/chezmoi from GitHub                  │ │
│  │  - GPG signature verification                          │ │
│  │  - SHA256 checksum verification                        │ │
│  └────────────────────────────────────────────────────────┘ │
└────────┬────────────────────────┬───────────────────────────┘
         │                        │
    ┌────▼────┐              ┌────▼────────┐
    │  mise   │              │   chezmoi   │
    │ Wrapper │              │   Wrapper   │
    └────┬────┘              └────┬────────┘
         │                        │
    ┌────▼────────────┐       ┌───▼─────────────┐
    │ ZERB's Private  │       │ ZERB's Private  │
    │ mise Binary     │       │ chezmoi Binary  │
    │                 │       │                 │
    │ Complete        │       │ Complete        │
    │ Isolation       │       │ Isolation       │
    └─────────────────┘       └─────────────────┘
Technology Stack
  • Language: Go 1.21+ (single binary)
  • CLI: spf13/cobra, spf13/viper
  • Lua: yuin/gopher-lua (pure Go, no CGO)
  • Git: go-git/go-git
  • Security: x/crypto/openpgp
  • Platform: github.com/shirou/gopsutil/v4/host (scoped to host package only)

Development Status & Roadmap

Current Status: Pre-Pre-Alpha

ZERB is in active development. The project plan is complete, but implementation has not yet begun.

Success Criteria (MVP)
  • ✅ Works on Linux (Linux Mint, specifically)
  • ✅ Downloads and verifies mise/chezmoi binaries
  • ✅ Installs tools via mise (all backends)
  • ✅ Manages configs via chezmoi
  • ✅ Complete isolation (no system conflicts)
  • ✅ Shell integration working
  • ✅ Git versioning with timestamped configs
  • ✅ Interactive version selection
  • ✅ Drift detection working
  • ✅ Config rollback functional
  • ✅ Git operations complete
  • ✅ >80% test coverage
  • ✅ Comprehensive documentation
Post-MVP Features
  • macOS/Windows full support
  • WSL/WSL2 detection
  • LTS metadata management
  • Fuzzy version matching
  • Version recommendations
  • Semantic version parsing
  • System package managers (apt/brew)
  • Rosetta detection
  • Auto-drift correction (optional)
  • Conventional commit messages (optional)

Contributing

Note: ZERB is not yet accepting contributions as the codebase is in early development. Once the MVP is complete and the API stabilizes, we'll welcome contributions.

Development Approach
  • Test-Driven Development (TDD): Strict test-first approach
  • Coverage Goal: >80% for all packages
  • Go Version: 1.21+
Development Environment

ZERB uses a Nix flake for reproducible development environments with all necessary tools and dependencies.

Quick Start
# Install Nix (if not already installed)
curl -L https://nixos.org/nix/install | sh

# Enable flakes (add to ~/.config/nix/nix.conf)
experimental-features = nix-command flakes

# Clone repository
git clone https://github.com/ZebulonRouseFrantzich/zerb.git
cd zerb

# Enter development environment
nix develop

# Initialize Go module (first time only)
just init

# Build and test
just build
just test
What's Included

The Nix dev shell provides:

  • Go 1.22 - Core language and toolchain
  • Development Tools - golangci-lint, goimports, gopls, delve
  • Testing Tools - gotestsum, go-junit-report
  • Component-Specific Tools - Tools for each component (added as implemented)
    • Lua interpreter and luacheck
    • GPG tools for binary verification
    • Shell testing tools (bash, zsh, fish)
    • Git and go-git dependencies
    • Platform detection utilities
  • Task Runner - Just (Justfile) for common commands
  • Documentation Tools - markdownlint-cli
Available Commands (via Justfile)
just test         # Run all tests
just lint         # Run linters
just build        # Build binary
just coverage     # Generate coverage report
just fmt          # Format code
just vet          # Run Go vet
just check        # Run all checks (lint + vet + test)
Directory Integration (Optional)

Enable automatic environment activation with direnv:

# Allow direnv for this directory
direnv allow

Now the development environment loads automatically when you cd into the project!

Editor Configuration

ZERB uses EditorConfig to maintain consistent coding styles:

  • Go files: Use tabs (community standard). Set your preferred tab display width in your editor.
  • Other files (YAML, JSON, Markdown, Nix): Use 2 spaces.

For Neovim users:

  • If you use vim-sleuth, it will automatically detect the project's indentation style
  • Set your personal tab display width preference in your config:
    vim.opt.tabstop = 2       -- Display tabs as 2 spaces wide (adjust to your preference)
    vim.opt.shiftwidth = 2    -- Indent by 2 spaces when using >> or <<
    
  • Ensure EditorConfig support is enabled (built-in for Neovim 0.9+, or use editorconfig/editorconfig-vim plugin)
AI-Assisted Development

ZERB is being built with the assistance of OpenCode, an AI-powered coding assistant that helps accelerate development while maintaining code quality and consistency.

How OpenCode Assists ZERB Development

OpenCode is used throughout the development process.

Agent Guidelines

ZERB uses an AGENTS.md file to provide OpenCode with project-specific context and guidelines:

  • Build/Test Commands - Standard commands for testing, building, and linting
  • Code Style - Go coding standards, naming conventions, and best practices
  • Architecture Constraints - Isolation requirements, security guidelines, and design principles
  • Testing Requirements - TDD approach, coverage goals, and testing strategies

This approach ensures that AI assistance is aligned with ZERB's specific architectural decisions, coding standards, and quality requirements. The AGENTS.md file serves as a contract between the project and AI tools, maintaining consistency across all AI-assisted development.

For more details on how to use AI tools effectively with ZERB, see the AGENTS.md file in the repository root.

Testing Strategy

Key test areas:

  • Binary management (download, GPG verification, SHA256 fallback)
  • Config versioning (timestamped files, rollback)
  • mise wrapper (tool installation, version resolution, isolation)
  • chezmoi wrapper (isolation verification, flag passing)
  • Drift detection (detection accuracy, user prompts)
  • Git operations (commit generation, sync, pre-commit hook, conflicts)
  • Shell integration (activation script generation)
  • Platform detection (distro detection, family booleans)

License

MIT-0 (MIT No Attribution) License - See LICENSE for details

ZERB is released under the MIT-0 license, which provides maximum freedom to use, modify, and distribute the software without requiring attribution. You can use ZERB in any project (personal, commercial, or otherwise) without needing to include copyright notices.


Acknowledgments

ZERB stands on the shoulders of giants:

  • mise by @jdx - Universal tool version manager
  • chezmoi by @twpayne - Dotfile manager
  • gopher-lua by @yuin - Lua VM in Go
  • cobra by @spf13 - CLI framework
  • go-git - Pure Go git implementation

Contact


Built with ❤️ for developers who value reproducibility and simplicity

Directories

Path Synopsis
cmd
zerb command
internal
binary
Package binary provides functionality for downloading, verifying, and managing the mise and chezmoi binaries that ZERB wraps.
Package binary provides functionality for downloading, verifying, and managing the mise and chezmoi binaries that ZERB wraps.
chezmoi
Package chezmoi provides an interface-based wrapper for chezmoi operations with complete isolation and error abstraction.
Package chezmoi provides an interface-based wrapper for chezmoi operations with complete isolation and error abstraction.
config
Package config provides secure Lua configuration parsing, generation, and management for ZERB's declarative environment management system.
Package config provides secure Lua configuration parsing, generation, and management for ZERB's declarative environment management system.
drift
Package drift provides drift detection functionality for ZERB.
Package drift provides drift detection functionality for ZERB.
git
Package git provides an interface-based wrapper for Git operations with context support and proper error handling.
Package git provides an interface-based wrapper for Git operations with context support and proper error handling.
platform
Package platform provides cross-platform detection and Lua integration for ZERB's declarative environment management.
Package platform provides cross-platform detection and Lua integration for ZERB's declarative environment management.
service
Package service provides high-level business logic for ZERB operations.
Package service provides high-level business logic for ZERB operations.
shell
Package shell provides shell integration functionality for ZERB.
Package shell provides shell integration functionality for ZERB.
testutil
Package testutil provides utilities for testing ZERB in isolation.
Package testutil provides utilities for testing ZERB in isolation.
transaction
Package transaction provides robust transaction management for config operations with locking, atomic writes, and recovery support.
Package transaction provides robust transaction management for config operations with locking, atomic writes, and recovery support.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL