mirror of
https://github.com/l0ng-ai/tty7.git
synced 2026-09-21 16:02:20 +00:00
The `tty7` CLI was built by every release run and thrown away: all four bundle scripts copied only `tty7-app`, and the upload glob covers `dist/`, which the CLI never reached. Nothing put it on PATH either, so the agent-facing half of the product was unreachable from a shipped install. Bundle it on all four platforms, and have the GUI link it up itself rather than hiding the step behind a menu item most people never find. The install has two halves. The environment half prepends the CLI's directory to this process's PATH before the daemon is spawned, so every pane inherits it — that alone makes `tty7` work where agents actually run, writes nothing to disk, and behaves the same everywhere. The on-disk half symlinks into a directory already on PATH (Unix) or appends to HKCU\Environment (Windows), and is allowed to fail. Candidate directories are a fixed list intersected with PATH, not the first writable entry on it: pyenv/rbenv/asdf/mise shim directories sit at the front of PATH on many machines and are writable, and anything dropped there is deleted on the next rehash — silently, days later. Debug builds get the environment half only. `target/debug` holds a `tty7` too, so otherwise a `cargo run` would repoint the developer's real `tty7` at a debug binary, and each isolated dev-verify instance would rewrite the PATH of the machine it is meant to stay away from.
101 lines
4.1 KiB
Bash
Executable File
101 lines
4.1 KiB
Bash
Executable File
#!/bin/bash
|
||
# Usage: bundle-appimage.sh <target-triple> <arch-label>
|
||
# Package the release binary into a self-contained AppImage:
|
||
# dist/tty7-<version>-linux-<arch>.AppImage
|
||
#
|
||
# Unlike the bare tarball (bundle-linux.sh), this bundles the x11/wayland/xkb/
|
||
# fontconfig/freetype runtime libraries alongside the binary, so it launches on
|
||
# distros that don't ship the exact same set Ubuntu does — Fedora, Arch, etc.
|
||
# (glibc itself is NOT bundled — an AppImage still needs the host glibc to be
|
||
# >= the build machine's, so the release runner's Ubuntu sets the floor.)
|
||
#
|
||
# Completion signatures are loaded at runtime relative to the executable
|
||
# (<exe-dir>/completions — see terminal::signature), so they go beside the
|
||
# binary at usr/bin/completions inside the AppDir.
|
||
set -euo pipefail
|
||
|
||
TARGET="$1"
|
||
ARCH="$2"
|
||
# Anchored on `= "` — see the note in bundle-macos.sh: the root manifest leads
|
||
# with `version.workspace = true`, which a bare `^version` match would return
|
||
# verbatim as the "version" and bake into every asset filename.
|
||
VERSION="$(grep -m1 '^version = "' Cargo.toml | sed -E 's/.*"([^"]+)".*/\1/')"
|
||
if [[ ! "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+ ]]; then
|
||
echo "bundle-appimage: could not read a version from Cargo.toml (got '$VERSION')" >&2
|
||
exit 1
|
||
fi
|
||
NAME="tty7-${VERSION}-linux-${ARCH}"
|
||
|
||
# AppImage tools need FUSE to self-mount; CI runners usually lack it, so extract
|
||
# and run instead. Harmless on machines that do have FUSE.
|
||
export APPIMAGE_EXTRACT_AND_RUN=1
|
||
|
||
# linuxdeploy is published per-arch; map Rust's arch label to its naming.
|
||
case "$ARCH" in
|
||
x86_64) LD_ARCH=x86_64 ;;
|
||
arm64 | aarch64) LD_ARCH=aarch64 ;;
|
||
*) echo "unsupported arch for AppImage: $ARCH" >&2; exit 1 ;;
|
||
esac
|
||
|
||
TOOLS="$(mktemp -d)"
|
||
LINUXDEPLOY="$TOOLS/linuxdeploy-${LD_ARCH}.AppImage"
|
||
APPIMAGETOOL="$TOOLS/appimagetool-${LD_ARCH}.AppImage"
|
||
curl -fsSL -o "$LINUXDEPLOY" \
|
||
"https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-${LD_ARCH}.AppImage"
|
||
curl -fsSL -o "$APPIMAGETOOL" \
|
||
"https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-${LD_ARCH}.AppImage"
|
||
chmod +x "$LINUXDEPLOY" "$APPIMAGETOOL"
|
||
|
||
# NB: don't wipe dist/ — the tarball step (bundle-linux.sh) runs first and its
|
||
# artifact must survive. Only clean our own AppDir.
|
||
APPDIR="dist/AppDir"
|
||
rm -rf "$APPDIR"
|
||
mkdir -p "$APPDIR/usr/bin"
|
||
|
||
cp "target/${TARGET}/release/tty7-app" "$APPDIR/usr/bin/tty7-app"
|
||
chmod +x "$APPDIR/usr/bin/tty7-app"
|
||
|
||
# The CLI, beside the GUI as everywhere else. Unlike the tarball, an AppImage is
|
||
# mounted at a fresh /tmp/.mount_XXXX per run, so `core::cli_install` must copy
|
||
# this onto PATH rather than symlink it — a link into the mount dies the moment
|
||
# the app exits. That branch keys off $APPIMAGE, which the runtime sets.
|
||
cp "target/${TARGET}/release/tty7" "$APPDIR/usr/bin/tty7"
|
||
chmod +x "$APPDIR/usr/bin/tty7"
|
||
|
||
# A desktop entry + icon are mandatory AppImage metadata; linuxdeploy places
|
||
# them and generates AppRun. Icon basename must match the desktop's Icon= key.
|
||
cat > "$TOOLS/tty7.desktop" <<'DESKTOP'
|
||
[Desktop Entry]
|
||
Type=Application
|
||
Name=tty7
|
||
Comment=A fast, native terminal
|
||
Exec=tty7-app
|
||
Icon=tty7
|
||
Categories=System;TerminalEmulator;
|
||
Terminal=false
|
||
StartupWMClass=tty7
|
||
DESKTOP
|
||
# linuxdeploy only accepts fixed icon resolutions (…256, 384, 512 — NOT the
|
||
# source's 1024), so downscale to 256×256.
|
||
convert assets/app-icon.png -resize 256x256 "$TOOLS/tty7.png"
|
||
|
||
# Phase 1 — populate the AppDir: copy in dependent libs (ldd + patchelf) and
|
||
# install the desktop/icon into their standard locations.
|
||
"$LINUXDEPLOY" \
|
||
--appdir "$APPDIR" \
|
||
--executable "$APPDIR/usr/bin/tty7-app" \
|
||
--desktop-file "$TOOLS/tty7.desktop" \
|
||
--icon-file "$TOOLS/tty7.png"
|
||
|
||
# Runtime-loaded completion specs live beside the binary (not bundled by
|
||
# linuxdeploy, which only tracks ELF deps), so drop them in after populate.
|
||
mkdir -p "$APPDIR/usr/bin/completions"
|
||
cp assets/completions/*.json "$APPDIR/usr/bin/completions/"
|
||
|
||
# Phase 2 — pack the finished AppDir. Done separately from linuxdeploy so the
|
||
# completions added above are included.
|
||
"$APPIMAGETOOL" "$APPDIR" "dist/${NAME}.AppImage"
|
||
chmod +x "dist/${NAME}.AppImage"
|
||
rm -rf "$APPDIR" "$TOOLS"
|
||
echo "✅ dist/${NAME}.AppImage"
|