thumbmux bringt passwortgeschützte mobile Web-Steuerung für tmux und AI-Agenten
Agenten wie Claude Code oder Codex laufen minuten- bis stundenlang im Terminal, lassen sich vom Handy aus aber schlecht überwachen. thumbmux bietet dafür eine mobile Weboberfläche, die von Anfang an passwortgeschützt ist.

Claude Code, Codex, OpenCode und ähnliche Tools laufen über Minuten oder Stunden in einem Terminal. Eine solche Session vom Handy über ein gewöhnliches Web-Terminal zu prüfen ist quälend: Die Tastatur kämpft mit der TUI, Autokorrektur verunstaltet die Eingaben, Scrollen ist nicht möglich, und alle Sessions sehen gleich aus. Ich habe thumbmux gebaut, eine mobile Weboberfläche für das eigene tmux: ein Tab pro Session, ein normales Textfeld, Scrollen per Swipe, Upload von Fotos und Dateien. Was meines Erachtens am wichtigsten ist, ist nicht die Oberfläche, sondern dass das Terminal hinter einem Passwort liegt und auf keinem offenen Port lauscht.
Ein Hinweis vorab: Die Oberfläche wurde für iOS Safari entworfen. Sie funktioniert in Desktop-Browsern, aber dort habe ich sie nicht ausgiebig getestet. Das Docker-Image und die VPN-Compose-Datei wurden auf dem Build-Rechner nicht getestet, weil dieser kein Docker hat. Die Serverseite ist durch Tests abgedeckt; die Screenshots unten stammen von einer Testinstanz, die in Chrome in iPhone-Größe geöffnet wurde.
Screenshots von einer Testinstanz mit Demo-Sessions, geöffnet in Chrome in iPhone-Größe.
Ein Web-Terminal ist eine Shell auf dem eigenen Rechner, die über HTTP erreichbar ist. Wenn sie ohne Passwort offen steht, ist das keine Unannehmlichkeit, sondern ein Loch: Jeder, der sie erreicht, kann Befehle im eigenen Namen ausführen. Jede Entscheidung in diesem Projekt wurde mit genau diesem Gedanken getroffen, deshalb beginne ich damit und nicht mit hübschen Screenshots.
Daraus folgt eine Betreibensregel: thumbmux hinter TLS betreiben. Im Repository finden sich Caddy- und nginx-Beispiele unter deploy/. Verwende besser eine eigene (Sub-)Domain statt eines Pfad-Präfix, leite den Host-Header weiter und setze THUMBMUX_TRUST_PROXY=1. Oder halte es auf dem Loopback-Interface und greife über einen SSH-Tunnel oder ein Overlay-Netzwerk wie Tailscale darauf zu. Veröffentliche den reinen HTTP-Port nicht im Internet. Und um ehrlich zu sein: Ein gemeinsames Passwort schützt eine ganze Shell, also wähle ein langes, einzigartiges.
Für eine stärkere Absicherung gibt es docker-compose.vpn.yml: Der Container läuft über ein VPN mit Kill-Switch, sodass er keinerlei Netzwerkzugriff hat, wenn der Tunnel abbricht. Diese Variante steht auf meiner Liste der nicht getesteten Dinge.
thumbmux ersetzt tmux nicht, es setzt sich davor. Die Sessions sind ganz normale, sodass man sich gleichzeitig per SSH verbinden und mit tmux attach -t phone dieselben Fenster sehen kann. Die Sessions laufen weiter, unabhängig davon, ob das Telefon verbunden ist oder nicht.
Der Server besteht aus einer einzigen Datei in reinem Python, ausschließlich Standardbibliothek, dazu ttyd und tmux. Installation ohne Docker:
sudo apt install tmux ttyd # oder: brew install tmux ttyd git clone https://github.com/meshoklv/thumbmux && cd thumbmux cp.env.example.env # optional THUMBMUX_PASSWORD setzen./run.sh Enter fullscreen mode Exit fullscreen mode Mit Docker ist es einfacher: docker compose up --build, ein zufälliges Passwort wird einmal in den Logs ausgegeben, und man öffnet http://127.0.0.1:7682. Wenn man THUMBMUX_TMUX_SOCKET setzt, gehen alle tmux-Aufrufe an diesen expliziten Socket statt an den normalen Server, was praktisch ist, um sie von den eigenen Haupt-Sessions fernzuhalten.
Neu in Unreleased: ein optionaler eingebauter Bot. Er meldet sich, wenn ein Tab fertig ist oder eine Frage stellt, mit den Schaltflächen "Reply" und "Open". Man antwortet mit Text oder einer Sprachnachricht, und diese wird in den richtigen Tab getippt. Es gibt /sessions, /new und /help. Er läuft im Server mittels Long-Polling, daher ist nur ausgehendes HTTPS nötig, kein Webhook und keine offenen Ports.
Und hier die wichtigste Warnung. Der Bot ist eine Remote-Eingabe in die eigene Shell: Wer ihm schreiben kann, führt Befehle im eigenen Namen aus. Deshalb ist die Integration standardmäßig deaktiviert und weigert sich zu starten, wenn ein Token gesetzt ist, während THUMBMUX_TG_ALLOWED_CHAT_IDS leer oder fehlerhaft ist. Sowohl der Chat als auch der Absender werden geprüft; alle anderen erhalten Schweigen (das Log hält eine Zeile ohne ihren Text fest). Das Token wird ausschließlich aus der Umgebung gelesen und niemals geloggt, die Eingabe ist auf 20 Nachrichten pro Minute und Chat begrenzt, und der Long-Poll-Offset wird in einer Datei mit den Rechten 600 gespeichert, damit alte Nachrichten nach einem Neustart nicht erneut zugestellt werden.
Ein zweiter Hinweis: Die Benachrichtigungen enthalten Terminal-Ausgaben, die also an Telegram gehen. Aktiviere die Integration nicht dort, wo Sessions Geheimnisse ausgeben. Und bisher habe ich sie nur gegen eine Fake-Bot-API in den Tests geprüft, nicht gegen den echten Telegram-Server.
Das Changelog enthält auch eine ehrliche Zeile zu einem behobenen Fehler: Der Start des Servers auf einer bereits existierenden tmux-Session ließ ihn durch eine nicht definierte Variable abstürzen. Behoben.
Ein Teil des Codes wurde zusammen mit einem KI-Assistenten (Claude) geschrieben; die Commit-Historie zeigt dies über eine Co-Authored-By-Zeile.
Repository: github.com/meshoklv/thumbmux, MIT-Lizenz. Issues und PRs sind offen; Schwachstellen bitte privat über GitHub Security Advisories melden. Notizen und neue Versionen poste ich auf Telegram unter t.me/meshoklv.
Automatisch übersetzt. Das Original auf Englisch ist unten aufklappbar.
Original (Englisch) anzeigen
Claude Code, Codex, OpenCode and similar tools run in a terminal for minutes or hours. Checking on such a session from a phone through an ordinary web terminal is miserable: the keyboard fights the TUI, autocorrect mangles prompts, there is no scrolling, and all sessions look the same. I built thumbmux, a mobile web interface for your own tmux: a tab per session, a normal text field, swipe scrolling, photo and file upload. What I think matters most isn't the interface but that the terminal is behind a password and listens on no open port.
A caveat up front: the interface was designed for iOS Safari. It works in desktop browsers, but I haven't poked at it there. The Docker image and the VPN compose file were not tested on the build machine, because it has no Docker. The server side is covered by tests; the screenshots below come from a test instance opened in Chrome at iPhone size.
Screenshots from a test instance with demo sessions, opened in Chrome at iPhone size.
A web terminal is a shell on your machine reachable over HTTP. If it's open without a password, that isn't an inconvenience, it's a hole: anyone who can reach it runs commands as you. Every decision in the project was made with that one thought in mind, so I'll start with them rather than with pretty screens.
From this follows an operating rule: put thumbmux behind TLS. The repository has Caddy and nginx examples in deploy/. Use a separate (sub)domain rather than a path prefix, forward the Host header and set THUMBMUX_TRUST_PROXY=1. Or keep it on loopback and reach it through an SSH tunnel or an overlay network such as Tailscale. Don't publish the plain-HTTP port to the internet. And to be honest about it: one shared password protects a whole shell, so choose a long, unique one.
For stronger insurance there is docker-compose.vpn.yml: the container goes through a VPN with a kill-switch, so if the tunnel drops it has no network at all. This variant is on my "not tested" list.
thumbmux doesn't replace tmux, it sits in front of it. The sessions are ordinary ones, so you can SSH in at the same time and run tmux attach -t phone to see the same windows. Sessions keep running whether or not the phone is connected.
The server is a single file of plain Python, standard library only, plus ttyd and tmux. Installing without Docker:
sudo apt install tmux ttyd # or: brew install tmux ttyd git clone https://github.com/meshoklv/thumbmux && cd thumbmux cp.env.example.env # optionally set THUMBMUX_PASSWORD./run.sh Enter fullscreen mode Exit fullscreen mode With Docker it's simpler: docker compose up --build, a random password is printed once in the logs, and you open http://127.0.0.1:7682. If you set THUMBMUX_TMUX_SOCKET, every tmux call goes to that explicit socket instead of your normal server, which is handy for keeping it away from your main sessions.
New in Unreleased: an optional built-in bot. It messages you when a tab finishes or asks a question, with "Reply" and "Open" buttons. Answer with text or a voice message and it is typed into the right tab. There are /sessions, /new and /help. It runs inside the server using long-polling, so only outbound HTTPS, no webhook and no open ports.
And here is the main warning. The bot is remote input into your shell: whoever can message it runs commands as you. So the integration is off by default and refuses to start if a token is set while THUMBMUX_TG_ALLOWED_CHAT_IDS is empty or malformed. Both the chat and the sender are checked; everyone else gets silence (the log keeps a line without their text). The token is read only from the environment and never logged, input is limited to 20 messages per minute per chat, and the long-poll offset is stored in a file with mode 600 so old messages aren't replayed after a restart.
A second caveat: notifications contain terminal output, so it goes to Telegram. Don't enable the integration where sessions print secrets. And so far I have tested it only against a fake Bot API in the tests, not against the real Telegram server.
The changelog also has an honest line about a fixed bug: starting the server on an already existing tmux session crashed it because of an undefined variable. Fixed.
Part of the code was written together with an AI assistant (Claude); the commit history shows this through a Co-Authored-By line.
Repository: github.com/meshoklv/thumbmux, MIT license. Issues and PRs are open; please report vulnerabilities privately through GitHub Security Advisories. I post notes and new versions on Telegram at t.me/meshoklv.