Skip to main content

Module durable_ssh

Module durable_ssh 

Source
Expand description

Durable SSH terminals (P4 of SPEC_REMOTE_TERMINALS_AND_DURABLE_SESSIONS_2026_10_02.md, §7).

A pane on an SSH connection with term:durable set is not a local PTY. It runs ssh -T host -- agentmux-remote attach --session ID --offset N ... and speaks the helper’s frames (agentmux_remote::frame) over that channel: the shell itself lives in the helper’s daemon on the host, so a dropped link, a sleeping laptop or an AgentMux restart only drops this ssh, and the pane reattaches and gets exactly what it missed.

  • Output lands in the pane’s term file through the same append as a PTY’s (shell::handle_append_block_file), and the next remote offset is kept beside it in that file’s metadata (remote:offset), written right after each append, so a reattach asks for exactly what is missing.
  • The session id is the block’s remote:session_id, made on first start.
  • The status stays running while reconnecting; only the session’s own end (Exited) makes it done, which is what offers “press to restart”.
  • Reconnect never gives up while the pane is open (§7.4): backoff 1, 2, 5, 10, then every 30 s. A ping every 15 s, and an ssh silent for 35 s is killed and replaced rather than left to its own timeout (§7.5).
  • Closing the pane ends the session; quitting AgentMux detaches it (it keeps running on the host for the next start to reattach); a forced restart or a connection change detaches too.
  • ssh has no terminal here, so its prompts (a password, a passphrase, a new host key) go to the user through the askpass bridge (remote::askpass). A login it still cannot make stops the pane with the reason rather than asking again every 30 s.

Structs§

Done 🔒
How a pane’s run ended, when the pane should show it done.
DurableSshController
Inner 🔒
Run 🔒
One durable pane’s connection loop.

Enums§

Accept
What part of an Output frame the pane has not seen yet, given the next offset it expects.
Ended 🔒
How one ssh ended.
Leave 🔒
How the pane leaves its session.

Constants§

EXIT_COMMAND_NOT_FOUND 🔒
ssh exits 127 when the remote shell cannot find the command: no helper.
EXIT_GRACE 🔒
How long an ssh whose output ended has to exit before it is killed.
EXIT_SSH_FAILED 🔒
ssh’s own failures (it could not connect or log in) exit 255.
FILE_META_REMOTE_OFFSET
term file meta: the next offset of the remote session’s output.
FIRST_REACH_TRIES 🔒
Tries a pane durable only by default makes at a host it has never reached, and the helper never ran on, before it becomes a plain SSH terminal.
META_KEY_DURABLE
Block meta: turns a pane on an SSH connection into a durable one.
META_KEY_SESSION_ID
Block meta: the helper session this pane attaches to.
PING_EVERY 🔒
STALLED_AFTER 🔒

Statics§

APP_EXITING 🔒
Set when AgentMux is quitting: panes then detach (their sessions live on for the next start) instead of ending their sessions as a pane close does.

Functions§

accept
Decide what to do with output at offset, when the pane expects expected.
append_checked 🔒
Append to the pane’s term file, then tell the frontend where the bytes landed (the same blockfile append event a PTY’s output produces). Unlike the PTY path’s handle_append_block_file, which logs and swallows a store error, this says whether the bytes were stored, so the remote offset never moves past output that was lost.
attach_command
The command ssh runs on the host.
backoff
How long to wait before reconnect attempt attempt (0-based): 1, 2, 5, 10, then 30 s for ever. Never a last attempt: a cap is how a recoverable pane becomes a dead one.
helper_path
Where the helper is installed on the host: a versioned path, so two AgentMux versions can use one host (spec §6.2). ~ is the remote home.
login_refused
ssh could not log in, and trying again would only fail (or ask) again: refused credentials, or a host key it will not accept.
note_app_exiting
AgentMux is quitting (sagas::agent_teardown::app_exit).
show_done 🔒
Show the pane done with done.code; a session that is over is forgotten, so the next start makes a new one.
term_size 🔒
The pane’s size from its runtime options, as (cols, rows); 80 x 24 when it has none yet (the frontend resizes right after it attaches).
valid_session_id
A session id as the helper accepts it: letters, digits, - and _, up to 64 (agentmux-remote’s daemon::valid_session_id).
windows_answer 🔒
The host’s answer to cmd /c echo %OS%: Windows, not Windows, or None when ssh itself failed (exit 255, or no exit code) and the host never answered.
windows_shell_refused
The host’s shell is Windows’ (cmd or PowerShell), which can’t run the helper: it answered the attach command that it doesn’t know it.

Type Aliases§

Fallback
Restarts a pane through resync_controller, which then picks the plain shell controller because wants has turned false. Built by resync_controller itself, which holds everything a restart needs. False when it did not restart: the pane would still be durable (so a restart would only come back here), or the block is gone.