Popsicle flashes many USB drives at once, and its packaging still points at 2024
Multiple USB File Flasher
At a glance
- What is it?
- Popsicle is a Rust utility from Pop!_OS that writes an image to several USB devices in parallel, with a CLI and a GTK front end. The code is recent but the newest tagged release is 1.3.3 from 2024-01-09, so most users will build from source.
- Who is it for?
- Popsicle is a good fit for a workshop that needs the same image on a rack of USB drives, since the parallel write and the device list that refreshes as drives come and go are the whole point of the tool. It is the wrong choice for a single drive or for a machine that cannot install to /usr/local, because the Makefile installs into /usr/local by default and the README documents no user-level install path.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 2 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 October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem: one image, a dozen identical sticks
Popsicle is a Linux utility for flashing multiple USB devices in parallel, written in Rust. The scenario it targets is narrow and very real: a technician with a box of identical USB drives who needs the same image on every one of them, and who does not want to run a copy command once per drive while watching progress bars.
The screenshots in the README follow the shape of the workflow. There is an image selection step, then a device selection step, then the flashing stage, then a summary. The device list, the README notes, dynamically refreshes as devices are added and removed, which matters more than it sounds. A USB hub that is plugged in halfway through a batch should appear without restarting the tool, and a drive that is pulled out should disappear rather than remain as a stale target.
The project ships under MIT and is developed in the Pop!_OS organisation, with the Cargo manifest listing two System76 authors. It is not a general disk imaging suite. Its scope is the repeated-write case, and the interface reflects that narrowness.
One Rust library, two front ends in a Cargo workspace
The repository is split into a library and two binaries. Cargo.toml declares the package name popsicle with the library at src/lib.rs, and a workspace with members cli and gtk. The Rust manifest is the fastest way to see what the project actually depends on: usb-disk-probe for finding removable devices, mnt for mount information, ron and serde for the serialization format used in configuration and state, srmw for writing images, thiserror and anyhow for error types, and async-std with the futures crates for the asynchronous side of parallel writes.
The two front ends are separate crates because they need different things. The CLI needs nothing beyond cargo. The GTK front end needs GTK and D-Bus development packages, which the README names as libgtk-3-dev and libdbus-1-dev. That distinction is why the build instructions offer three separate targets rather than one, and it means a headless build server can skip the graphical half of the project entirely.
The Rust edition is 2021 and the manifest declares rust-version 1.70.0 as the floor. The repository also carries a rust-toolchain file, so a clone with the right toolchain manager installed will use the pinned compiler rather than whatever cargo finds on the path.
The Makefile treats the CLI and the GTK app as different products
The Makefile reveals more about the project than the README does. It builds two binaries with different names, popsicle and popsicle-gtk, and it tracks the sources for each separately with CLI_SOURCES, GTK_SOURCES and SHR_SOURCES, where SHR covers the shared library in src.
Installation is handled by install-cli and install-gtk targets. The CLI install places the binary in the bin directory and also installs a compressed man page under share/man/man1, which means the CLI is expected to be used from a terminal with documentation available through man. The GTK install places popsicle-gtk in the same bin directory along with its assets, desktop entry and icons. The application ID is com.system76.Popsicle, and the same string appears as a JSON file at the top of the repository, alongside an appimage.sh script and an appimagecraft.yml configuration for AppImage builds. A debian/ directory covers Debian style packaging.
The prefix handling is worth noticing because it decides where the tool lands. The default is /usr/local, and prefix can be overridden, with DESTDIR support threaded through the install commands. That makes the tool usable inside a package build, but it also means the default install needs root, and the README documents no alternative for a user who cannot write to /usr/local.
Building from source with three documented make targets
The README gives three installation paths, and they are worth quoting exactly because the choice determines what ends up on the system. Building only the CLI keeps the dependency list down to cargo alone, which is the sensible choice on a server or in a container image.
make cli && sudo make install-cliThat target builds the CLI workspace and installs the binary and its man page. The GTK route installs the graphical front end instead.
make gtk && sudo make install-gtkAnd the combined target covers both workspaces in one pass.
make && sudo make installThe build itself is driven by cargo. The Makefile sets a RELEASE variable of debug and switches to release when DEBUG is 0, appending the --release argument, so a default make produces an optimised build. A second switch, VENDORED, adds --frozen to the cargo arguments when it is set to 1, which is what you want once the crate sources have been vendored and the machine has no network access. Clean and distclean targets exist too, and distclean removes the .cargo and vendor directories along with vendor.tar.
The README does not document the command line flags of the CLI or the GTK application in the pages shown, so the man page installed by install-cli is the reference to read after installing.
Vendoring crates for a build with no network
Popsicle handles the offline case explicitly. Crate dependencies are fetched from Crates.io, and for anyone who needs to vendor them the README points at cargo-vendor and the make vendor target. That target creates a .cargo directory, runs cargo vendor, trims the last line of the output into .cargo/config, appends a directory = "vendor" entry to that config, packs the vendor tree into vendor.tar and then removes the vendor directory itself. Leaving the tree only as a tarball keeps the working copy small.
Once that tarball is unpacked and the vendor directory restored, building with VENDORED=1 set adds the --frozen flag to cargo, which forbids cargo from touching the network or changing the lock file. Combined with the committed Cargo.lock, that gives a reproducible build.
The vendor target runs cargo vendor with its output piped through head -n -1, which drops the final line of the output before it is written into .cargo/config. This is the standard way to strip the informational trailer cargo prints, and it explains why the config file ends up as a cargo configuration with a directory pointing at the vendored sources rather than a copy of the full output.
Translations use Project Fluent, and each language is one pull request
Localisation is handled with Project Fluent rather than gettext, and the README says so plainly, with the reason given as being easier to work with. Translation files live in the i18n directory at the top of the repository.
The contribution rule is specific: translators are asked to submit one commit per language added or improved, with a message in the form below.
i18n(eo): Add Esperanto language supportA per-language commit convention is worth respecting for a project like this. It keeps a diff for one language reviewable on its own, which matters when a translation file is a long list of message identifiers and one edit would otherwise be buried in a mixed commit.
The i18n directory being a top-level entry also tells you the front ends read their strings from there, so a new locale means adding a Fluent file and submitting the change. The README does not describe the fallback behaviour when a key is missing from a translation, so a partially translated locale is worth checking against the base language before shipping it.
Where Popsicle falls short, and how it compares to writing one drive at a time
The honest limitation is the release cadence and the packaging surface. The last push to the repository was on 2026-10-15, so the code is moving, but the newest tagged release is 1.3.3 dated 2024-01-09, with 1.3.1 from 2022-12-05 and 1.3.0 from 2020-11-06 before it. Version 1.3.3 is also the version in Cargo.toml, so the manifest and the newest tag agree. A project can ship tagged releases rarely and stay perfectly healthy, but if you want a fixed tarball for a workshop image, the tag is 1.3.3 and not the current tree.
The second limit is operational. Parallel writing to many drives at once will saturate the bus, and the README says nothing about how Popsicle paces concurrent writes, whether it verifies each write afterwards, or how it behaves when one device in a batch fails mid-run. The summary screen at the end of the flow suggests results are reported per device, but the detail of that report is not described. With raw image writing, a silent failure is worse than a loud one, so this is worth confirming on your own hardware with a disposable drive before a batch run.
The alternative approach is a script that writes the image to one drive at a time with a plain copy command. That approach is slower, has no device list that refreshes, and offers no summary, but it needs no toolchain, no GTK and no root, and each write is easy to verify by hand. Popsicle earns its place when the batch size is large enough that the manual approach is the bottleneck. It is overkill for one drive, and it is the wrong tool when the image must be verified cryptographically against a known hash, since the README makes no mention of checksum validation.
Editorial conclusion
Popsicle is a good fit for a workshop that needs the same image on a rack of USB drives, since the parallel write and the device list that refreshes as drives come and go are the whole point of the tool. It is the wrong choice for a single drive or for a machine that cannot install to /usr/local, because the Makefile installs into /usr/local by default and the README documents no user-level install path. Before adopting it, check that the target machine can build with Rust 1.70.0 or newer, that the device list it shows matches the drives you intend to write, and that you can live without a tagged release, since the newest one is 1.3.3 dated 2024-01-09.
Frequently asked questions
What are the build dependencies for Popsicle?
The CLI needs only Rust's cargo utility. Building the GTK front end additionally requires the GTK and D-Bus development packages, usually named libgtk-3-dev and libdbus-1-dev.
How do I build and install Popsicle on Linux?
The included Makefile offers three routes: make cli && sudo make install-cli for the CLI only, make gtk && sudo make install-gtk for the GTK front end, or make && sudo make install for both. The default prefix is /usr/local and prefix can be overridden.
What Rust version does Popsicle require?
The Cargo manifest declares rust-version 1.70.0 and uses edition 2021. The repository also contains a rust-toolchain file, so the pinned toolchain is used when your toolchain manager reads it.
How do I build Popsicle without network access?
Install cargo-vendor and run make vendor, which creates vendor.tar and the .cargo/config pointing at a vendor directory. Building with VENDORED set to 1 adds the --frozen flag so cargo does not reach the network or change Cargo.lock.
Which license is Popsicle released under and where is the latest release?
The Cargo manifest lists the project as MIT licensed. The newest release tag is 1.3.3 dated 2024-01-09, and that same version appears in Cargo.toml.
Official sources
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.
[](https://hysenlabs.com/projects/pop-os-popsicle)Was this useful?