Un gestore di AppImage nativo per KDE, scritto in Rust.
Al click su un file .AppImage in Dolphin appare una finestra di conferma
(kdialog); se accetti, l'AppImage viene copiata in ~/.local/bin, viene
creata la voce nel menù di KDE (icona + .desktop) e l'app viene
avviata. Include anche list e uninstall.
Stato: progetto greenfield, funzionante e testato su KDE Plasma con un'AppImage reale (ZCode).
- Click-to-install: il click su un'AppImage in Dolphin apre la conferma, poi installa e avvia (come AppImageLauncher, ma minimale e KDE-native).
- Integrazione menù completa: copia l'eseguibile, riscrive il
.desktopcon il path assoluto, installa tutte le icone hicolor, aggiorna la cache delle icone e il database dei.desktop. - List / Uninstall: elenca le AppImage installate e rimuovile (binario, voce di menù e icone) con conferma.
- Niente esecuzione dell'AppImage durante l'installazione: i metadati
(
.desktop, icone) sono estratti leggendo direttamente il payload squashfs tramiteunsquashfs, mai eseguendo il file. - Zero runtime pesanti: solo Rust +
kdialog. Nessun binding Qt.
Runtime (già presenti su una KDE Plasma standard):
kdialogunsquashfs(pacchettosquashfs-tools)xdg-mime,xdg-icon-resource(pacchettoxdg-utils)update-desktop-database,gtk-update-icon-cache
Build:
- Rust ≥ 1.85 (edition 2024). Installa con
rustupo il pacchetto della tua distro (rust+cargo).
cargo build --release
# binario: target/release/app-image-managerSe non hai Rust installato — o vuoi riprodurre esattamente l'ambiente della CI —
usa l'infrastruttura in docker/. Funziona con podman o docker, e
docker/run.sh non richiede nessuna implementazione di compose:
docker/run.sh test # cargo fmt --check + clippy + cargo test (job "build" della CI)
docker/run.sh fmt # riformatta i sorgenti con rustfmt
docker/run.sh build # binario release -> dist/app-image-manager
docker/run.sh deb # pacchetto Debian/Ubuntu -> dist/*.deb
docker/run.sh rpm # pacchetto Fedora 44 -> dist/*.rpm
docker/run.sh ci # tutti e quattro, in sequenza
docker/run.sh shell # shell interattiva con il toolchain
docker/run.sh clean # svuota le cache (volumi cargo + target)Con un compose disponibile, gli stessi servizi sono in docker/compose.yaml:
docker compose -f docker/compose.yaml run --rm testDettagli che vale la pena conoscere:
- Le immagini non contengono i sorgenti: il working tree è montato in
/srca runtime, quindi una modifica al codice non richiede nessun rebuild dell'immagine. target/è un volume, non la cartella dell'host: dentro il container si compila con un toolchain e una glibc diversi, e mescolare le due cose in una sola directory costringerebbe a ricompilare tutto ad ogni cambio. Il tuotarget/locale resta intatto; gli artefatti finiscono indist/.- Immagini base allineate alla CI:
ubuntu:22.04per test e.deb(glibc 2.35, quindi il binario gira anche su 24.04+),fedora:44per l'.rpm. È la distro a fissare la glibc del pacchetto, per questo sono pinnate. - Limite di CPU: di default il container usa metà dei core, così una
compilazione non blocca il desktop. Alza con
AIM_CPUS=16 docker/run.sh ci.
Copia il binario in una directory nel PATH (utente):
mkdir -p ~/.local/bin
cp target/release/app-image-manager ~/.local/bin/Assicurati che ~/.local/bin sia nel PATH (di solito lo è su KDE Plasma).
Registra il tool come handler predefinito per i MIME type delle AppImage, così il click in Dolphin apre la finestra di conferma:
app-image-manager setupQuesto scrive ~/.local/share/applications/appimage-handler.desktop (con
Exec=...app-image-manager handle %f) e lo registra come default per
application/vnd.appimage e application/x-appimage tramite xdg-mime.
Solo tipi MIME specifici delle AppImage. Il tool non si registra su
application/octet-stream: è il tipo generico che il database freedesktop assegna a qualsiasi file binario non riconosciuto (firmware,.bin, immagini disco, dati sconosciuti), quindi rivendicarlo faceva comparire la richiesta di installazione su file che non c'entravano nulla con le AppImage. Se hai installato una versione precedente alla 0.1.3, l'aggiornamento del pacchetto — o una nuova esecuzione diapp-image-manager setup— rimuove l'associazione obsoleta.
Nota su Dolphin: Dolphin può avere l'azione "Esegui" per i binari eseguibili. Affinché il click singolo apra la conferma di installazione (e non esegua direttamente l'AppImage), il MIME type del file deve risultare
application/vnd.appimageoapplication/x-appimage. Se Dolphin mostra "Tipo: sconosciuto" o "eseguibile", rigenera il database MIME o usa Apri con → AppImage Manager la prima volta, quindi imposta "Ricorda l'associazione". In alternativa, imposta Dolphin per aprire i file con un singolo click (Impostazioni di Dolphin → Comportamento).
# Click in Dolphin → equivalente a:
app-image-manager handle /percorso/al/App.AppImage
# Installazione non interattiva (script/CLI)
app-image-manager install /percorso/al/App.AppImage
# Elenca le AppImage installate
app-image-manager list
# Disinstalla (con conferma kdialog)
app-image-manager uninstall <nome>
# Disinstalla senza prompt (script)
app-image-manager uninstall <nome> --yesDove <nome> è mostrato da list (es. zcode), derivato dal campo Name
del .desktop interno, normalizzato in minuscolo senza spazi.
Tutto sotto la home dell'utente (scope per-utente, niente sudo):
| Cosa | Dove |
|---|---|
| Eseguibile AppImage | ~/.local/bin/<nome>.AppImage (permessi 0700) |
| Voce di menù | ~/.local/share/applications/<nome>.desktop |
| Icone | ~/.local/share/icons/hicolor/<size>x<size>/apps/<nome>.png |
| Handler MIME | ~/.local/share/applications/appimage-handler.desktop |
| Registro installazioni | ~/.local/share/app-image-manager/installed.list |
list e uninstall leggono il registro, non la cartella applications:
è un file di testo INI-like che tiene nome, binario, .desktop e sorgente di
ogni installazione. Le voci di menù restano marcate con
X-AppImage-Manager=true (più X-AppImage-Source=<percorso originale>), ma è
solo informativo.
Perché il nome del
.desktopè quello canonico (<nome>.desktop). Molte applicazioni si registrano da sole al primo avvio — le app Electron lo fanno daapp.setAsDefaultProtocolClient()— scrivendo~/.local/share/applications/<nome>.desktopcon unExecche punta al binario in esecuzione, cioè alla nostra copia in~/.local/bin. Usando lo stesso ID quel file sostituisce il nostro invece di affiancarsi, e resta una sola voce nel menù. La 0.1.2 usavaappimage-manager-<nome>.desktop: ID diverso, quindi due voci identiche. L'aggiornamento migra da solo le installazioni vecchie, e ogniinstall/listrimuove le voci duplicate che puntano a un binario gestito da noi.
- Riconoscimento: legge i magic byte dell'ELF +
AI\x02(AppImage type 2). - Offset del payload: cerca il magic squashfs
hsqsnel file e valida ogni candidato contro il superblock squashfs (block_size == 1 << block_log,bytes_usedcoerente con la dimensione del file). Questo evita i falsi positivi quandohsqscompare nei dati dell'ELF. - Estrazione mirata: usa
unsquashfs -o <offset> -catper estrarre solo il.desktopradice e le icone hicolor, senza spacchettare tutto né eseguire l'AppImage. - Reinstallazione: copia l'eseguibile, riscrive
Exec=AppRun ...inExec=~/.local/bin/<nome>.AppImage ...(anche negli eventuali gruppi[Desktop Action ...], che vengono preservati come richiede la spec), aggiunge i marker, installa le icone viaxdg-icon-resource --novendor(con fallback a copia manuale), aggiorna i database. - Avvio: lancia l'AppImage installata in una nuova sessione (
setsid) così sopravvive alla chiusura del processo chiamante.
src/
├── main.rs # entrypoint + dispatch comandi
├── cli.rs # definizione CLI (clap)
├── appimage.rs # riconoscimento type 2 + offset squashfs (con validazione)
├── metadata.rs # estrazione .desktop + icone via unsquashfs
├── desktop.rs # parser/serializer .desktop (INI minimale)
├── registry.rs # registro delle installazioni (fonte di verità per list/uninstall)
├── installer.rs # copia, rewrite .desktop, icone, refresh DB, list, uninstall
├── launcher.rs # avvio non bloccante (setsid)
├── kdialog.rs # wrapper kdialog (yesno/msgbox/error/...)
└── mime.rs # setup handler MIME
docker/
├── Dockerfile # toolchain Ubuntu 22.04 (+ cargo-deb) e Fedora 44 (+ cargo-generate-rpm)
├── compose.yaml # stessi servizi via compose
└── run.sh # driver podman/docker senza compose
Il progetto produce due pacchetti nativi per x86_64 (amd64):
.debper Ubuntu/Debian — viacargo-deb.rpmper Fedora 44 — viacargo-generate-rpm, costruito in containerfedora:44per il glibc corretto
La GitHub Action .github/workflows/release.yml ha questa pipeline:
| Job | Runner | Cosa fa |
|---|---|---|
build |
ubuntu-22.04 |
fmt + clippy (-D warnings) + test + build release |
deb |
ubuntu-22.04 |
cargo deb → app-image-manager_*_amd64.deb |
rpm |
fedora:44 (container) |
cargo generate-rpm → app-image-manager_*_x86_64.rpm |
release |
ubuntu-22.04 |
solo su tag v*: crea GitHub Release con .deb + .rpm |
I pacchetti installano:
/usr/bin/app-image-manager(binario,0755)/usr/share/applications/appimage-handler.desktop(handler MIME di sistema, punta a/usr/bin/app-image-manager handle %f)/usr/share/metainfo/app-image-manager.metainfo.xml(AppStream, per Discover/GNOME Software)
Con le dipendenze runtime dichiarate (kdialog, squashfs-tools, xdg-utils, desktop-file-utils, gtk-update-icon-cache).
- Da una release: vai nella pagina Releases del repo e scarica il
.debo.rpmdell'ultima versione. - Da un run CI (qualsiasi push/PR): nella scheda Actions del repo, apri il run, scorri fino ad Artifacts e scarica
app-image-manager-amd64-deboapp-image-manager-x86_64-rpm.
# Ubuntu/Debian
sudo apt install ./app-image-manager_*_amd64.deb
# Fedora 44
sudo dnf install ./app-image-manager_*_x86_64.rpmCon il pacchetto installato non serve eseguire app-image-manager setup: la registrazione MIME avviene automaticamente tramite gli script di post-installazione del pacchetto.
I pacchetti .deb e .rpm registrano e deregistrano l'handler MIME tramite i rispettivi script maintainer, che invocano un helper condiviso (/usr/lib/app-image-manager/mime-register.sh):
| Evento | Debian | RPM | Azione |
|---|---|---|---|
| Installazione | postinst configure |
%post |
registra i MIME type in /usr/share/applications/mimeapps.list |
| Upgrade | postinst configure (nuovo) |
%post (idempotente) |
refresh della registrazione |
| Rimozione | prerm remove |
%preun (con $1 == 0) |
deregistra i MIME type |
| Dopo rimozione | — | %postun |
refresh di update-desktop-database / gtk-update-icon-cache |
Note:
- Su upgrade la registrazione viene mantenuta (non rimossa in
prerm/%preun), così il nuovo pacchetto la rinfresca senza "sfarfallii". - La deregistrazione avviene in
prerm/%preun(prima della cancellazione dei file), non inpostrm/%postun, perché l'helper deve essere ancora presente sul disco. - L'helper è idempotente: marca il proprio blocco con
# BEGIN/END app-image-managere modifica solo le righe dei propri MIME type, preservando ogni altra associazione presente nel file.
I MIME type registrati come default: application/vnd.appimage, application/x-appimage. application/octet-stream non viene registrato (è il fallback generico di ogni binario non riconosciuto); le registrazioni lasciate dalle versioni ≤ 0.1.2 vengono rimosse in fase di add/remove, senza toccare le associazioni octet-stream di altre applicazioni.
cargo install cargo-deb cargo-generate-rpm --locked
cargo deb # → target/debian/*.deb
cargo build --release # richiesto prima del generate-rpm
cargo generate-rpm # → target/generate-rpm/*.rpmNota: il
.rpmva costruito su Fedora (o nel containerfedora:44) per avere il glibc giusto; costruendolo altrove si ottiene un pacchetto che al limite non si installa su Fedora 44.
cargo test # 7 test unitari
cargo clippy --all-targets -- -D warnings
cargo build --release- Niente update via zsync: non ancora supportato (AppImageUpdate).
- Scope per-utente: installa solo in
~/.local, non a livello di sistema. - MIME detection in Dolphin: dipende dal fatto che il file sia classificato
come
application/*appimage; vedi la nota nel paragrafo Setup.
MIT.