From 6ca8175d2b137a674f62f1fe80472add4c01d4fe Mon Sep 17 00:00:00 2001 From: mARTin-B78 Date: Thu, 4 Jun 2026 09:25:32 +0200 Subject: [PATCH] Add Debian (.deb) installer (v1.1.0) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit packaging/build-deb.sh builds an installable blitztext__arm64.deb with a desktop entry, app icon, and launcher. Bundles a relocatable venv (all Python deps, no pip at install) and declares system deps (python3-gi, xdotool, libnotify-bin, recorder). Built on /usr/bin/python3 so the tray works out of the box. Installs via the Software app or `apt install ./…deb`. Co-Authored-By: Claude Opus 4.8 --- linux/.gitignore | 1 + linux/CHANGELOG.md | 19 +++++- linux/README.md | 36 +++++++++-- linux/blitztext/__init__.py | 2 +- linux/packaging/blitztext.desktop | 11 ++++ linux/packaging/blitztext.svg | 12 ++++ linux/packaging/build-deb.sh | 104 ++++++++++++++++++++++++++++++ linux/packaging/copyright | 26 ++++++++ 8 files changed, 203 insertions(+), 8 deletions(-) create mode 100644 linux/packaging/blitztext.desktop create mode 100644 linux/packaging/blitztext.svg create mode 100755 linux/packaging/build-deb.sh create mode 100644 linux/packaging/copyright diff --git a/linux/.gitignore b/linux/.gitignore index 77ac754..22332bc 100644 --- a/linux/.gitignore +++ b/linux/.gitignore @@ -1,3 +1,4 @@ .venv/ __pycache__/ *.pyc +dist/ diff --git a/linux/CHANGELOG.md b/linux/CHANGELOG.md index f2b548b..925f44c 100644 --- a/linux/CHANGELOG.md +++ b/linux/CHANGELOG.md @@ -9,6 +9,22 @@ The version is defined in [`blitztext/__init__.py`](blitztext/__init__.py). ## [Unreleased] +## [1.1.0] - 2026-06-04 + +### Added +- **Debian package** (`packaging/build-deb.sh`) producing an installable + `blitztext__arm64.deb` with a desktop entry, app icon, and a `blitztext` + launcher. Installs via the Software app or `apt install ./…deb`. Bundles a + relocatable venv with all Python deps (no pip/network at install) and declares + system deps (python3-gi, xdotool, libnotify-bin, a recorder) so they pull in + automatically. The bundled venv is built on the system `/usr/bin/python3`, so + the tray works out of the box. + +### Notes +- `python3-gi` is already present on a standard Ubuntu GNOME install; the tray + only seemed unavailable from source when the project venv was built from a + non-system Python (e.g. conda/miniforge). The `.deb` avoids this entirely. + ## [1.0.1] - 2026-06-03 ### Changed @@ -58,6 +74,7 @@ into that field. AppIndicator typelibs and GNOME `ubuntu-appindicators` extension are already present on the target host). -[Unreleased]: https://github.com/mARTin-B78/blitztext-app/compare/v1.0.1...HEAD +[Unreleased]: https://github.com/mARTin-B78/blitztext-app/compare/v1.1.0...HEAD +[1.1.0]: https://github.com/mARTin-B78/blitztext-app/compare/v1.0.1...v1.1.0 [1.0.1]: https://github.com/mARTin-B78/blitztext-app/compare/v1.0.0...v1.0.1 [1.0.0]: https://github.com/mARTin-B78/blitztext-app/releases/tag/v1.0.0 diff --git a/linux/README.md b/linux/README.md index 76a9f93..210ff75 100644 --- a/linux/README.md +++ b/linux/README.md @@ -37,6 +37,24 @@ transcribes, optionally rewrites, and types the result where your cursor is. ## Install +### Option A — Debian package (recommended on Ubuntu/Debian) + +Build a `.deb` and install it with the Software app or apt: + +```bash +cd linux +bash packaging/build-deb.sh # -> dist/blitztext__arm64.deb +sudo apt install ./dist/blitztext_*.deb # or double-click the .deb in Files +``` + +This installs `blitztext` to `/opt/blitztext` (a self-contained bundle — no pip +step), adds a **Blitztext** entry to your app grid, and pulls in the system deps +(`python3-gi`, `xdotool`, `libnotify-bin`, a recorder). Launch it from the app +grid, or run `blitztext` / `blitztext gui` from a terminal. Remove with +`sudo apt remove blitztext`. + +### Option B — run from source (venv) + ```bash cd linux ./install.sh @@ -45,6 +63,11 @@ cd linux This creates `.venv`, installs `faster-whisper` + `pynput`, and writes the default config to `~/.config/blitztext/config.toml`. +> For the **tray** from source, the venv must be built on a Python that can see +> the system `python3-gi` — `install.sh` uses `python3 -m venv +> --system-site-packages`, so use the system `/usr/bin/python3` (a conda/miniforge +> Python won't see the apt-installed `gi`). The `.deb` handles this for you. + ## Run Three front-ends, same engine (local Whisper + global hotkeys + xdotool typing): @@ -62,17 +85,18 @@ export OPENAI_API_KEY=sk-... The tray is the closest match to the macOS menu-bar app: a status icon with a menu listing every workflow (click to record), plus **Show panel**, **Settings…**, -and **Quit**. It needs PyGObject once (the GTK/AppIndicator typelibs and the -GNOME `ubuntu-appindicators` extension are already present here): +and **Quit**. It needs PyGObject (`python3-gi`) and the GTK/AppIndicator +typelibs — already present on a standard Ubuntu GNOME install (the `.deb` +declares them as dependencies): ```bash -sudo apt install python3-gi # one-time; no build, just the bindings +sudo apt install python3-gi # usually already installed .venv/bin/python -m blitztext tray ``` -If PyGObject is missing, `tray` prints this hint and falls back to the window. -(The venv is created with `--system-site-packages` so it can see the -apt-installed `gi`.) +If PyGObject isn't visible, `tray` prints this hint and falls back to the +window. The venv is created with `--system-site-packages` so it can see the +system `gi` — build it from `/usr/bin/python3`, not a conda/miniforge Python. Either way, focus any text field and trigger a workflow — by tray menu, panel button, or hotkey (defaults): diff --git a/linux/blitztext/__init__.py b/linux/blitztext/__init__.py index 1689a27..8bfdafa 100644 --- a/linux/blitztext/__init__.py +++ b/linux/blitztext/__init__.py @@ -6,4 +6,4 @@ counterpart to the macOS Blitztext menu bar app: it runs natively on the host (not in a container) so it can type into any application via xdotool. """ -__version__ = "1.0.1" +__version__ = "1.1.0" diff --git a/linux/packaging/blitztext.desktop b/linux/packaging/blitztext.desktop new file mode 100644 index 0000000..203f13d --- /dev/null +++ b/linux/packaging/blitztext.desktop @@ -0,0 +1,11 @@ +[Desktop Entry] +Type=Application +Name=Blitztext +GenericName=Voice Dictation +Comment=Speak and have the text typed into any field +Exec=blitztext tray +Icon=blitztext +Terminal=false +Categories=Utility;AudioVideo;Accessibility; +Keywords=dictation;speech;voice;transcription;whisper;stt; +StartupNotify=false diff --git a/linux/packaging/blitztext.svg b/linux/packaging/blitztext.svg new file mode 100644 index 0000000..8a9f57f --- /dev/null +++ b/linux/packaging/blitztext.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + diff --git a/linux/packaging/build-deb.sh b/linux/packaging/build-deb.sh new file mode 100755 index 0000000..ef8c99f --- /dev/null +++ b/linux/packaging/build-deb.sh @@ -0,0 +1,104 @@ +#!/usr/bin/env bash +# Build a self-contained .deb for Blitztext (Ubuntu/Debian, arm64). +# +# Bundles a relocatable venv with the Python deps (faster-whisper, pynput, +# tomli-w) under /opt/blitztext so installation needs no pip/network. System +# integration (python3-gi, xdotool, libnotify-bin, a recorder) is declared via +# Depends so the Software app / apt pull them in. +set -euo pipefail + +HERE="$(cd "$(dirname "$0")" && pwd)" +LINUX_DIR="$(dirname "$HERE")" # .../linux +PKG="blitztext" +ARCH="$(dpkg --print-architecture)" +VER="$(sed -n 's/.*__version__ = "\(.*\)".*/\1/p' "$LINUX_DIR/blitztext/__init__.py")" +PYBIN="${PYBIN:-/usr/bin/python3}" + +BUILD="$(mktemp -d)" +ROOT="$BUILD/${PKG}_${VER}_${ARCH}" +OUT_DIR="${OUT_DIR:-$LINUX_DIR/dist}" +trap 'rm -rf "$BUILD"' EXIT + +echo "==> Building $PKG $VER ($ARCH) with $($PYBIN --version)" + +# 1) Bundled, relocatable venv with all Python deps ------------------------- +APPDIR="$ROOT/opt/$PKG" +VENV="$APPDIR/venv" +mkdir -p "$APPDIR" +"$PYBIN" -m venv --copies "$VENV" +"$VENV/bin/pip" install --upgrade pip -q +"$VENV/bin/pip" install -q -r "$LINUX_DIR/requirements.txt" tomli-w + +# Drop the app package into the venv so `python -m blitztext` works. +cp -r "$LINUX_DIR/blitztext" "$VENV/lib/python"*/site-packages/ + +# Let the venv also see the system PyGObject (apt python3-gi) for tray mode, +# while still preferring its own bundled deps. +PYVENV="$VENV/pyvenv.cfg" +sed -i 's/^include-system-site-packages = false/include-system-site-packages = true/' "$PYVENV" +grep -q "^include-system-site-packages = true" "$PYVENV" || echo "include-system-site-packages = true" >> "$PYVENV" + +# Trim build cruft to shrink the package. +find "$VENV" -type d -name "__pycache__" -prune -exec rm -rf {} + 2>/dev/null || true +rm -rf "$VENV/lib/python"*/site-packages/pip "$VENV/lib/python"*/site-packages/pip-* \ + "$VENV"/bin/pip* "$VENV/lib/python"*/site-packages/setuptools* 2>/dev/null || true + +cp "$LINUX_DIR/README.md" "$LINUX_DIR/CHANGELOG.md" "$APPDIR/" + +# 2) Launcher, desktop entry, icon, docs ------------------------------------ +install -Dm755 /dev/stdin "$ROOT/usr/bin/$PKG" <<'EOF' +#!/bin/sh +exec /opt/blitztext/venv/bin/python -m blitztext "$@" +EOF + +install -Dm644 "$HERE/$PKG.desktop" "$ROOT/usr/share/applications/$PKG.desktop" +install -Dm644 "$HERE/$PKG.svg" "$ROOT/usr/share/icons/hicolor/scalable/apps/$PKG.svg" +install -Dm644 "$HERE/copyright" "$ROOT/usr/share/doc/$PKG/copyright" + +# 3) DEBIAN control + maintainer scripts ------------------------------------ +SIZE_KB="$(du -sk "$ROOT" | cut -f1)" +mkdir -p "$ROOT/DEBIAN" +cat > "$ROOT/DEBIAN/control" <= 3.12), python3-gi, gir1.2-ayatanaappindicator3-0.1, xdotool, libnotify-bin, pipewire-bin | pulseaudio-utils | alsa-utils +Maintainer: Martin Bierschenk +Installed-Size: $SIZE_KB +Description: Blitztext - local voice dictation for Linux + Focus any text field, press a hotkey, speak, and the transcribed text is + typed into that field. Optional LLM rewrite turns rough speech into a nicer + email, a calmer message, or adds emojis. + . + Transcription runs locally via faster-whisper; the optional rewrite uses any + OpenAI-compatible endpoint (OpenAI or a local server). Runs in the system + tray or as a small control-panel window. Requires an X11 session. +EOF + +cat > "$ROOT/DEBIAN/postinst" <<'EOF' +#!/bin/sh +set -e +if [ "$1" = "configure" ]; then + gtk-update-icon-cache -qf /usr/share/icons/hicolor 2>/dev/null || true + update-desktop-database -q 2>/dev/null || true +fi +EOF +chmod 755 "$ROOT/DEBIAN/postinst" + +cat > "$ROOT/DEBIAN/postrm" <<'EOF' +#!/bin/sh +set -e +# Remove runtime-generated files (e.g. *.pyc) left in the bundled venv. +if [ "$1" = "remove" ] || [ "$1" = "purge" ]; then + rm -rf /opt/blitztext +fi +EOF +chmod 755 "$ROOT/DEBIAN/postrm" + +# 4) Build ------------------------------------------------------------------- +mkdir -p "$OUT_DIR" +DEB="$OUT_DIR/${PKG}_${VER}_${ARCH}.deb" +fakeroot dpkg-deb --build --root-owner-group "$ROOT" "$DEB" >/dev/null +echo "==> Built: $DEB ($(du -h "$DEB" | cut -f1))" diff --git a/linux/packaging/copyright b/linux/packaging/copyright new file mode 100644 index 0000000..c59678a --- /dev/null +++ b/linux/packaging/copyright @@ -0,0 +1,26 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: blitztext +Source: https://github.com/mARTin-B78/blitztext-app + +Files: * +Copyright: 2026 Martin Bierschenk +License: MIT + +License: MIT + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + . + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + . + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE.