A small, honest tarball installer

Debian supportedUbuntu supportedZorin OS supportedFedora supportedopenSUSE Tumbleweed supportedAlpine Linux supportedVoid Linux supportedArch Linux supported

Instead of asking people to extract a .tar.xz somewhere and run a random binary by hand, Tarminal installs the app into a standard location, creates a command, a desktop menu entry and an icon, tracks what it installed, and removes it cleanly later.

The project is split into two Cargo packages: tar-install, a reusable library, and tarminal, the CLI frontend built on top of it. If someone runs the bare tar-install binary directly, it just points them at tarminal.

Written in Rust, MIT licensed, maintained by TamKungZ_. The reusable core is published as the tar-install Rust crate and Python bindings for tools that want to build on the installer directly.

Tarminal terminal screenshot showing app installation from tarball
Tarminal installing an application from a plain tarball.

Install Tarminal

Debian / Ubuntu / Zorin

bash
curl -fsSL https://packages.tamkungz.me/gpg.key | \
  sudo gpg --dearmor -o /usr/share/keyrings/tamkungz-packages.gpg

echo "deb [arch=amd64 signed-by=/usr/share/keyrings/tamkungz-packages.gpg] https://packages.tamkungz.me/apt stable main" | \
  sudo tee /etc/apt/sources.list.d/tamkungz-packages.list

sudo apt update
sudo apt install tarminal
Optional: If you prefer packages built by Launchpad for Ubuntu Jammy or Noble, you can install from the PPA instead:
bash
sudo add-apt-repository ppa:tamkungz/stable
sudo apt update
sudo apt install tarminal

Fedora / RPM

bash
sudo tee /etc/yum.repos.d/tamkungz-packages.repo >/dev/null <<'EOF'
[tamkungz-packages]
name=TamKungZ Packages
baseurl=https://packages.tamkungz.me/rpm/$basearch/
enabled=1
gpgcheck=0
repo_gpgcheck=1
gpgkey=https://packages.tamkungz.me/gpg.key
EOF

sudo dnf makecache
sudo dnf install tarminal
Note: gpgcheck=0 is used for now — repo metadata is signed, RPM package signing is on the way.

openSUSE Tumbleweed

bash
sudo zypper ar https://download.opensuse.org/repositories/home:/TamKungZ_/openSUSE_Tumbleweed/home:TamKungZ_.repo
sudo zypper refresh
sudo zypper install tarminal
Published channels: packages are available from packages.tamkungz.me for Debian/Ubuntu, Fedora/RPM, Alpine, Void, and Arch. openSUSE Tumbleweed packages are built through Open Build Service.

Alpine (APK)

bash
sudo mkdir -p /etc/apk/keys
curl -fsSL https://packages.tamkungz.me/apk/tamkungz.rsa.pub | \
  sudo tee /etc/apk/keys/tamkungz.rsa.pub >/dev/null

echo "https://packages.tamkungz.me/apk" | \
  sudo tee -a /etc/apk/repositories

sudo apk update
sudo apk add tarminal
Void Linux (XBPS)
bash
sudo mkdir -p /etc/xbps.d
sudo tee /etc/xbps.d/tamkungz.conf >/dev/null <<'EOF'
repository=https://packages.tamkungz.me/xbps/$XBPS_ARCH
EOF

sudo xbps-install -S
sudo xbps-install tarminal
Arch Linux (pacman)
bash
curl -fsSL https://packages.tamkungz.me/gpg.key | sudo pacman-key --add -
sudo pacman-key --lsign-key release@tamkungz.me || true

sudo tee -a /etc/pacman.conf >/dev/null <<'EOF'
[tamkungz]
Server = https://packages.tamkungz.me/arch/$arch
SigLevel = DatabaseRequired PackageOptional
EOF

sudo pacman -Sy
sudo pacman -S tarminal

Published Packages — v0.2.0

PackageFormatChannel
tarminal_0.2.0-1_amd64.debDebian / Ubuntu/apt
tarminal-0.2.0-1.x86_64.rpmFedora / RPM/rpm/x86_64
tarminalopenSUSE TumbleweedOBS
tarminal-0.2.0-r0.apkAlpine APK/apk
tarminal-0.2.0-0-x86_64.pkg.tar.zstArch pacman/arch/x86_64
tarminal-0.2.0_1.x86_64.xbpsVoid XBPS/xbps/x86_64
tar-installRust crate / Python packagecrates.io / PyPI

GitHub Releases also publish standalone Linux binaries, .deb, .rpm, .tar.xz, SHA256SUMS, and detached .asc signatures. Full list on GitHub Releases →

Developer Packages

  • Rust crate: use the installer core directly from Rust applications.
  • Python bindings: reuse the shared library from Python tools.

Usage

bash
# Inspect tarball
tarminal inspect ./myapp-1.2.0-linux-x64.tar.xz

# Install with automatic detection
tarminal install ./myapp.tar.xz

# Manual config prompts
tarminal install ./app.tar.xz --config

# Use a recipe file
tarminal install ./app.tar.xz --recipe ./app.tarapp.yml

# System-wide install
sudo tarminal install ./app.tar.xz --system

# List installed apps (shows 'unknown' if no reliable version found)
tarminal list

# Remove an app
tarminal remove myapp

# Check installed app
tarminal doctor myapp
Output of tarminal --help
tarminal --help

Installation Paths

User install

paths
App files:   ~/.local/share/tarapp/apps/<app-id>/
Command:     ~/.local/bin/<command>
Desktop:     ~/.local/share/applications/<app-id>.desktop
Icon:        ~/.local/share/icons/hicolor/256x256/apps/<app-id>.*
State DB:    ~/.local/state/tarapp/apps.json

System install

paths
App files:   /opt/<app-id>/
Command:     /usr/local/bin/<command>
Desktop:     /usr/share/applications/<app-id>.desktop
Icon:        /usr/share/icons/hicolor/256x256/apps/<app-id>.*
State DB:    /var/lib/tarapp/apps.json

Supported Archives & Detection

Archive formats: .tar.xz, .txz, .tar.gz, .tgz, .tar.bz2, .tbz2, .tar

Filename detection

Tarminal first tries to infer app metadata from common filename shapes:

text
<app>-<version>-<os>-<architecture>.tar.xz
<app>_<version>_<os>_<architecture>.tar.xz

Executable detection

It then inspects the archive contents and looks for likely executable candidates, including names that match:

text
<app>
<app>-<architecture>
<app>_<architecture>
bin/<app>

If detection isn't good enough for a given tarball, fall back to tarminal install ./app.tar.xz --config or provide a recipe (below).

Detection fallback

  1. user-provided CLI / config / recipe version
  2. reliable archive filename parsing
  3. app metadata inside the installed directory (product-info.json, package.json, VERSION, etc.)
  4. runtime command probing (--version, -version, -v, version, -V)
  5. unknown/None if nothing reliable was found
Note: If automatic detection is not good enough for a tarball, use --config or provide a recipe.

Recipe Format

External: --recipe ./app.tarapp.yml  |  Embedded (inside the archive): tarapp.yml, tarapp.yaml, .tarapp.yml, .tarapp.yaml, manifest.yml, manifest.yaml

app.tarapp.yml
id: com.example.myapp
name: My App
version: 1.0.0
exec: MyApp
command: myapp
icon: assets/icon.png
desktop:
  categories:
    - Utility
  terminal: false

Recipes are optional, but they are the recommended way for communities or app authors to make tarball installs reliable.

Build From Source

bash
cargo build --workspace
cargo build --release -p tar-install --bin tar-install
cargo build --release -p tarminal

Rust workspace — tar-install library + tarminal CLI frontend.

Safety Behavior

Tarminal refuses to install archives with unsafe entries, regardless of recipe or CLI flags:

  • absolute paths
  • .. path traversal
  • unsafe or absolute symlink targets
  • hard-link entries (still unsupported)

Relative symlinks are allowed only when they resolve inside the extracted app tree. Anything that points outside the app tree is rejected.

Package Locally

Install the packaging tools once:

bash
cargo install cargo-deb cargo-generate-rpm

Build .deb

bash
cargo deb -p tar-install
cargo deb -p tarminal

Build .rpm

bash
cargo build --release -p tar-install --bin tar-install
cargo build --release -p tarminal

cargo generate-rpm -p crates/tar-install
cargo generate-rpm -p crates/tarminal
Inspect package contents
bash
for deb in target/debian/*.deb; do
  dpkg -I "$deb"
  dpkg -c "$deb"
done

for rpm in target/generate-rpm/*.rpm; do
  rpm -qpi "$rpm"
  rpm -qpl "$rpm"
  rpm -qpR "$rpm"
done

Release Process

Releases are handled by GitHub Actions when a version tag is pushed:

bash
git tag v0.2.0
git push origin v0.2.0

The workflow builds packages, signs artifacts, creates the GitHub Release, and publishes package-repository files to packages.tamkungz.me:

text
/gpg.key
/apt
/rpm/x86_64
/apk
/xbps
/arch
/apps/tarminal

/apps/tarminal is only this landing/documentation page — package managers install from /apt and /rpm/$basearch (and the Alpine/Void/Arch repositories above) directly.

Tagged releases also publish GitHub Release assets, OBS sources for openSUSE Tumbleweed, AUR PKGBUILD updates when credentials are configured, the tar-install crate on crates.io, and Python bindings through the pylib-tar-install workflow.

Project Structure

text
crates/
  tar-install/
    src/lib.rs          library exports
    src/bin/            hint command binary
    src/archive.rs      inspect tarball, detect binary/icon/manifest
    src/filename.rs     parse <app>-<version>-<os>-<arch>
    src/install.rs      install/remove/doctor logic
    src/ffi.rs          C ABI used by Python bindings
    src/desktop.rs      .desktop generation
    src/paths.rs        user/system install targets
    src/recipe.rs       manifest/recipe schema
    src/state.rs        installed apps database

  tarminal/
    src/main.rs         CLI frontend

pylib-tar-install/
  python/tarinstall/    Python bindings around libtar_install.so

Status

This is an early prototype designed for iteration — but the important architecture is already separated:

  • tar-install can be reused by other GUIs or tools
  • tarminal is only a CLI wrapper around it
  • recipes are optional but first-class
  • --config lets people fix bad filename/archive detection
  • package publishing is automated for GitHub Releases and packages.tamkungz.me
  • tar-install is published for Rust and Python developers

Changelog

addedchangednotes

v0.2.0

Added

  • openSUSE Tumbleweed install path through Open Build Service
  • Developer packages for the reusable tar-install core: Rust crate on crates.io and Python bindings on PyPI
  • Release automation for GitHub assets, package repositories, OBS sources, AUR updates, crates.io, and PyPI workflow triggers
  • Python binding layout through pylib-tar-install and a C ABI in src/ffi.rs

Changed

  • Installation docs now cover Debian/Ubuntu/Zorin, Fedora/RPM, openSUSE, Alpine, Void, and Arch from the main README
  • Repository layout now lists /apk, /xbps, and /arch as first-class package repositories
addedfixedchangednotes

v0.1.4

Added

  • Alpine APK, Arch Linux PKGBUILD, and Void Linux XBPS package formats
  • Runtime version detection fallback for when no reliable version is found from the archive filename
  • Metadata-based version detection: product-info.json (JetBrains IDEs), package.json / resources/app/package.json (Electron/Node apps), and plain VERSION/VERSION.txt/version.txt/build.txt/RELEASE files
  • Command probing fallback using --version, -version, -v, version, -V
  • --no-probe-version flag and probe_version: false recipe key to disable execution-based detection

Fixed

  • Improved version detection for apps that don't include a version in the archive filename
  • Fixed missing version metadata for Neovim, Blender, Java-based tools, and JetBrains IDE archives
  • Reduced weak filename guessing by preferring metadata / runtime probing over unreliable numeric fragments
  • Improved JetBrains archive handling by reading versions from product-info.json

Changed

  • Version detection now runs in a fixed order: user input → filename → metadata → runtime probe → unknown/None
  • Runtime probing happens only after extraction, against the actual installed executable path
  • Failed version probes no longer fail the install — they're recorded as install notes instead
Notes: runtime probing may execute the installed app with version flags — use --no-probe-version for untrusted archives. Some GUI apps may briefly open a window or write extra files when probed; metadata detection is always attempted first to reduce this.
fixedchangednotes

v0.1.3

Fixed

  • Improved filename parsing for dotted versions — blender-5.1.2-linux-x64.tar.xz
  • Fixed architecture parsing for x86_64 filenames
  • Fixed false version detection where 64 was stored as version
  • Added recognition for macos, darwin, osx, windows, win64
  • Platform guard: non-Linux archives rejected by default

Changed

  • Version stored as unknown/None when unreliable
  • tarminal list displays unknown for missing version
  • CLI flags, --config, and recipe YAML take priority
fixedadded

v0.1.2

Fixed

  • sudo tarminal install no longer installs into /root/.local/...
  • Root/sudo now defaults to system scope automatically
  • Force root-user scope with --scope user if needed

Added

  • Install progress display — extraction, copying, desktop integration
  • Progress events from the tar-install library
bash
# Clean up old root-user install if needed
sudo tarminal remove blender --scope user
fixedsecurity

v0.1.1

Fixed

  • Safe relative symlinks now allowed during install
  • Symlinks preserved when copying to final install directory
  • Real-world tarballs with bundled library symlinks (e.g. Blender) now work

Security

  • Unsafe symlink targets still rejected
  • Absolute symlink targets rejected
  • .. path traversal rejected
  • Hard-link entries remain unsupported