rigging/CLAUDE.md
Christopher Mühl 6f555de30d
docs: add README and CLAUDE.md
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 01:18:29 +01:00

3.3 KiB

Rigging

Multi-repo NixOS + Nomad infrastructure management CLI and flake-parts module.

What this is

Three components:

  1. Flake-parts module (flake-module.nix) — repos import this to declare what they provide and expose a bosun-manifest package (JSON derivation)
  2. Nushell CLI (cli/rigging.nu) — reads ~/.config/bosun/config.toml, builds each repo's manifest via nix build, aggregates, dispatches commands
  3. Bash CLI (cli/default.nix) — repo-local Nomad job operations with runtime variable support

File layout

flake.nix              # exports flakeModules.default + lib
flake-module.nix       # the flake-parts module (top-level bosun.{meta,hosts} + perSystem bosun.{enable,jobsDir,...})
cli/
  default.nix          # bash bosun CLI (repo-local Nomad ops)
  rigging.nix          # nix wrapper for the nushell CLI
  rigging.nu           # nushell CLI source
lib/
  default.nix          # bosun library (discoverJobs, evalJob, compileJobs, etc.)
  nomad.nix            # nomad helpers (traefikTags, pinToHost, resources, etc.)
  nushell.nix          # writeNushellApplication (bundled, no overlay needed)

How consumers use it

Consumers add this as a flake input and import flakeModules.default. This gives them:

  • bosun.meta.name / bosun.hosts — top-level options for repo identity + host declarations
  • perSystem.bosun.{enable,jobsDir,nomadAddress,...} — Nomad job management
  • packages.bosun-manifest — always generated JSON manifest
  • packages.rigging — the multi-repo CLI
  • packages.bosun — repo-local Nomad CLI (only when bosun.enable = true)

The manifest is the key integration point: rigging builds each repo's manifest via nix build <repo>#bosun-manifest, reads the JSON, and knows what hosts/jobs each repo provides.

Key design decisions

  • No legacyPackages for vars: Runtime job evaluation with variables uses nix eval --expr inline (same pattern as the bash CLI). The legacyPackages.bosun.evalJobWithVars exists for backward compat but the CLI constructs the eval expression directly.
  • Rigging delegates Nomad ops: The nushell CLI is a thin orchestration layer. For actual Nomad operations (run, plan, stop, etc.), it delegates to the repo-local bash CLI via nix run <repo>#bosun -- <cmd>.
  • writeNushellApplication bundled: lib/nushell.nix is a self-contained copy so consumers don't need an overlay.
  • Top-level + perSystem split: bosun.meta/bosun.hosts are flake-level options (shared across systems). Nomad job config is perSystem (needs pkgs). The manifest bridges both by reading top-level config from within perSystem via closure over topArgs.config.bosun.
  • mkMerge/mkIf for config: The perSystem config uses mkMerge + mkIf (not // + lib.optionalAttrs) to avoid infinite recursion when the module system evaluates packages.

Vision

The end state: rigging is installed globally (via home-manager or devShell) and manages all infrastructure repos. Each repo is self-describing — rigging repo add <path> discovers everything. Commands like rigging host deploy alvin or rigging job run forgejo Just Work regardless of which repo owns the resource.

Phase 4 (pending): wire up dotfiles repo as a second consumer. Phase 5: drop the bash CLI once rigging fully replaces it.