Repository navigation
Linux distribution (install script, apt, AUR) #44
Description
Opportunity
A Linux user can't install or update TuiCode with a tool they already have.
The README's only Linux instruction is brew install mentaldesk/tap/tuicode. That asks a Linux user to install Homebrew — a macOS package manager — for one editor. The alternative it offers is downloading a tarball from Releases and putting it on PATH by hand, which never updates: the user finds out there's a new version when they next visit GitHub, if ever.
This bites exactly the user the vision describes — someone who "lives in the terminal, locally or over SSH". The machines they SSH into are Debian, Ubuntu, Fedora and Arch servers, and none of them have Homebrew. The Reach theme says TuiCode should be "installed through the package manager the user already has"; on Linux, today, it isn't installed through any.
Two unknowns sit under every option below, and neither has ever been measured:
- glibc floor. The Linux legs build on
ubuntu-latest(24.04). A NativeAOT binary links against the build host's glibc, so it likely won't start on anything older than glibc 2.34 — which rules out Ubuntu 20.04 and Debian 11, still common on servers people SSH into. Nobody has run the binary on one to find out. - ICU.
InvariantGlobalizationisn't set, so the binary loadslibicuat startup and fails without it. Minimal server images and containers often don't have it, and the package name differs per release (libicu72,libicu74, …).
Options considered
- Do nothing. Keep Homebrew and the tarballs. Costs nothing and the tarballs genuinely work, but it leaves the README telling Linux users to install a macOS package manager, and nothing ever auto-updates. Rejected: this is a stated theme, not an edge case.
- A one-line install script only.
curl … | shdetects architecture, verifies the checksum, installs to~/.local/bin. Covers every distro at once, needs no signing key, no hosted repo and no third-party account, and updates by re-running. But it isn't the user's package manager —apt list --upgradablewon't mention it, andcurl | shputs some people off. - Native packages, hosted.
.deb+ a signed apt repo on GitHub Pages,.rpm, and AURtuicode-bin— the original idea. This is the only option whereapt upgradepicks TuiCode up with everything else. It's also the only one that needs a GPG key the maintainer creates and holds, and an AUR account listed under their name, both of which block work until they exist. - Hand it to distro packagers. Keep the release assets stable and documented and let Arch/Nix/Alpine maintainers package it. Zero ongoing cost and it's how most tools of this size get into the AUR. But it only happens once enough people want it, which is the thing we're trying to cause.
- Native packages, unhosted (part of the proposal). Build
.deband.rpmfrom the tarballs with nfpm and attach them to each release.sudo dnf install <url>andsudo apt install ./tuicode.debwork immediately, dependencies are declared properly, anddpkg -lknows about it. No key, no account, no hosting — but no auto-update either.
Proposed: 2 + 5, then the apt half of 3. The script and the attached packages reach every distro in the first three slices, with nothing waiting on the maintainer. The signed apt repo on Pages follows once the GPG key exists. The AUR half of 3 is deferred: AUR account registration is closed right now, so it's split out as its own Idea (#383) and the install script covers Arch until then.
Proposal
- Measure and fix the compatibility floor first. Run the published binary in
debian:11,debian:12,ubuntu:22.04andfedoracontainers, record the real glibc and ICU requirements, and fix what rules out a distro we want. Add a CI leg that runs--smokein the oldest supported one, so a future dependency bump can't silently raise the floor again. install.shin the repo root, served overraw.githubusercontent.com. Detects architecture, downloads the matching tarball, verifies the.sha256sidecar, installs to~/.local/bin, and says how to update..deband.rpmfor x64 and arm64 attached to every release, built with nfpm inside the release run, each installed and smoke-tested in a CI container.- A signed apt repo on GitHub Pages, refreshed as part of the release run, so
apt upgradecarries TuiCode along. Needs a GPG key. - README gains a Linux block with these commands.
Flatpak and Snap stay out: both sandbox file access, which fights an editor that opens arbitrary paths passed from a shell. Nix is left to the community.
It has to fit the release flow #163 built
#163 has landed its release work (#215 merged), so this is now settled rather than a moving target:
bump-tap.ymlis gone..github/workflows/isci.ymlandrelease.yml, nothing else. The "react torelease: published" model this draft was originally written against no longer exists to copy.- A
release: publishedtrigger will not fire. The release is created by a-team's sharedrelease-publish.ymlusingGITHUB_TOKEN, and GitHub deliberately doesn't start workflows from events raised by that token. Slice 4 runs inside the release run, not as a separate reacting workflow. - Publishing is locked to
main. Since Release publishes only from main, and CI's token is read-only #326 and The tap token lives in a release environment only main can reach #328 thepublishjob only runs frommain, and its push tokens live in areleaseenvironment onlymaincan reach. The GPG key for slice 4 belongs in that same environment. - The shared workflow already has the right shape.
mentaldesk/a-team/.github/workflows/release-publish.yml(pinned atv0.1.3) takes rendered package templates as inputs (formulafor the Homebrew tap,scoopfor the bucket) and pushes each to its own repo with a packages token. An apt repo is the same shape: a template in TuiCode, a new input and a push step in the shared workflow. That means an issue onmentaldesk/a-teamand a pinned release carrying it — the same route Know which build you're running, and ship a release in one step #163 took.
Mockup
$ curl -fsSL https://raw.githubusercontent.com/mentaldesk/TuiCode/main/install.sh | sh
tuicode 0.0.5 (linux-x64)
✓ downloaded tuicode-0.0.5-linux-x64.tar.gz
✓ sha256 verified
✓ installed to ~/.local/bin/tuicode
Run `tuicode` to start. Re-run this script to update.
# Debian / Ubuntu — attached to the release (slice 3)
$ curl -fsSLO https://github.com/mentaldesk/TuiCode/releases/download/v0.0.5/tuicode_0.0.5_amd64.deb
$ sudo apt install ./tuicode_0.0.5_amd64.deb
# Fedora
$ sudo dnf install https://github.com/mentaldesk/TuiCode/releases/download/v0.0.5/tuicode-0.0.5-1.x86_64.rpm
# Debian / Ubuntu — from the repo, once it exists (slice 4)
$ curl -fsSL https://mentaldesk.github.io/apt/key.asc | sudo tee /etc/apt/keyrings/mentaldesk.asc >/dev/null
$ echo "deb [signed-by=/etc/apt/keyrings/mentaldesk.asc] https://mentaldesk.github.io/apt stable main" \
| sudo tee /etc/apt/sources.list.d/mentaldesk.list
$ sudo apt update && sudo apt install tuicode
Scope
In
- Measuring the real glibc floor and ICU dependency, and fixing what rules out a distro we want.
install.shin the repo root, exercised in CI against the latest release..deb+.rpmfor x64 and arm64 on every release, each installed and smoke-tested in a CI container.- A signed apt repo on GitHub Pages, refreshed inside the release run.
- README install instructions for Linux.
Out
- The AUR
tuicode-binpackage. AUR registration is closed, so no account can be made; split out as its own Idea (On Arch I can't install or update TuiCode with yay #383).install.shcovers Arch meanwhile. - A hosted rpm/dnf repo (Copr or similar). The attached
.rpmcovers Fedora until someone asks. - Flatpak, Snap and Nix.
- Debian/Ubuntu's official archives — that needs a source build and a sponsor.
- A
--versionflag.install.shreads the version from the release tag; adding the flag is #163's explicitly-excluded scope. - Terminal config drops like the iTerm2 profile. One binary, no launcher script.
- Rebuilding the release flow itself. Slices 3 and 4 extend
release.ymland a-team's shared publish workflow; Know which build you're running, and ship a release in one step #163 has already put both in place.
Rough breakdown
-
TuiCode starts on the distros people actually SSH into. Measure glibc and ICU (
objdump -T, plus running the binary indebian:11,debian:12,ubuntu:22.04,fedora), fix what rules out a target, and add a CI leg running--smokein the oldest supported distro. Nothing else can be trusted until this lands. No dependency; can start now. -
One line installs TuiCode on any distro.
install.shplus a CI job that runs it in a clean container and thentuicode --smoke. Needs 1. -
apt/dnfinstall it as a real package. nfpm in the release run producing.deband.rpmfor both architectures with correctDepends(andwl-clipboard/xclipasRecommends, since copy falls back to them where the terminal refuses OSC 52, A copy the clipboard refuses lands through the system's clipboard program (#319) #339), plus an install-and-smoke check per format. Needs 1. The release flow it plugs into is in place — Release TuiCode in one click from the Actions tab #215 has merged.A reasonable stopping point. Every distro is covered and nothing above waits on the maintainer.
-
apt upgradebrings TuiCode along. Signed apt repo on Pages, refreshed inside the release run. Needs 3, a GPG key, and the shared workflow support (a-team issue). -
README and CONTRIBUTING carry the Linux commands and the updated release diagram. Folded into whichever of 2–4 ships last.
Decided
- Oldest distro: Debian 12 / Ubuntu 22.04 (glibc 2.35), built on
ubuntu-22.04runners. Yours. Reaching Debian 11 / Ubuntu 20.04 would mean an older build container on every release for machines out of standard support. - apt repo on GitHub Pages, signed with a GPG key you create and keep in the
releaseenvironment. Yours. - AUR deferred. Yours. Registration is closed; split out as On Arch I can't install or update TuiCode with yay #383.
- ICU: invariant on Linux builds only. Mine.
libicuis a separate package on Linux whose name changes each distro release, and without it the binary won't start. The cost: on Linux, counts and file sizes (Document info,(1,234 selected), the Open view's entry cap, revert messages) show en-US separators whatever the locale. macOS and Windows keep following the locale. - README and CONTRIBUTING updates ship inside each task, not as a slice of their own. Mine.
- The install script and the packages run in parallel once TuiCode starts on Debian 12, Ubuntu 22.04 and Fedora, even without libicu #414 lands. Mine. They touch different files; both only add to the README's Linux block.
Original idea
Reviewer's original text
Goal
Reasonable install paths for the main Linux distros so users aren't downloading tarballs from GitHub Releases by hand.
Channels to consider
| Channel | Audience | Effort | Notes |
|---|---|---|---|
.deb in a PPA / apt repo |
Debian/Ubuntu | Medium | Most-asked-for; can be hosted via Cloudsmith / packagecloud / self-hosted Pages |
AUR (tuicode-bin) |
Arch | Low | Community-maintained PKGBUILD pointing at GitHub Release tarball; auto-updateable |
| Flatpak (Flathub) | Distro-agnostic GUI/TUI | Medium-High | Sandboxed; clipboard access via portals; might be awkward for a terminal app |
| Snap | Ubuntu-default | Medium | Strict confinement makes clipboard/file I/O painful; probably skip |
| Nix (nixpkgs) | Nix users | Low | Community-maintainable; just needs a derivation |
| Tarball + install script | Everyone else | Low | Already covered by the release workflow output |
Recommended starting set
- AUR — lowest effort, fastest user reach in the Arch community.
.debvia apt repo — biggest user base; pick a hosting option and document it.- Tarball + one-liner install script as the fallback for distros not covered above.
Defer Flatpak / Snap / Nix until users ask.
Dependencies
Blocked by: release workflow (produces Linux binaries for x64 and arm64).
Open questions
- Do we want a single
tuicodebinary or split intotuicode+ a separate launcher script that handles per-terminal config drops (analogue of the iTerm2 dynamic profile)? - Wayland clipboard handling — TG v2 should handle this via OSC 52 + wl-clipboard fallback, but worth a smoke test per packaging channel.
Activity
Add tag-driven release workflow producing AOT binaries (#55)
[-]Linux distribution (apt, AUR, Flatpak)[/-][+]Linux distribution (install script, apt, AUR)[/+]jamescrosswell commentedon Sep 20, 2026
Moved back to Exploring to make room in Pitched for #197 (Focus issues), which is marked Urgent.
This keeps its Medium priority and its drafted pitch — it comes back to Pitched by itself once a slot frees, with nothing to redo.
jamescrosswell commentedon Sep 20, 2026
Promoted to Pitched. It had sat in Exploring a while, so I rechecked it against the code and against #163, and rewrote it. Three things changed:
.deb/.rpmattached to each release (slices 1–3), with the hosted apt repo and the AUR kept in the breakdown but not gating it. Those two are the only pieces that can't start until something outside the repo exists — a GPG key and an AUR account, both yours to hold permanently. Stopping after slice 3 still covers every distro; it just doesn't auto-update.bump-tap.ymlgoes in Release TuiCode in one click from the Actions tab #215, and arelease: publishedtrigger won't fire any more either — the release will be created withGITHUB_TOKEN, and GitHub doesn't start workflows from that token's events. So the apt and AUR steps have to run inside the release, next to the Homebrew and Scoop ones, which means raising them onmentaldesk/a-teamrather than building them here.StringComparer.Ordinal, and the only two culture-sensitive calls areDocumentInfoView's file-size and thousands-separator formatting.InvariantGlobalizationdrops thelibicudependency and the per-distro package-name problem outright. The visible cost is that a French user sees1,234rather than1 234— say so if that's not acceptable.Three questions left for you, in the pitch: oldest distro to support (I'd say Debian 12 / Ubuntu 22.04), whether you want slices 4 and 5 given the key and account they need, and Pages vs Cloudsmith for the apt repo (I lean Pages).
jamescrosswell commentedon Sep 20, 2026
Moved back to Exploring to make room in Pitched for #133 ("Notice when open files change on disk"), which is priority High against this one's Medium.
It keeps its priority, so it comes back to Pitched by itself once a slot frees — nothing to do here.
jamescrosswell commentedon Sep 21, 2026
Promoted from Exploring — there's room in front of you again.
Refreshed against what's landed since it was drafted: #215 has merged, so the release flow this plugs into is real now, not anticipated.
bump-tap.ymlis gone, the release is published by a-team's sharedrelease-publish.yml, and that workflow already takes rendered package templates as inputs (formulafor the tap,scoopfor the bucket). An apt repo and an AUR package are the same shape — a template here, a new input and push step there — which makes slices 4 and 5 cheaper than when this was written. Slice 3 no longer waits on anything.Four questions for you, in the pitch. The one that decides how far this goes is 3: slices 4 and 5 need a GPG signing key and an AUR account that are yours to create and hold permanently. Stopping after slice 3 still reaches every distro — just without
apt upgradepicking TuiCode up.jamescrosswell commentedon Sep 21, 2026
Moved back to Exploring to make room in Pitched: #171 ("A diff shows me the change I don't want, then makes me go elsewhere to undo it") is High priority against this one's Medium, so it takes the slot.
This keeps its priority and its drafted pitch — it comes back to Pitched by itself once a slot frees, with no work lost. If you'd rather see Linux packaging sooner, raise its priority and it'll jump the queue.
a-team-app commentedon Oct 1, 2026
Back in Pitched: a slot freed up when #138 was approved.
Rechecked against main; three small updates, the proposal is unchanged:
main, with its tokens in areleaseenvironment (Release publishes only from main, and CI's token is read-only #326, The tap token lives in a release environment only main can reach #328). The GPG and AUR keys for slices 4 and 5 would go there too..deb/.rpmwould listwl-clipboard/xclipas recommended, since copy now falls back to them (A copy the clipboard refuses lands through the system's clipboard program (#319) #339).The four open questions are unchanged. Question 3 (will you own a GPG key and an AUR account?) decides how far this goes.
jamescrosswell commentedon Oct 3, 2026
Agreed.
Looks like we can't do the AUR account yet - their registration page currently shows:
Sure, let's go with pages.
a-team-app commentedon Oct 3, 2026
Thanks. I've updated the pitch with your answers:
releaseenvironment.Nothing is left for you to answer. The pitch is now four slices, with a natural stopping point after slice 3.
jamescrosswell commentedon Oct 3, 2026
Just checking, how does this relate to the Linux distro? Where are we talking about when we say a French user sees
1,234?a-team-app commentedon Oct 3, 2026
It's a Linux-only problem. macOS and Windows ship ICU with the OS. On Linux it's a separate package,
libicu, and the binary won't start without it. Minimal servers and containers often don't have it, and its name changes with each distro release (libicu72,libicu74, …), so one.debcan't name the right one for every release. Turning ICU off ("invariant mode") removes the dependency.The cost shows up in the counts TuiCode formats with thousands separators. Those would always use en-US style:
(1,234 selected)A French user would see
1,234there instead of1 234. Sorting, comparisons and dates don't change.I've rewritten the assumption so it says this, and scoped it to Linux builds only: macOS and Windows keep following the locale.
a-team-app commentedon Oct 4, 2026
Broken down into four tasks, in the order I expect them to land:
apt/dnfinstall from a.deb/.rpmattached to each release. Waits for TuiCode starts on Debian 12, Ubuntu 22.04 and Fedora, even without libicu #414; runs alongside One line installs or updates TuiCode on any Linux distro #415.apt upgradekeeps it current from a signed repo on Pages. Waits for apt and dnf install TuiCode from a package attached to each release #416, and is markedblockedon you: it needs your GPG key and a change to a-team's shared publish workflow. Details on apt upgrade keeps TuiCode up to date from a signed apt repository #417.Stopping after 3 still covers every distro. README and CONTRIBUTING updates ship inside each task. Everything I settled myself is under Decided.