Skip to content

Repository files navigation

🧰 workshop

Where the hausfold family gets built. Every repo in one directory, and bench — the CLI that moves a change across them.

pre-release · every path that could lose your work is either reversible by design or stops to ask you first. that's the intent, not a warranty — run it on a machine you can afford to rebuild, and tell us what breaks.

Five of them are Nix flakes, each pinning the ones upstream of it. Split a desktop across five repos and you buy yourself a daily annoyance: nothing you write is visible to its own neighbour until a lock file says so. bench is what makes that chain feel like one codebase — build your real Mac against your uncommitted edits, then push a change the whole way down.

the one gotcha

nebelung ──► pounce ──► haus ──► ~/.config/nix ──► your Mac
theme        palette    layer    host file         darwin-rebuild

That's the spine, not the whole graph: perch, trill, scruff and snug are inputs of haus too, and nebelung is one a second time, directly rather than through pounce. Eight edges in all — bench's EDGES has the list.

A flake input is not "whatever's on GitHub right now" — it's one exact commit, frozen in flake.lock. That's what makes a rebuild reproducible, and it's the catch: committing changes nothing downstream. Pushing changes nothing downstream. A one-hex-digit colour tweak in nebelung reaches your Mac only after three lock files move behind it.

Never walk that by hand. ./bench ship does it in order; ./bench status names every pin that's fallen behind. (Those are repo names. Your flake's INPUT name for the layer is your own — inputs.haus is what bootstrap.sh scaffolds. bench doesn't care which you pick: it reads the name out of your flake.lock. That matters because Nix does not fail an override naming an input that isn't there, so a hardcoded guess would build the pinned layer while reporting your branch.)

start

git clone https://github.com/hausfold/workshop && cd workshop
./bench clone          # plant every other repo beside this one

./bench status         # what this Mac is RUNNING · dirty trees · stale pins · agent lanes
./bench try            # build your real machine against the LOCAL checkouts
./bench try switch     # …and run it, for real (still nothing pushed)
./bench ship           # push upstream→downstream, updating each lock on the way
./bench ship pounce    # …narrowed to pounce + whatever consumes it, other edges untouched

try is the one that earns the repo. It builds your actual machine config out of your local, uncommitted checkouts — so you never push to find out whether something works, and main never holds code nobody has felt.

./bench …
status what's activated right now (the pinned build, or the branch a try switch put on it), every git and lock edge, every release edge
try [switch] build (and activate) against the local checkouts — worktree-aware, so it can build ONE unmerged branch
try lane [switch] same, plus every repo a scruff child spawned from this pane — a cross-repo lane in one rebuild
try-batch [switch] every open PR merged onto a throwaway tree per repo and built together in ONE rebuild, main untouched
ship push in dependency order, rippling each flake.lock
rebuild the plain pinned rebuild — the normal day
pull · clone fast-forward every repo · fetch the ones you're missing
release <repo> [version] stamp the version, tag it, then watch CI to the end — release + tap bump. The date is the version, except for scruff, which takes semver because five SDK registries share the number
overlap [--brief|--path <f>] what the OTHER agent lanes on this repo have already changed, and where their edits and yours land in the same region — measured from the shared object store, never declared
docs-since [--mark [--pending <repo>…] | --landed <repo>…] every commit since the docs were last reconciled, plus what a repo has read but not landed — the input to the scheduled docs sweep

the family

Five repos share the lock chain above:

  • 🏠 haus — the whole desktop, one Nix flake: the nix-darwin layer, plus hacker, the desktop built on it. start here.
  • 🐾 pounce — a keyboard-first command palette. every command is a file.
  • 🪺 perch — a file shelf that grows out of the notch.
  • 🌫️ nebelung — the silver-mist palette underneath all of it.
  • 🐈 scruff — worktree lanes, so parallel coding agents never fight over a checkout.

Two more are on the lock chain as inputs of haus, without being family: 🔔 trill (a quiet notification compositor) and 🐈 snug (how every one of these tools puts a line in your terminal — one Go package the Go tools import, one binary the shell ones drive, and the layer puts it on your PATH). For both, bench try builds your branch and bench ship ripples the lock, while bench status and ship leave their git state alone. They land through their own PRs.

Three more ride along with no lock edge at all, so the ripple never walks them: 🍺 homebrew-tap (CI-owned — you almost never touch it), ⌂ hausfold.co and 🐙 org-profile. bench clone plants them anyway; they carry docs. Your own ~/.config/nix — the host file naming your apps, your identity, your secrets — stays private, outside this directory, and is restored from its own repo.

This repo itself holds bench (and _bench, its zsh completion — symlink it into ~/.zsh-completions/ to get it on fpath) and one set of agent instructions. The docs, the product pages and the curl | bash one-liner all live at hausfold.co.

the life of a change

hack ──► test ──► assure ──► PR ──► batch-test ──► merge ──► ship ──► release

Coding agents draft on worktree-* branches in parallel, bench try proves a branch builds, a clean-context reviewer reads the diff cold, and bench try-batch feels the whole review queue in a single rebuild — before any of it lands on main.

more

  • workflows — daily driving, parallel agents, batch-testing, releasing
  • the three CLIshaus vs bench vs scruff
  • the agent surface — what every tool here owes a coding agent
  • the agent's own Mac — a headless macOS a lane can drive, so it never takes your screen
  • the factory — the night shift: docs-only PRs merge themselves under a lease you grant
  • bug reports — one issue form per repo, generated from one table
  • drift — the shapes a write-up goes wrong in, and what catches each
  • AGENTS.md — where a change goes, and the one instruction file every agent reads

⌂ hausfold

About

Every repo in the hausfold family, side by side — plus the bench CLI that moves changes between them

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages