Announcing ssh-obi — keeping SSH shells alive across disconnects, sleeps, and network roams

A lightweight, per-user persistence layer for interactive SSH sessions: no system service, no custom port, no in-band escape commands — and unlike mosh, your local terminal's scrollback keeps working.

Announcing ssh-obi — keeping SSH shells alive across disconnects, sleeps, and network roams

A lightweight, per-user persistence layer for interactive SSH sessions: no system service, no custom port, no in-band escape commands — and unlike mosh, your local terminal's scrollback keeps working.

Published by the Human-life Information Platforms Institute (Menhera.org)

May 2026


TL;DR

We have released ssh-obi v0.1.0, a small Rust tool that keeps your remote shell alive when the SSH connection drops, when your laptop sleeps, or when you roam between Wi-Fi and cellular. It tunnels everything over your existing SSH config — no separate port, no UDP, no setuid binary, no system-wide daemon.

Install on Windows (client-only):

powershell -NoProfile -ExecutionPolicy Bypass -Command "irm https://obi.menhera.org/bootstrap.ps1 | iex"

Or with a Rust toolchain:

cargo install ssh-obi

Install on Unix-like systems (client + server):

wget -O - https://obi.menhera.org/bootstrap.sh | sh -s -- --install

Or with a Rust toolchain:

cargo install --features=server-bin ssh-obi

Then connect exactly the way you already do:

ssh-obi user@example.com

That's the entire user-visible surface for the common case. The remote server component bootstraps itself the first time you connect (with confirmation), under your unprivileged user account.

Documentation, release tarballs, and bootstrap scripts: https://obi.menhera.org/ Source code: https://github.com/menhera-org/ssh-obi Crates.io: https://crates.io/crates/ssh-obi


What is ssh-obi?

ssh-obi is a per-user terminal persistence layer for SSH. The name comes from obi (帯), the Japanese sash that holds a kimono together — fitting for a tool whose job is to keep a remote shell tied to your terminal across disconnects.

It is designed to feel like plain SSH:

  • It uses the same destination names, keys, jump hosts, and SSH config you already use.
  • Your local terminal's scrollback, search, selection, and copy/paste keep working.
  • The remote shell survives a network break; reconnect with the same command and you are reattached.
  • You can keep several independent sessions open on the same remote account.
  • Installation is per-user. No root service, no custom network port.

It is intentionally not a terminal window manager. It does not implement panes, tabs, or in-band escape commands. If you want window management, run tmux or another multiplexer inside the remote shell — ssh-obi will keep that tmux alive across your disconnects, and tmux will give you the panes.

Why this exists

If you do interactive work over SSH, you have probably hit at least one of these:

  • A cargo build, make, training run, long rsync, or database migration that you have to either babysit or wrap in nohup/screen/tmux defensively.
  • Your laptop sleeps and you come back to a half-dead SSH connection that needs to be killed and rebuilt.
  • Tethering switches from Wi-Fi to LTE and the SSH session silently freezes for two minutes before TCP gives up.
  • You have a long-running editor session you cannot easily move between machines.

There are well-known answers to this:

  • tmux / screen on the remote are excellent. They are also a separate workflow that requires conscious "I should attach to tmux" discipline before every long task, and their key bindings clash with each other and with applications.
  • mosh solves the network-roaming problem beautifully but takes ownership of the terminal screen — your local terminal's scrollback stops being the source of truth for what you saw, and search/copy/paste behave differently. It also requires UDP and a non-default port range, which is awkward through firewalls and bastion hosts.
  • Eternal Terminal (et) keeps shells alive but expects a system-wide daemon installed by an administrator on the server.

ssh-obi is a deliberately narrower answer. It does one thing: it keeps the bytes flowing to and from the shell across SSH disconnects, with the local terminal still owning the screen. Everything outside that scope (panes, tabs, screen replication, alternate transports) is left to other tools.

How it compares

ssh-obi mosh Eternal Terminal tmux/screen alone
Survives network drops only if combined with SSH retry
Local terminal owns scrollback ❌ (mosh redraws the screen) ❌ (with defaults)
Uses plain SSH (no extra port/UDP) ❌ (UDP, custom port range) ❌ (custom TCP port)
Per-user install (no admin needed) usually ✅ ❌ (system service)
Independent from window/pane management ✅ (use tmux)
Multiple persistent sessions per user

The trade-off worth being honest about: because ssh-obi does not own the screen, the bounded-buffer replay on reconnect can briefly duplicate output that was already on your terminal before the disconnect. This is acceptable — your local scrollback already has the original copy, and the duplicated bytes scroll past once. We considered the alternative (mosh-style screen reconstruction) and decided that giving up native scrollback was a worse trade than tolerating the occasional repeat.

Quick start

Install the client locally (see the TL;DR for one-line installers).

Connect:

ssh-obi user@example.com

The first time you connect to a given remote, the client offers to install the small server component into ~/.ssh-obi/bin on that account. No root access is required, and nothing system-wide is touched.

After that, repeat invocations behave like this:

  • No existing free session → a new one is created and you are attached.
  • Exactly one free session → you are auto-attached to it.
  • Multiple free sessions → a local picker shows them with init time, last detach time, and a best-effort guess at what is currently running (bash, vim notes.md, cargo watch, …).

Force a new session, list sessions, attach to a specific one, or boot a stuck attached client:

ssh-obi --new user@example.com
ssh-obi --list user@example.com
ssh-obi --session abc123 user@example.com
ssh-obi --detach --session abc123 user@example.com

To detach cleanly from inside the remote shell without killing it:

ssh-obi-server --detach

That tells the remote daemon "drop the client, keep the shell." Closing your laptop, losing Wi-Fi, or killing the local SSH process is treated differently — the client interprets that as ambiguous and tries to reconnect to the same session.

Scope and non-goals

These are commitments, not "not yet":

  • No window or pane management. Pure 1:1 forwarding between local TTY and remote PTY. Use tmux for multiplexing.
  • No in-band escape sequences. The bytes you type are the bytes the remote shell receives. Detach is performed by running a separate command (ssh-obi-server --detach), not by a magic key combination.
  • Not a screen-state replicator. Only a bounded recent-output buffer is replayed on reconnect. Older history lives in the local terminal's scrollback, which is where it belongs.
  • Windows is client-only. Remote servers are Unix-like. There is no plan to ship a Windows server.

Platform support

Local client: Linux, macOS, Windows x86_64, and FreeBSD/NetBSD/illumos where release artifacts are published. The client requires a working system ssh binary; ssh-obi does not reimplement SSH.

Remote server: Linux, macOS, FreeBSD, NetBSD, illumos. systemd-based distributions are supported, but systemd is not required — the daemon is a plain per-user process that does not depend on any system service manager.

Release tarballs are published for the following targets at https://obi.menhera.org/:

  • release-x86_64-unknown-linux-musl.tar.gz
  • release-aarch64-unknown-linux-musl.tar.gz
  • release-riscv64gc-unknown-linux-musl.tar.gz
  • release-powerpc64le-unknown-linux-musl.tar.gz
  • release-s390x-unknown-linux-musl.tar.gz
  • release-x86_64-apple-darwin.tar.gz
  • release-aarch64-apple-darwin.tar.gz
  • release-x86_64-unknown-freebsd.tar.gz
  • release-x86_64-unknown-netbsd.tar.gz
  • release-x86_64-unknown-illumos.tar.gz
  • release-x86_64-pc-windows-msvc.tar.gz (client only)

A note on security model

ssh-obi does not change SSH's security model. The transport is whatever your ssh binary already negotiates: same keys, same known_hosts, same ProxyJump, same multi-factor prompts. The persistent server runs as your unprivileged remote user, listens only on a UNIX-domain socket inside /tmp/ssh-obi-<uid>/ (mode 0700, ownership-checked on reuse, refuses to start on NFS/SMB), and is only ever spoken to over SSH.

There is no setuid binary, no shared state between users, no listening TCP/UDP port introduced anywhere on the remote, and no system service that an administrator would need to audit. If a remote account is compromised, the attacker has the same access they would have had via plain sshssh-obi does not enlarge the blast radius.

For v0.1.0, the auto-install bootstrap downloads release tarballs over HTTPS without an additional signature check. We trust HTTPS for the MVP and intend to add signature verification before declaring 1.0. Users who want stronger assurance today can install via cargo install ssh-obi --features=server-bin on the remote, which goes through the crates.io supply chain instead.

Status

v0.1.0 is the first public release: usable, documented, but young. The CLI surface (ssh-obi, ssh-obi-server) is the user-facing contract and we intend to keep it stable. The wire protocol between client and server is forward-compatible by capability negotiation rather than version bumping — once a capability ships, its message format is frozen, and new functionality arrives as new capability strings rather than as edits to existing ones. Library APIs (ssh_obi as a crate dependency) are not yet stable.

Bug reports, feedback, and pull requests are welcome at https://github.com/menhera-org/ssh-obi.

Why a Japanese nonprofit is shipping this

Menhera.org (the Human-life Information Platforms Institute, 一般社団法人生活情報基盤研究機構) is a Japan-incorporated nonprofit whose mission is to empower individuals with more freedoms by designing IT systems, infrastructure, protocols, and more. We operate AS63806 as a research autonomous system of the Internet, with a focus on privacy and protocol work.

Most of our day-to-day operations involve interactive SSH on long-running tasks across multiple machines. The existing options for shell persistence each made a trade-off we were not happy to keep paying — either they took over the terminal screen, or they required an administrator to install something system-wide, or they introduced a separate transport that did not pass through the same firewalls and bastions as our regular SSH. So we built the tool we wanted, and we are publishing it because we suspect we are not the only ones who wanted it.

The software is dual-licensed at the user's option under either Apache-2.0 or MPL-2.0. Use it freely, fork it, package it for your distribution, redistribute it.

License

Dual-licensed at the user's option under:

  • Apache License, Version 2.0
  • Mozilla Public License, Version 2.0

Contact


The Human-life Information Platforms Institute is a Japan-incorporated nonprofit (一般社団法人生活情報基盤研究機構). This software is provided as a public good in alignment with the Institute's mission. No warranty is expressed or implied. Use at your own discretion.


This post was initially drafted with Claude Opus 4.7 (an LLM) but it incorporates substantial manual review and changes. The author takes full responsibility on this content.

Read more

Copyright © Human-life Information Platforms Institute (Menhera.org), incorporated in Japan (JCN7050005013201). Menhera® is the registered trademark of Human-life Information Platforms Institute.

Content is avaiable under a CC-BY-SA license, unless otherwise stated.