tty7: a terminal workbench for agents
tty7 is a Rust terminal workbench with a session daemon, native SSH and agent-aware panes. Install it, then see where tmux on the VPS still wins.
What tty7 is, and where it runs
tty7 is a terminal workbench written in Rust: shells, persistent sessions, a native SSH client and coding-agent awareness in one desktop application. It is a graphical program. It renders through Zed's gpui and takes its VT (virtual terminal) core from Alacritty, so it needs a display server and a window on the machine it runs on. That machine is your laptop, never your VPS.
That single fact decides how tty7 fits a server workflow. tty7 is the client. The VPS sits at the far end of an SSH connection. Everything tty7 keeps alive, it keeps alive on your desk.
The project lives at github.com/l0ng-ai/tty7 under the Apache 2.0 licence. As of July 2026 the current release is v26.7.6, and the Linux builds are x86_64 only.
Install tty7 on a Linux desktop
There is no apt repository and no Ubuntu package. The releases page carries an AppImage and a tar.gz archive.
cd ~/Downloads
curl -fLO https://github.com/l0ng-ai/tty7/releases/download/v26.7.6/tty7-26.7.6-linux-x86_64.AppImage
chmod +x tty7-26.7.6-linux-x86_64.AppImage
./tty7-26.7.6-linux-x86_64.AppImageThe README says the X11 and Wayland libraries are bundled inside the AppImage, so a normal desktop needs nothing else installed. A window should open on the first run.
The AppImage will not start on Ubuntu 24.04 without libfuse2t64
An AppImage is a compressed image that mounts itself at run time using FUSE (filesystem in userspace) version 2. Ubuntu 24.04 dropped the libfuse2 package: the 64-bit time_t transition renamed it to libfuse2t64. Ask apt for the old name and it reports nothing to install.
apt-cache policy libfuse2The line Candidate: (none) in that output is the whole problem. The AppImage then cannot load the library it needs, and it stops with a message naming the missing object:
dlopen(): error loading libfuse.so.2Install the renamed package, then confirm the shared library is registered:
sudo apt update && sudo apt install -y libfuse2t64
ldconfig -p | grep libfuse.so.2ldconfig -p should print a path such as /lib/x86_64-linux-gnu/libfuse.so.2. No output means the library is still missing, and the AppImage will keep failing the same way.
If you would rather not install FUSE at all, unpack the image instead. Every AppImage accepts this flag:
./tty7-26.7.6-linux-x86_64.AppImage --appimage-extract
./squashfs-root/AppRun--appimage-extract writes the contents into squashfs-root/ in the current directory and mounts nothing, so it works with no FUSE and no root access. The tar.gz build avoids the question too. List it before you unpack it, so you can see where the binary actually sits rather than guess:
curl -fLO https://github.com/l0ng-ai/tty7/releases/download/v26.7.6/tty7-26.7.6-linux-x86_64.tar.gz
tar -tzf tty7-26.7.6-linux-x86_64.tar.gz | headWhy you cannot run tty7 on the VPS itself
A fresh VPS image has no display server and no GPU, and tty7 is a GPU-drawn window. The project ships no headless build and no server component. So the split is fixed: tty7 on your machine, OpenSSH and a multiplexer on the server. The server half of the job does not change because the client got better, and running a coding agent on a VPS covers that half on its own terms.
Connect to the VPS with the built-in SSH client
tty7 carries its own SSH implementation built on the russh stack instead of shelling out to ssh. It offers saved connection profiles, passwords and passphrases held in the operating system keychain rather than in a plain file, an SFTP panel for browsing and moving files, port forwarding including a dynamic SOCKS mode, and multi-hop jump hosts through ProxyJump or ProxyCommand.
Keychain storage moves one thing worth thinking about. Your key passphrase now lives in the desktop secret store, so the safety of the connection is the safety of your desktop login. What you do with keys on the server side still matters, and SSH key management does not get easier because the client is prettier.
Port forwarding is the feature that pays off fastest with a VPS. A service bound to 127.0.0.1 on the server stays unreachable from the internet, and a local forward puts it on your laptop's loopback for the length of the session. That is how you reach an admin panel that should never listen on a public port.
What tty7's persistent sessions actually persist
tty7 keeps shells running in a small background daemon on the machine tty7 runs on. Close the window or reboot the desktop and the shells come back, with no tmux involved. That is real, and it is local.
An SSH pane is a different story, and the mechanism is the important part. Your shell on the VPS is a child of the sshd session for that one connection, attached to a pty (pseudo terminal) that sshd created for it. When the connection dies, sshd tears the session down and the pty is destroyed. The kernel then sends SIGHUP to the foreground process group on that terminal, so the agent or the long build running there is killed. tty7 can rebuild its own pane and open a fresh connection. It cannot bring back a process the VPS already stopped.
You can prove this in a minute. Start top over SSH, drop the network, then reconnect and look for it:
pgrep -u "$USER" -x topNo output and exit status 1. The process is gone. Persistence on the client does not reach across the wire.
Keep the work alive on the VPS with tmux
The tmux server runs on the VPS, and it is not a child of your SSH session, so a dropped connection never reaches it. Install it and check what you got:
sudo apt update && sudo apt install -y tmux
tmux -VUbuntu 24.04 ships tmux 3.4, so as of July 2026 that command prints tmux 3.4.
Give every session a name when you create it.
tmux new-session -d -s agent
tmux has-session -t agent
echo $?-d creates the session detached, so the command returns and you keep your prompt. has-session exits 0 when the session exists, and exits 1 with a message on stderr when it does not, which makes it the right test to put in a script. tmux ls prints one line per session, starting with the name and the window count.
Never target a session by number. tmux new-session -d with no -s names the session after the lowest free integer, so -t 0 means whichever session happens to be numbered 0 at that moment. Kill one session and create another, and that number points at a different shell. A name you chose yourself never moves.
You can also drive a session without attaching to it, which is what makes tmux scriptable:
tmux send-keys -t agent 'uptime' Enter
tmux capture-pane -p -t agent | tail -n 5send-keys types into the session, and the bare word Enter is the return key rather than five characters of text. capture-pane -p prints the visible pane to standard output. Attach with tmux attach -t agent, and detach with Ctrl+B then D. Detaching leaves every process running.
Why does tmux ls print error connecting to a socket path?
Removing the last session ends the tmux server, and the server unlinks its socket file as it exits.
tmux kill-session -t agent
tmux lsThe second command exits 1 and prints:
error connecting to /tmp/tmux-1000/default (No such file or directory)Read it literally. tmux tried to open a socket file, and the file is not there, because no server is running. The message does not mean a permissions problem. The socket directory is named after your numeric user ID, so id -u tells you which path is yours: the first normal account on a fresh VPS is 1000, and root is 0, which is why the same message names /tmp/tmux-0/default in a root shell. Start a named session again and both the socket and the listing come back. tmux prints a different message when the socket file is still present but the server behind it has gone.
tty7 against tmux, honestly
What tty7 gives you that tmux never tried to:
- Editor-grade input at the prompt: completion with explanations, syntax highlighting, ghost suggestions drawn from history, Ctrl+R fuzzy history search and a caret you can place with the mouse. tmux multiplexes terminals. It does not touch your command line.
- A full SSH client with profiles, keychain secrets, SFTP and forwarding in the same window as the shell.
- Per-pane agent detection, with a status dot, desktop notifications, branch and diff information, and a tray icon that signals when a pane is waiting for you.
- GPU-drawn output with smooth scrollback, plus a keybinding preset that puts pane and tab actions back behind a Ctrl+B prefix if your hands already know tmux.
What tmux still wins:
- It runs on the server, which is the only side where persistence survives your laptop.
- It is one apt package on every distro, and it works through any terminal at all. Driving Claude Code from a phone works because tmux is sitting on the far end.
- It is scriptable from a plain shell with
send-keys,capture-paneandhas-session, so a cron job or a deploy script can talk to a live session. - Two people can attach to the same session and watch the same screen.
The two tools solve different halves. tty7 is the window on your desk. tmux is what outlives it on the server.
Running coding agents in tmux, watched from tty7
tty7 recognises coding agents running in a pane (Claude Code, Codex, Gemini CLI, Aider, Amp, OpenCode and around ten more), shows their status, and can relaunch a conversation with its original flags after a restart. Those features read the pane on your machine. A pane holding an SSH connection is a single ssh process locally, so check for yourself whether detection follows an agent to the far side before you build a habit on it.
The arrangement that survives a dropped connection is simple. The agent runs inside a named tmux session on the VPS, and tty7 supplies the window, the profile and the notification.
ssh user@203.0.113.10 -t 'tmux new-session -A -s agent'-A attaches to the session called agent if it exists and creates it if it does not, so the same line is safe to run every time. -t forces a pty, which tmux needs in order to attach. Close the laptop in the middle of a task and the agent keeps working on the server. Reconnect with the identical command and you are back on the same screen. Running Claude Code on a VPS inside tmux walks through that layout in detail, including how to leave a long task running overnight.
When the server does not know your terminal type
Full-screen programs on the VPS read TERM to learn which escape sequences your terminal understands. If the name your terminal sets has no entry in the server's terminfo database, those programs fail before they draw anything. Check it on the VPS:
echo "$TERM"
infocmp "$TERM" > /dev/null
echo $?A non-zero status means this server has no entry under that name. Two fixes work. Override the type for one connection with TERM=xterm-256color ssh user@203.0.113.10, which is enough for almost everything. Or copy your own entry to the server once, into your home directory there:
infocmp -x "$TERM" | ssh user@203.0.113.10 -- tic -x -One related surprise is worth knowing. OpenSSH sends TERM inside the pty request and otherwise sends only the variables named by SendEnv, which on Ubuntu means LANG and LC_*. tty7 identifies itself through TERM_PROGRAM in the local shell, and that variable never reaches the VPS. A script on the server that branches on TERM_PROGRAM sees an empty string.
FAQ
Can I install tty7 on my VPS?
No. tty7 is a graphical desktop application that renders through the GPU using Zed's gpui, and the Linux release is an x86_64 AppImage or tar.gz built for a desktop. A standard VPS image has no display server and no GPU, and the project ships no headless build. Run tty7 on your own computer and reach the server through its SSH client.
Do tty7's persistent sessions keep my process running on the server?
No. The daemon that holds sessions runs on the machine tty7 runs on. A shell you opened over SSH is a child of the sshd session on the VPS, so when the connection drops the pty is destroyed and the kernel sends SIGHUP to the foreground process group. Your agent dies there, and tty7 can only restore its own end of the pane. Start anything long inside a named tmux session on the VPS.
Why does tmux ls print error connecting to /tmp/tmux-1000/default?
Because no tmux server is running, so the socket file named in that message does not exist. Killing the last session stops the server, and the server removes the socket as it exits. The number in the path is your user ID from id -u, so a root shell sees /tmp/tmux-0/default instead. Run tmux new-session -d -s agent and both the socket and the listing come back.
Why does the tty7 AppImage fail on Ubuntu 24.04?
Because the AppImage mounts itself with FUSE 2 and Ubuntu 24.04 renamed that package during the 64-bit time_t transition. apt-cache policy libfuse2 reports Candidate: (none), and the AppImage stops with dlopen(): error loading libfuse.so.2. Install libfuse2t64, or skip FUSE entirely by running the image with --appimage-extract and starting ./squashfs-root/AppRun.
Which coding agent CLIs does tty7 detect?
The project lists around seventeen, naming Claude Code, Codex, Gemini CLI, Aider, Amp and OpenCode among them. Detection is per pane, and it drives the status dot and the notifications. It reads the process running in the local pane, so confirm the behaviour you expect before relying on it through an SSH connection.