alden: detachable terminal sessions without breaking scrollback
Wed 11 Jun 2025 by mskala Tags used: linux, software, networkingFor a long time I've wanted to have a thing for resuming interrupted ssh sessions. The typical scenario is that I connect to a server with ssh, start a long-running task, and leave the window open so I can watch it. Then something causes the connection to break. Maybe I lose my local networking connection; maybe there's a power failure at my end; maybe I need to reboot my computer for some reason. What happens to the task on the server side?
Very often, a connection loss means the task on the server side will receive a SIGHUP and automatically terminate. If I don't want that to happen, I can plan ahead with such tools as "nohup," "disown," output redirection, and "tail -f," to keep the task running regardless of a lost connection. But there are a lot of compromises involved in doing that. In particular, it doesn't work well for tasks that really are in some way interactive; even if I can keep the task running, I don't have much ability to control and interact with it, once it's been spun off into the server's subconscious.
There are tools that provide in different ways for reconnecting to a disconnected terminal session. Some of the best-known are mosh, tmux, and screen. But they all break scrollback, in the sense that while running them, if text scrolls off the top of the screen, you can't scroll back to that text using the native scrollback feature of your GUI terminal emulator. They. Break. Scrollback. They violate one of the most basic rules of user interface design, especially significant for Web pages but also important for terminal-based applications: never mess with the scrollbar.
The tmux and screen packages are said to provide scrollback, or even to "support" scrollback, but that is true only in a limited and unsatisfactory sense: mosh, tmux, and screen are basically all terminal emulators themselves, which run as an additional layer inside your GUI terminal emulator. In the cases of tmux and screen, they have scrollback features of their own. So by using a different set of commands unique to tmux or screen, not the scrollbar built into your GUI, you can get access to the history of scrolled-away text in tmux or screen. But it remains that the GUI's native scrollback is broken when you use any of these.
The mosh developers add insult to injury because their stock response to complaints about how mosh breaks scrollback, is to tell users to use tmux or screen inside mosh. They have been taking that position since 2012.
Part of the problem there is that mosh's protocol is based on an abstraction that is not easy to reconcile with scrollback. Instead of conveying a stream of characters that resumes after interruption, mosh's protocol is based on the idea of keeping variables synchronized between the two ends of the connection. The distinction is important in computer-science terms, and necessary for mosh to do the things it does do that its creators consider high-priority. One advantage to the variable-synchronization approach is that it means the server does not need to keep arbitrarily large buffers of past history that the client may have missed; it only needs to keep the latest state of the variables, and allow the client to query back any parts that are not up to date.
But it's hard to even state the scrollback problem clearly in the language of keeping variables synchronized, let alone actually solve it. Proposals have included defining a "virtual" screen that is something like three times the height of the real screen, and keeping that synchronized in a place that the native scroll bars can reach - as if scrollback users would be satisfied with just two pages' worth of previous history. Having a system that allows scrollback to really work, pretty much requires returning to the abstraction of a stream of characters.
It's been 13 years, and this week I finally got sufficiently annoyed to sit down and write the utility I actually want: a thing for resuming terminal connections that does not act as a terminal emulator itself, instead passing traffic through to the native terminal so that scrollback won't break.
I call the result "alden," and you can download the first tarball source release here:
It's GPL3. It is, obviously, a work in progress. It works pretty well for my purposes already, but I only have bandwidth to add extra features and improve portability, if other people want to use it, and especially if other people want to write about it.
After building, run the "alden" command-line program to start a new shell, which will be wrapped inside a client and server. If you lose your network connection or the client dies for some other reason, the server and shell ought to survive. Then you can log back in again, type "alden" again, and be connected to the existing server and shell. Further details are in the man page inside the package; even further details will probably be in other documentation if and when I do another release.
Unlike mosh, this program does not implement a high-reliability networking protocol of its own. The only IPC it does is through local mechanisms like named pipes. You still have to create an ssh connection and then run alden inside your ssh connection, and on a really bad network with a lot of packet loss, it works no better than ssh does. The thing it's intended to protect against is, instead, the situation where a basically usable network connection is suddenly lost entirely.
By design, alden also does not interpret or translate terminal command sequences in any way, in either direction. The closest it comes is that it passes through SIGWINCH terminal-size updates, so if you resize your window, aware programs inside the alden session ought to be able to detect that and adjust themselves accordingly.
0 comments