Declarative dev-machine setup
Declare your dotfiles, packages, macOS defaults, and secrets in one file. BoomTube makes the real machine match — same fixed order, every run — and journals what it changed, so rollback can undo it. One binary, zero runtime deps.
curl -fsSL https://raw.githubusercontent.com/alxjrvs/boom/main/install.sh | sh
Three panels. That's the whole trick!
File in. Machine out!
The file goes in
[[section]] name = "Shell" link = [{ src=".zshrc" }] pkg = [{ manager="brew" }]your dotfiles repo
The machine comes out
✓ Packages
✓ macOS defaults
✓ Secrets
➜ boom source ▎ PREPARING FOR THE WORLD THAT'S COMING… ▎ DOTFILES...✓ ✓ ~/.zshrc linked ✓ ~/.gitconfig linked ▎ DIRECTORIES...✓ ✓ ~/.config created ▎ MACOS...✓ ✓ com.apple.dock autohide = 1 ▎ SOURCE...COMPLETE! 3 categories touched · all clear · 2.1s
One file — and BoomTube keeps it true!
The file is the machine you meant to have. BoomTube closes the gap between it and the one you've actually got — and records every change it makes, so you can undo any of it.
One file — the whole machine
Links, packages, macOS defaults, run steps, hooks — all declared in one typed boomfile.toml. It's validated up front, so a typo fails loudly at load instead of halfway through a run. Pull in someone else's sections with use and the module ships the files and hooks it declares — no vendoring.
Nothing it can't take back
Every run that changes something is journaled — undo record first, write second — and whatever it displaces is backed up before it moves. boom rollback replays that in reverse, and never claims an undo it didn't perform: a directory you've since filled is left standing and reported, not blown away.
Just a binary
One executable for macOS and Linux, runtime baked in. Nothing else has to be on the box for BoomTube to run.
Honest about drift
boom verify reports what's drifted without touching a thing. And if the config pull fails, BoomTube syncs from the last good clone instead of leaving you stuck.
Three verbs — one loop!
sync, verify, and uninstall aren't three scripts. They're the same walk over the same resources — only the action at each step changes. Teach BoomTube a new resource type once, and every verb already knows what to do with it.
The verbs
You run them as boom source (bare, or source sync), boom verify, and boom uninstall.
Every run walks this order
Can't say it declaratively? Write a hook.
A hooks/<name>.ts exports sync/verify/uninstall on a typed HookApi — and it is a first-class resource, not a trapdoor. It sees the run (repo, vars, os, host, profiles, --fix), declare()s the destinations it places so they land in the manifest and get reaped when you drop them, and journalWrite()s before it writes so boom rollback can undo it. Quiet when converged, like everything else. Modules can ship one.
It's all one file!
Typed, validated TOML — a list of sections, each declaring resources that run in phase order. Gate any section to an OS, a host, or any of several named profiles. Overlay files and used modules stack onto it — and when two layers name the same destination, the last one wins, dropped before the run instead of fought over during it.
[[section]] name = "Shell + git" link = [{ src = ".zshrc", dst = "~/.zshrc" }] [[section]] name = "Packages" pkg = [{ manager = "brew" }, { manager = "mise" }] [[section]] name = "macOS" when = { os = "darwin", profile = ["work", "home"] } # any of, per axis
What a section can hold
- link · copy · tmpl — symlink, copy, or render a template with
[vars](a globsrcfans out; per-machine without a hook) - secret — render a 0600 secret, never journaled in plaintext (1Password, env, pass, age/sops); a file BoomTube didn't render is left alone until
--fix - pkg — a Brewfile, mise tool versions, an apt/dnf/cargo/npm/pipx/gem/flatpak list, or gh CLI extensions — each entry says whether
uninstallreclaims it - osx_default · launchd · systemd — macOS defaults + agents, or generated systemd user units on Linux
- dir · check — ensure a directory exists; assert (and repair) file content
- run — a shell step tied to a verb, skippable with
unless/creates - hook — your own typed module
The rest of the arsenal!
The core loop — sync, verify — is the heart of it. Around that sit a handful of surfaces — one line apiece.
Bootstrap
Point BoomTube at your dotfiles repo — or start from nothing: boom init scaffolds, inits, and pushes a fresh config repo; boom adopt --from chezmoi|stow|… imports another manager. boom source set owner/repo
See everything
One screen for where the machine stands, a cross-machine view of your whole fleet, and a registry of shareable module packs. boom status · fleet · module
Code portals
Open portals to your repos — symlink them all into one dir for agents, or spin up a separate workspace for each. boom code …
Prove & recover
Validated on every load; gate CI with verify --ci, doctor the install, then roll back any journaled run. boom doctor · rollback
Still taking shape. This is the map, not the manual — the docs carry the exact reference, every flag and verb. Coming up from an older release? The v0.23 migration note says plainly what changed underneath you.
Bare metal to set up — five steps.
Get it running!
Your dotfiles repo is the source of truth — boom init can scaffold and push a fresh one for you, or write a boomfile.toml at the root of an existing repo. Point BoomTube at it, and from then on you just sync.
Install BoomTube
One self-contained binary — grab it with curl, or tap it from Homebrew (the repo is its own tap).
curl -fsSL https://raw.githubusercontent.com/alxjrvs/boom/main/install.sh | sh # or via Homebrew brew tap alxjrvs/boom https://github.com/alxjrvs/boom brew install boom
Write a boomfile.toml
Author it by hand at the root of your dotfiles repo. Each [[section]] declares resources — links, packages, macOS defaults. Start with one link and grow it.
# boomfile.toml — at your dotfiles repo root [[section]] name = "Shell + git" link = [{ src = ".zshrc", dst = "~/.zshrc" }] [[section]] name = "Packages" pkg = [{ manager = "brew" }]
Commit it with your dotfiles
BoomTube syncs from a git remote, not a local folder — so the boomfile ships inside your dotfiles repo. Commit and push to a repo you own.
git add boomfile.toml git commit -m "declare the machine" git push
Point BoomTube at the repo
One reference, once. This clones your repo, remembers it, and runs the first sync. Pin a reviewed state with @ref whenever you want it fixed.
boom source set owner/dotfiles # pin a reviewed tag or SHA boom source set owner/dotfiles@v1
Sync — prove — undo
From here on it's one loop. source makes reality match the file, verify reports drift without touching a thing, rollback walks the last run backward.
boom source # make it so boom source --dry-run # preview, touch nothing boom verify # what drifted? boom rollback # take it back
Whoever can write that repo can run code on your machine.
BoomTube syncs from a git remote you choose; run steps and hook modules execute as you. Treat push access to that repo like shell access, and pin to a tag or SHA when you want a fixed, reviewed state. Release binaries are checksum-verified.