v0.26.0

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
Quick start →

Three panels. That's the whole trick!

File in. Machine out!

01 · Declare

The file goes in

[[section]]
name = "Shell"
link = [{ src=".zshrc" }]
pkg = [{ manager="brew" }]
your dotfiles repo
Sync!
sync · verify · rollback
03 · Done

The machine comes out

Shell + git
Packages
macOS defaults
Secrets
exactly what the file said
boom source — live readout
 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

sync makes reality match the file
verify reports drift — changes nothing
uninstall tears down what BoomTube placed
--fix not a verb — a sync that overwrites drift instead of skipping it

You run them as boom source (bare, or source sync), boom verify, and boom uninstall.

Every run walks this order

01link
02copy
03tmpl [vars]
04secret op · env · pass · age
05dir
06pkg brew · mise · gh · …
07osx_default
08launchd / systemd
09run unless · creates
10check
11hook

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.

boomfile.tomlillustrative
[[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 glob src fans 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 uninstall reclaims 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.

boom source — sync your machine boom verify — prove it boom status — the whole picture boom source --fix — mend drift boom rollback — undo

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.