One YAML file. One preview. One run. Fluxion shows you the exact commands it would execute — then runs that same traversal with mutation switched on. What you review is what happens.
curl --proto '=https' --tlsv1.2 -sSfL https://worxbend.github.io/fluxion.cr/install.sh | sh
The installer verifies the release's published SHA-256 before writing anything,
installs to ~/.local/bin/fluxion, and leaves your shell startup files alone.
Read it first if you would rather not pipe a script to a shell —
that is a reasonable instinct, and the script is short.
Preview and run are the same code path with one flag different, so a dry run cannot describe something other than what executes.
apiVersion: initkit.io/v1alpha1 kind: WorkstationProfile metadata: name: my-laptop spec: target: os: distribution: arch phases: - name: system-foundation steps: - name: core-cli-tools kind: pacman-packages spec: packages: [git, curl, ripgrep, zsh]
fluxion validateIs this profile sound?fluxion dry-runWhat would it do?fluxion applyDo it.Fluxion · arch-workstation · dry-run Target: arch Host: CachyOS (amd64) [PHASE] system-foundation core-cli-tools ▸ git ... would run $ sudo pacman -S --noconfirm git ▸ ripgrep ... would run $ sudo pacman -S --noconfirm ripgrep ▸ zsh ... would run $ sudo pacman -S --noconfirm zsh [DONE] system-foundation [PHASE] shell oh-my-zsh ▸ ~/.oh-my-zsh ... would run $ download https://raw.githubusercontent.com/…/install.sh verify 95118b50d0…0172b61 run sh [DONE] shell ⚠ Restart required Default shell changed to zsh. Log out and back in, then re-run fluxion. Summary: 0 ok · 0 failed · 0 skipped · 34 would run
A bootstrapper runs privileged commands on a machine you have not finished setting up. Each of these is deliberate, and each has a reason.
Every download Fluxion makes is HTTPS-only with no URL credentials, re-validated after each redirect — a redirect is an attacker-controllable hop — size-bounded while streaming rather than after, and digest-checked before use. A release asset that is not in Fluxion’s pinned digest catalog is not installed.
Installing binaries is binstaller’s job and installing fonts is
nerd-fonts-installer’s, each reading its own config. Fluxion
verifies the tool, then runs it; the checksums for what it installs live in
that tool’s profile. Set spec.policy.mode: strict to get back a hard
refusal of missing checksums and mutable URLs — fluxion lint says so
when it is absent.
PATH for anything privileged.
A sudo step becomes sudo -n -- <resolved target>, where the
target is a real path under a root-owned system directory with no writable ancestor.
There is no safe way to drop back to your account for the steps that must not end up root-owned.
Items marked confirm need --yes up front. A run that waits
for input is a run that hangs unattended.
A probe that cannot answer reports unknown, never missing. Absence of evidence is not evidence of absence, and reinstalling on that basis would be wrong.
Fluxion records what worked — versions, checksums — and fingerprints each phase's configuration. A completed phase is skipped only while that fingerprint still matches, so editing a package list makes the phase run again rather than being quietly considered done.
What is installed, missing, unknown, or drifted — probed against the real host.
Only what differs from this machine. The short list you actually read.
Why one phase or item would run or skip, in the orchestrator's own terms.
Keep the profiles you want everywhere in a git repository, and install them by id.
The clone lives in your cache directory and is disposable. What you install lives in your config directory and is yours — a sync refreshes the first and never touches the second, and tells you which of your configurations changed upstream.
Installing writes a file and stops. Running it stays a separate, deliberate step.
$ fluxion registry add https://github.com/you/profiles ✔ Registered profiles (https://github.com/you/profiles) syncing… ✔ 3 configurations available $ fluxion remote-ls example-profiles (profiles) Bootstrap configurations, one entry per role base Base tools current developer Developer workstation update available server Headless server not installed $ fluxion registry install developer --with-requires ✔ Installed base → ~/.config/fluxion/registries/… ✔ Installed developer → ~/.config/fluxion/registries/… Review before running: fluxion dry-run -c ~/.config/fluxion/…/developer.yaml
Phases declare dependencies, so ordering is a graph you can read and render —
fluxion graph emits Mermaid, DOT, or JSON.
Every phase and step can be selected by host facts. The same profile does the right thing on Fedora and on Arch, and says what it skipped.
One document shape, one validation path, one page describing it.
The safe commands come first. The one that changes anything comes last.
| generate | A starter profile for this machine |
| validate | Would this profile run at all? |
| lint | Profile quality and safety advice |
| doctor | Is this host ready for this profile? |
| plan | The execution plan — text, table, tree, or JSON |
| graph | The phase dependency graph (Mermaid, DOT, JSON) |
| status · diff · explain | What is installed, what differs, and why |
| dry-run | The real traversal with mutation switched off |
| apply | Do it |
| registry · remote-ls | Profiles shared through a git repository |
| snapshot · import | Turn what is installed into a profile |
| state · report | Inspect what previous runs recorded |
Fluxion was a Java 25 / GraalVM project. This is a ground-up Crystal reimplementation of the same product: same commands, same trust rules. State files written by the Java version are read directly, so upgrading does not mean reinstalling everything you already have.