No description
- D 61.6%
- Rust 37.2%
- HTML 0.7%
- Makefile 0.4%
- Shell 0.1%
| target | ||
| unipack-core | ||
| unipack-creator | ||
| unipack-installer | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| comprehensive_test.sh | ||
| CONFIG_FIX_SUMMARY.md | ||
| end_to_end_test.sh | ||
| FUNCTIONALITY_FIXES.md | ||
| IMPORT_IMPROVEMENTS.md | ||
| LICENSE | ||
| quick_start.sh | ||
| README.md | ||
| TAURI_CONFIG_FIX.md | ||
| test_import.sh | ||
UniPack — Universal Linux Package Format
One format. Every distro. No bullshit.
UniPack is a dead-simple universal package format for Linux. A .unipack file is
literally a .tar.xz archive with a METADATA.toml prepended — nothing exotic.
The smart part is the installer, which detects your distro and does the right thing:
native pacman on Arch, builds a .deb on Debian/Ubuntu, builds an .rpm on Fedora,
and falls back to ~/.local install everywhere else.
Why?
| Problem | Solution |
|---|---|
| AppImages don't integrate with the system | UniPack installs like a real package |
| AppImages need FUSE / throw FUSE errors | UniPack is a plain tar.xz extract |
| Snap needs a background daemon | UniPack has zero runtime overhead |
| Flatpak bundles its own runtime | UniPack uses native system libraries |
| Maintaining distro packages is hell | One .unipack file works everywhere |
Components
unipack/
├── unipack-core/ # Shared Rust library (pack, unpack, install, distro detect)
├── unipack-creator/ # Tauri GUI — create .unipack files
│ ├── src/ # Frontend HTML
│ └── src-tauri/ # Rust backend
├── unipack-installer/ # Tauri GUI — install .unipack files
│ ├── src/ # Frontend HTML
│ └── src-tauri/ # Rust backend + MIME type assets
└── website.html # Project website (single file)
Format
A .unipack file is a .tar.xz archive containing:
METADATA.toml ← always the first entry
payload/
bin/myapp
share/applications/myapp.desktop
share/icons/hicolor/48x48/apps/myapp.png
lib/...
METADATA.toml
[package]
name = "myapp"
display_name = "My App"
version = "1.0.0"
description = "Does cool stuff"
author = "You"
license = "MIT"
arch = "x86_64"
format_version = 1
[install]
prefix = "/usr"
executable = "bin/myapp"
supports_user_install = true
[dependencies]
arch = ["openssl"]
debian = ["libssl3"]
fedora = ["openssl-libs"]
[scripts]
post_install = "gtk-update-icon-cache -f /usr/share/icons/hicolor"
[desktop]
name = "My App"
exec = "bin/myapp"
icon = "myapp"
categories = "Utility;"
terminal = false
Distro support
| Distro | Method | Notes |
|---|---|---|
| Arch Linux | pacman -U on renamed tar.xz |
Native package |
| Manjaro, EndeavourOS, CachyOS | Same as Arch | Arch-compatible |
| Debian, Ubuntu, Mint, Pop!_OS | Builds .deb → dpkg -i |
On-the-fly |
| Fedora, RHEL, AlmaLinux, Rocky | Builds .rpm → rpm -i |
On-the-fly |
| openSUSE | Builds .rpm → zypper install |
On-the-fly |
| Void Linux | Extracts to ~/.local |
User install |
| Alpine Linux | Extracts to ~/.local |
User install |
| Any other | Extracts to ~/.local + .desktop |
Fallback |
Prerequisites
- Rust 1.75+ (
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh) - Tauri CLI (
cargo install tauri-cli) - WebKit2GTK (Arch:
webkit2gtk, Debian:libwebkit2gtk-4.1-dev) pkg-config,libssl-dev(or equivalent)
Building
# Build everything
cargo build --workspace
# Build creator GUI
cd unipack-creator/src-tauri
cargo tauri build
# Build installer GUI
cd unipack-installer/src-tauri
cargo tauri build
# Register .unipack MIME type (so double-click works)
sudo xdg-mime install unipack-installer/src-tauri/assets/unipack-mime.xml
sudo update-mime-database /usr/share/mime
sudo cp unipack-installer/src-tauri/assets/unipack-installer.desktop /usr/share/applications/
sudo update-desktop-database /usr/share/applications
Usage
Creating a package
- Launch
unipack-creator - Point "Source Directory" at your build output (the directory that would become
/usr) - Fill out the metadata form — name, version, description, arch, dependencies
- Enable "Desktop Entry" if your app has a GUI
- Click Pack → you get
myapp-1.0.0.x86_64.unipack
Installing a package
Double-click the .unipack file in your file manager (after registering the MIME type), or:
unipack-installer myapp-1.0.0.x86_64.unipack
The GUI shows you package info, lets you choose user vs system install, then installs.
Library usage
use unipack_core::{
pack::{pack, PackOptions},
install::{install, InstallOptions, InstallScope},
unpack::read_metadata,
};
// Read metadata from a .unipack
let meta = read_metadata(Path::new("myapp.unipack"))?;
println!("{} v{}", meta.package.name, meta.package.version);
// Install a .unipack
let result = install(InstallOptions {
unipack_path: PathBuf::from("myapp.unipack"),
scope: InstallScope::User,
verify_checksum: true,
install_deps: true,
progress: Some(Box::new(|stage, msg| println!("[{stage}] {msg}"))),
})?;
License
MIT — see LICENSE.