When an SSH session ends — dropped Wi-Fi, closed laptop, mobile tunnel gone — the shell that ran inside it receives the SIGHUP signal and its foreground jobs are terminated. To keep work alive past a disconnect you have a spectrum of tools: nohup and disown detach individual processes, setsid moves a command into its own session, terminal multiplexers like tmux and screen hold entire sessions you can reattach to, and mosh keeps an interactive session alive through network changes. CLIAnywhere solves the problem at a different layer: the session lives on the host computer natively, and the phone is just one client that comes and goes.
Short Answer
If you work over SSH, run your work inside tmux (or GNU screen) on the machine you connect to — the session survives the disconnect and tmux attach brings it back, scrollback included. For a single command you forgot to wrap, Ctrl-Z, bg, disown can rescue it, and nohup protects the next one. If your actual goal is using that machine from your phone, CLIAnywhere gives you the same property by default: the session runs on your PC, so disconnecting the phone costs you nothing — reconnect and the shell, its jobs and its scrollback are still there.
Why This Is Difficult
A terminal session is a chain: your keyboard feeds an SSH connection, SSH feeds a pseudo-terminal (PTY) created by sshd on the remote machine, and the PTY is the controlling terminal of the shell that runs against it. When the TCP connection drops, sshd closes its end of the PTY. The kernel reacts by sending SIGHUP — "hangup", a name inherited from modems — to the session leader, normally your shell. A well-behaved shell forwards the signal to its jobs, and the foreground command exits.
The important detail is that nothing failed. The machine is fine, the filesystem is fine, your shell's environment is gone only because its terminal is gone. The problem is purely architectural: the lifetime of your work was tied to the lifetime of the connection.
That coupling has a second cost. Even if a process survives (because it ignored the signal), the output it printed after the disconnect went nowhere recoverable, and you cannot get an interactive prompt back — nohup writes to a log file, but you cannot type into a job you detached. Reattachment requires something that owns the terminal session independently of any single client: a multiplexer, or a session hosted on the machine itself.
Common Solutions
Option 1: nohup — detach one command
nohup ./long-job.sh & starts the command with SIGHUP set to be ignored and redirects output to nohup.out (or your own file with > log.txt 2>&1). The job keeps running after the shell dies, and you can check on it later with tail -f log.txt.
Limits: it is non-interactive — you cannot answer a prompt the job asks, and you cannot reattach to it. It must also be typed before the command starts, which is exactly the moment you are not thinking about disconnects.
Best for: fire-and-forget batch jobs where a log file is enoughOption 2: disown and setsid — rescue or pre-detach
Already running the job in a shell? Suspend it with Ctrl-Z, resume it in the background with bg, then remove it from the shell's job table with disown. The shell no longer sends it SIGHUP on exit. setsid ./long-job.sh takes the opposite order: it starts the command in a brand-new session with no controlling terminal at all, so there is no hangup to receive.
Same fundamental limit as nohup: the process survives, the interactivity does not. disown also only works on jobs of the current shell — it cannot save a command running in another window.
Option 3: tmux or GNU screen — sessions you reattach to
A multiplexer runs a server process on the machine you work on, and that server owns the PTYs. Start tmux once, work inside it, and disconnects become irrelevant: tmux attach from the next SSH login returns you to the same windows, the same running programs, and the same scrollback. screen does the same with older syntax (screen -r). This is the canonical answer for a reason — it works everywhere, on every Unix-like system, with no extra infrastructure.
The friction is habit and client: you must remember to start the multiplexer before the work (a plain shell that dies is still gone), and on a phone, an SSH client plus tmux's prefix keys are a lot of thumb-work on a touch keyboard. tmux also does nothing about reaching the machine in the first place — you still need SSH access from wherever you are.
Best for: anyone working over SSH on servers and dev machinesOption 4: mosh — survive the network, not the exit
Mosh replaces the TCP connection with UDP and keeps a roaming session alive across IP changes, laptop sleep and high-latency links — the client reconnects automatically and shows predicted local echo while it waits. For interactive work on a flaky connection, it feels far better than SSH.
But mosh solves a different slice of the problem: it keeps the connection alive, not the session. Exit the client and the session ends; mosh has no detach/reattach model and no scrollback. It also needs mosh-server on the host and a range of open UDP ports (60000–61000 by default), which many networks do not allow.
Option 5: CLIAnywhere — the session lives on the host
CLIAnywhere moves the ownership question one layer down. The daemon on your PC hosts the terminal session, the same way a tmux server does — but that is the default state, not a habit you have to remember, and the phone client is a first-class viewer rather than an SSH app. Close the app, take a call, ride the subway: the shell, its foreground job and its scrollback keep running on the PC.
Reconnecting from the phone — or switching to the desktop client and back — attaches to the same session. There is no SSH server to expose, no key to install on the phone, and no port forwarding: the daemon makes an outbound connection, peer-to-peer over DTLS where possible with an encrypted relay as fallback.
Best for: using your own PC's terminal from a phone without managing SSHUsing CLIAnywhere
Install the daemon on the PC that runs your work
The open-source daemon runs on Windows, macOS or Linux and is installed from GitHub Releases — the setup guide has the tabbed build instructions for each platform. On the phone, install the Android app from Google Play, the iOS app from the App Store (see the download page), or open the Web App in any browser.
Link the app to your PC
Create an access key in the app and link it to the daemon — paste the key, or scan the daemon's QR code. The pairing uses a local SPAKE2 key exchange; the Security Code is generated on your PC and never uploaded. Your PC then shows up in the app's device list, and one account can link multiple PCs, each with its own code.
Start your work, then forget about the connection
Open the session on the PC and run the long command — a migration, a build, an install — exactly as you would at the desk. Pick up the phone, open CLIAnywhere, and the same session is there. Close the app mid-command and nothing happens on the PC: the job keeps running, output keeps accumulating into the session's scrollback, and the next connection — phone, web client, or the desktop itself — attaches to the very same shell.
| Session survives client disconnect | Yes — session runs on the host PC |
|---|---|
| Scrollback preserved across reconnects | Yes |
| Desktop ↔ mobile session switching | Yes |
| Command needed to protect a session | None — persistence is the default |
| Windows / macOS / Linux host | Yes (Linux: desktop UI or headless CLI build) |
| iOS / Android / Web client | Yes — see the download page |
| Shells | bash / zsh / fish / sh / cmd / pwsh / powershell |
| SSH server, port forwarding or public IP required | No |
| Encryption | SPAKE2 key exchange + AES-256-GCM, P2P (DTLS) with encrypted relay (WSS) fallback |
| Open-source daemon | Yes — github.com/CLIAnywhere/clianywhere_daemon |
Example: A Two-Hour Data Job and a Train Ride
You kick off a heavy job before leaving the office — say ./migrate.sh, which walks a database in batches and prints a progress line every few seconds. At your desk it is a normal foreground command in a normal terminal window.
With plain SSH this is the moment of risk: if you had started it over SSH from a laptop and the laptop sleeps, the shell gets SIGHUP and the migration dies mid-batch. The classic protection is to have planned ahead — tmux new -s migrate before starting, then tmux attach -t migrate later — and it works, provided you remembered, and provided you can reach the machine over SSH from the train.
With CLIAnywhere there was nothing to remember. Twenty minutes into the ride you open the app, tap your PC, and the migration is exactly where it was — still printing progress, scrollback intact from the first line. You scroll up, confirm batch 4 of 7 finished, lock the phone, and check again at home from the desktop. Same session the whole way; the connection went in and out and the job never knew.
Security
Keep-in-running techniques do not change who can reach the machine — that is a separate question, and for SSH it usually means an exposed port and key management. CLIAnywhere keeps the host unexposed: no inbound ports, keys negotiated locally via SPAKE2, traffic encrypted with AES-256-GCM, peer-to-peer over DTLS where possible, and a relay that only ever sees ciphertext. See how CLIAnywhere handles security for details.