Open-source project
ifd3f/caligula avatar
ifd3f/caligula

Caligula: a disk imager that takes the fear out of writing a whole drive

A user-friendly, lightweight TUI for disk imaging

2,359 stars39 forksRustGPL-3.0

At a glance

What is it?
A Rust TUI for imaging disks with graphs, hash validation, privilege escalation and a binary under 5 MB, plus a platform support matrix that tells you exactly where it has actually been tested.
Who is it for?
Caligula is a small program with an unusually honest README. It lists what it does, shows the exact commands it accepts, publishes a packaging status badge, and then spends more space explaining what its test matrix does and does not cover than most projects spend on their screenshots.
Can I use it commercially?
Yes, with conditions. GPL-3.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 20 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 28, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A friendly wrapper around a genuinely destructive operation

Writing a disk image is the kind of task where most command line tools offer a single flag and no feedback, and where a typo writes over the wrong partition. Caligula's stated goal is a user-friendly, lightweight TUI for imaging disks, and the design shows a decision that fewer imageries make: assume the user is nervous. The feature list includes rich confirmation dialogs so you don't accidentally destroy your filesystem, listing attached disks along with their size and hardware model, and verifying the disk after writing to make sure the data landed. In other words, the tool spends its complexity budget on making a destructive operation legible rather than on adding formats nobody uses.

The interface itself is a terminal application, built on the Rust TUI stack rather than a web view. The Cargo manifest pins ratatui at 0.26.3 with crossterm and the event-stream feature, and it also depends on inquire for prompts, indicatif for progress rendering and format-bytes for human readable sizes. The binary ships under 5 megabytes even when statically linked, which is a design constraint the README states as a feature rather than an accident.

Live graphs are listed first in the feature list, twice, with the second mention wearing a joke. It is still the practical point: when a write takes twenty minutes, a rate graph tells you whether the operation is progressing or stalled, and most alternatives show you a spinner.

The command surface is the documentation

The README embeds the generated help output directly between HTML comment markers, which is a pattern worth copying. The output is checked in as generated help and sits between `BEGIN GENERATED HELP OUTPUT` and `END GENERATED HELP OUTPUT`, so the flags a user reads are the flags the binary actually has.

code
Usage: caligula
       caligula burn [OPTIONS] <IMAGE>
       caligula help [COMMAND]...

Options:
  -h, --help     Print help
  -V, --version  Print version

The `burn` subcommand is the whole tool, and its options show the design decisions rather plainly. Compression takes a list of possible values including `ask`, `auto`, `none`, `gz`, `bz2`, `xz`, `lz4` and `zst`, and the default is `ask`, meaning the program asks rather than guessing. Hash validation has the same shape: `-s` takes a hash with a default of `ask`, `--hash-file` points at a file containing the expected hash, and `--hash-of` decides whether the digest was computed over the raw or the compressed file. Interactive mode, escalation behaviour and confirmation all use the same three-state pattern of `ask`, `always` and `never`, so a human gets a prompt once and a script gets determinism.

Two of those flags deserve attention. `--root` decides whether to try escalating privileges when writing to the output fails, which covers the case where you forgot to run as root, and `--force` skips the confirmation that would otherwise destroy the disk. That is the correct division of responsibility: unsafe behaviour is opt-in and visible in the help text.

Install paths that cover most Linux setups

Packaging is unusually thorough for a project of this size, and it starts with a Repology badge, which is the standard way to show how many distributions carry a package. The binary release route is the plain one: pre-built binaries from the latest GitHub release.

On Arch there are four separate options, which is worth pausing on. `pacman -S caligula` installs from the official extra repository, `caligula-bin` in the AUR is a package the project publishes automatically with every release, `caligula-git` in the AUR builds from the latest commit on `main`, and the archlinuxcn repository carries prebuilt binaries of that same git version. Having both a stable and a git channel in the AUR means testing a new commit is a one line change for anyone on Arch.

Nix users have the `nix-env -i caligula` route through Nixpkgs, plus a repository flake, and the README attaches a warning that is easy to miss and worth heeding: `main` can potentially break, so pin to a version. That is also why the Nix tree carries `flake.lock` and `shell.nix` next to `default.nix`, a sign that development happens inside the same environment the package is built in.

The remaining two routes are a third party Homebrew tap, `brew tap philocalyst/tap && brew install caligula`, and plain Cargo with `cargo install caligula`. Building from source is described as a relatively standard cargo project: clone and run `cargo build --release`. The manifest confirms it, with `edition = "2024"` and a `build.rs` at the root.

The platform matrix is the most useful page in the README

Most imageries publish a compatibility badge and leave it there. Caligula publishes a four row table with three levels of strictness, and the definitions are spelled out separately from the table, which is the part that makes it credible.

Linux x86_64 is the only row with a check in the full tests column, meaning the complete end to end VM test suite defined in the `checks/` directory runs there. Linux aarch64 builds automatically and gets no tests. Both macOS architectures build and pass basic tests, which are defined as unit tests plus a check that `caligula --help` works, but run no end to end suite. The maintainer is explicit that automated builds do not guarantee the tool works at all, and that basic tests mean it is likely to work with potential for uncaught issues between releases.

The platform notes are where the project is most candid. macOS has known bugs and very limited support, with two specific reasons: end to end setup is hard, tracked in issue 219, and automated escalation is broken, tracked in issue 125. Linux on non-x86_64 works in theory and has been used successfully, with aarch64 end to end tests tracked in issue 220 and riscv64 support in issue 221. Windows is issue 2 and BSDs is issue 3.

Read that matrix as a deployment decision rather than a limitation list. On x86_64 Linux, Caligula is a tool with an end to end test battery. On Apple silicon it is a tool that compiles and probably works. That is a narrower claim, and it is the accurate one.

What v0.5.0 changed, and what the dependencies reveal

The most recent stable release, v0.5.0, published in May 2026, is described as a very large refactor of roughly 3000 lines. The stated payoff is reliability and error handling rather than new capability: error messages and logging are much better, logs now record information about the OS, computer and terminal, and the program gives explicit instructions on how to report a problem. For a bug report that now means attaching logs plus the distribution channel you installed from, and the release notes note that log content can be omitted for anyone worried about privacy.

One earlier change from that era is a small illustration of care. The v0.5.0-rc.2 notes retract guidance from rc.1 about uploading coredumps, because coredumps can expose environment variables. Removing your own advice once you have realised it was unsafe is rarer than adding it in the first place.

The dependency list in `Cargo.toml` maps directly onto the feature list, which is a good sign for a project where the README makes claims. Compression is covered by `bzip2` with the static feature, `flate2` for gzip, `lz4_flex` with framing, and `ruzstd` for zstd. Hashing pulls in `sha1`, `sha2` and `md5`, aliased from the `md-5` crate to appease cargo-machete. The terminal stack is `ratatui` with `crossterm`, and `indicatif` handles progress. Privilege escalation uses the `nix` crate, which is the portable choice, and `libc` covers the gaps. `tokio` and `futures` sit there for async work, `test-strategy` for property tests, and `shell-words` for argument parsing. Even the closure over a project built around disk writes is careful about dependency hygiene.

The origin story explains the design

The README ends with two questions, and both of them are about motivation rather than usage. The first is why the project exists, and the answer is a complaint about size: the author had to image one too many USB drives and wanted a user-friendly `dd` alternative that was not 413 megabytes. The comparison is made with an actual measurement, unzipped balenaEtcher and checked with `du -sh`.

code
% unzip balenaEtcher-linux-x64-2.1.4.zip
% du -sh balenaEtcher-linux-x64
413M	balenaEtcher-linux-x64

That single number sets the ceiling for the whole design, and it explains the choices made elsewhere. A Rust binary with no runtime and no bundled Electron shell lands under 5 MB. A terminal interface needs no GPU or display server. A static build means it runs on a machine that has nothing else installed. The graphs, prompts and verification are all cheap in that budget, while an Electron runtime is not.

The second question is the name, and the answer is deliberately unserious: there used to be a tool called Nero Burning ROM, so the author picked another Roman emperor. It is described as a very uncreative name, which is the kind of self-awareness that usually goes with a small project that knows exactly what it is. Search engines will not return anything useful for the word, incidentally, so expect to filter aggressively.

Editorial conclusion

Caligula is a small program with an unusually honest README. It lists what it does, shows the exact commands it accepts, publishes a packaging status badge, and then spends more space explaining what its test matrix does and does not cover than most projects spend on their screenshots. That combination, a terminal interface that refuses to feel dangerous, and a binary small enough to download in seconds, is what earns its place next to balenaEtcher. The two things to check before committing are the platform row that matches your machine, since full end to end testing only happens on Linux x86_64 today, and the confirmation dialog behaviour if you plan to script it. Everything else is documented well enough that a five minute read will tell you whether it fits.

Frequently asked questions

Is Caligula safe to use on macOS or Apple silicon?

It builds on both macOS architectures and passes the basic tests, which are unit tests plus a check that the help output works, but it does not run the end to end VM suite there. The README calls macOS support very limited and names two known problems: end to end test setup is tracked in issue 219, and automated privilege escalation is broken in issue 125. Linux x86_64 is the only platform with full end to end coverage today.

How does Caligula verify that an image was written correctly?

Two separate mechanisms. The input image can be validated against a hash before writing, with md5, sha1, sha256 and others available, and you can point at a file containing the expected digest with `--hash-file` while `--hash-of` records whether it was computed over the raw or compressed file. After writing, the tool verifies the disk, so a successful run is not the same as a correct run.

How do I install Caligula on Arch Linux?

There are four routes. `pacman -S caligula` uses the official extra repository. The AUR has caligula-bin, which the project publishes automatically on every release, and caligula-git, which builds from the latest commit on main. The archlinuxcn repository also carries prebuilt caligula-git binaries, so an Arch user can pick a tagged release or a tracking build.

Why is the project named Caligula?

The author picked another Roman emperor because there used to be a tool called Nero Burning ROM, and describes it as a very uncreative name. The naming also creates a search problem, since the top results for the word are about the Roman emperor rather than about disk imaging.

Can Caligula handle compressed image files?

Yes. The compression flag accepts ask, auto, none, gz, bz2, xz, lz4 and zst, with ask as the default so the program asks rather than guessing. The Rust dependencies back this up: bzip2 with static features, flate2 for gzip, lz4_flex with framing and ruzstd for zstd.

Official sources

  1. ifd3f/caligula on GitHub
  2. Issues
  3. License: GPL-3.0
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/ifd3f-caligula.svg)](https://hysenlabs.com/projects/ifd3f-caligula)