Add Debian (.deb) installer (v1.1.0)
packaging/build-deb.sh builds an installable blitztext_<ver>_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 <noreply@anthropic.com>
This commit is contained in:
parent
a5dffb8f1e
commit
6ca8175d2b
1
linux/.gitignore
vendored
1
linux/.gitignore
vendored
@ -1,3 +1,4 @@
|
|||||||
.venv/
|
.venv/
|
||||||
__pycache__/
|
__pycache__/
|
||||||
*.pyc
|
*.pyc
|
||||||
|
dist/
|
||||||
|
|||||||
@ -9,6 +9,22 @@ The version is defined in [`blitztext/__init__.py`](blitztext/__init__.py).
|
|||||||
|
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
|
## [1.1.0] - 2026-06-04
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- **Debian package** (`packaging/build-deb.sh`) producing an installable
|
||||||
|
`blitztext_<ver>_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
|
## [1.0.1] - 2026-06-03
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
@ -58,6 +74,7 @@ into that field.
|
|||||||
AppIndicator typelibs and GNOME `ubuntu-appindicators` extension are already
|
AppIndicator typelibs and GNOME `ubuntu-appindicators` extension are already
|
||||||
present on the target host).
|
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.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
|
[1.0.0]: https://github.com/mARTin-B78/blitztext-app/releases/tag/v1.0.0
|
||||||
|
|||||||
@ -37,6 +37,24 @@ transcribes, optionally rewrites, and types the result where your cursor is.
|
|||||||
|
|
||||||
## Install
|
## 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_<ver>_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
|
```bash
|
||||||
cd linux
|
cd linux
|
||||||
./install.sh
|
./install.sh
|
||||||
@ -45,6 +63,11 @@ cd linux
|
|||||||
This creates `.venv`, installs `faster-whisper` + `pynput`, and writes the
|
This creates `.venv`, installs `faster-whisper` + `pynput`, and writes the
|
||||||
default config to `~/.config/blitztext/config.toml`.
|
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
|
## Run
|
||||||
|
|
||||||
Three front-ends, same engine (local Whisper + global hotkeys + xdotool typing):
|
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
|
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…**,
|
menu listing every workflow (click to record), plus **Show panel**, **Settings…**,
|
||||||
and **Quit**. It needs PyGObject once (the GTK/AppIndicator typelibs and the
|
and **Quit**. It needs PyGObject (`python3-gi`) and the GTK/AppIndicator
|
||||||
GNOME `ubuntu-appindicators` extension are already present here):
|
typelibs — already present on a standard Ubuntu GNOME install (the `.deb`
|
||||||
|
declares them as dependencies):
|
||||||
|
|
||||||
```bash
|
```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
|
.venv/bin/python -m blitztext tray
|
||||||
```
|
```
|
||||||
|
|
||||||
If PyGObject is missing, `tray` prints this hint and falls back to the window.
|
If PyGObject isn't visible, `tray` prints this hint and falls back to the
|
||||||
(The venv is created with `--system-site-packages` so it can see the
|
window. The venv is created with `--system-site-packages` so it can see the
|
||||||
apt-installed `gi`.)
|
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
|
Either way, focus any text field and trigger a workflow — by tray menu, panel
|
||||||
button, or hotkey (defaults):
|
button, or hotkey (defaults):
|
||||||
|
|||||||
@ -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.
|
(not in a container) so it can type into any application via xdotool.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__version__ = "1.0.1"
|
__version__ = "1.1.0"
|
||||||
|
|||||||
11
linux/packaging/blitztext.desktop
Normal file
11
linux/packaging/blitztext.desktop
Normal file
@ -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
|
||||||
12
linux/packaging/blitztext.svg
Normal file
12
linux/packaging/blitztext.svg
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<svg width="128" height="128" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<defs>
|
||||||
|
<linearGradient id="bg" x1="0" y1="0" x2="0" y2="1">
|
||||||
|
<stop offset="0" stop-color="#2b8cff"/>
|
||||||
|
<stop offset="1" stop-color="#0a5cf0"/>
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<rect x="8" y="8" width="112" height="112" rx="28" fill="url(#bg)"/>
|
||||||
|
<path d="M70 26 L42 70 H60 L56 102 L86 56 H66 Z"
|
||||||
|
fill="#ffffff" stroke="#ffffff" stroke-width="2" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 529 B |
104
linux/packaging/build-deb.sh
Executable file
104
linux/packaging/build-deb.sh
Executable file
@ -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" <<EOF
|
||||||
|
Package: $PKG
|
||||||
|
Version: $VER
|
||||||
|
Section: utils
|
||||||
|
Priority: optional
|
||||||
|
Architecture: $ARCH
|
||||||
|
Depends: python3 (>= 3.12), python3-gi, gir1.2-ayatanaappindicator3-0.1, xdotool, libnotify-bin, pipewire-bin | pulseaudio-utils | alsa-utils
|
||||||
|
Maintainer: Martin Bierschenk <mail@martin-bierschenk.de>
|
||||||
|
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))"
|
||||||
26
linux/packaging/copyright
Normal file
26
linux/packaging/copyright
Normal file
@ -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.
|
||||||
Loading…
Reference in New Issue
Block a user