Named sessions and etserver restart survival - #793
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #793 +/- ##
==========================================
+ Coverage 78.86% 79.71% +0.84%
==========================================
Files 143 150 +7
Lines 18176 21233 +3057
Branches 11619 13775 +2156
==========================================
+ Hits 14334 16925 +2591
- Misses 2303 2559 +256
- Partials 1539 1749 +210 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
|
@epsalmond Why close this? |
|
@MisterTea is was vibe-opened and wasn't ready. I've since made a ton of improvements, it actually works as intended, and it's my full-time terminal workflow. If you're interested in it I'll re-open it with a month worth's of updates and bugfixes. |
|
Sure, go for it |
cd71a07 to
1584571
Compare
e50d130 to
7a4c4b7
Compare
|
Nice work on this PR. Restart survival and the reset handshake are real gaps for sessions. Just flagging one thing: #819 also adds a client-side The one in #819 is a much thinner piece (just a cached reconnect id/passkey with no restart survival and no title capture), and is needed for |
|
@Kronuz Thanks! It has been battle-tested. I had to stand up a windows vm to work through some of the stuff that has landed since I first opened this, and today there are a few merge conflicts. I expect I'll be ready to merge today. |
7a1d98e to
cca7db5
Compare
84d638c to
241fad5
Compare
|
@MisterTea @Kronuz I think this is ready. Freebsd test failed this run but it looks flakey. PR is updated. Protocol backwards-compatible (so no bump) and I cleaned up the commits and comments. Rebased on top of #850 and #855. Two bugfixes for master included: a terminal that re-registers after a restart never started the #855 disconnect deadline, and the #850 positional-command parser lost the host after the jumphost flag. I don't have anything for the control plane in this PR but I'm happy to do a follow up on top of #819 to add |
|
@Kronuz if this PR lands, what's the state of your PRs? Would you rebase on this? |
|
I want this too, let me know how I can be of any help. |
|
@MisterTea Yes, and I've already done the rebase: both of my PRs are rebased onto 793's head and pushed, as |
A client resuming a session from a fresh process has no sequence history, so both sides can now reset their state and rekey from a server-chosen salt. The server honors a reset only after a keyed challenge, offered to clients that set supportsChallenge, and proves its decision back. Plain connects never ask for a reset. PROTOCOL_VERSION stays 6; older peers get the original handshake, and that legacy path goes away at the next version bump.
|
Main moved out from under me again. Should I rebase again? (jk I already am). Excited to get this in but let me know if I should hold off, or let me know when this is up next and I'll wait. |
et saves each direct session's endpoint, id, and passkey under ~/.et/sessions so --attach can resume it from a new process with a reset; --list and --kill manage the records. Jumphost and -T sessions are not saved. SshSetupHandler no longer echoes server output in its errors, since that output can contain the credentials; this drops the old hint about a .bashrc that prints.
When the router goes away, etterminal keeps its shell and re-registers with the same credentials, retrying indefinitely with backoff capped at 30s, and the new server resumes the session with a reset. For 60s after startup the server answers unknown ids with RETRY_LATER so clients wait for re-registration. -T sessions end instead, since their packet-framed stream cannot be resumed. Stopping etserver leaves shells running until they exit or --disconnect-timeout closes them.
241fad5 to
0400273
Compare
|
Rebased again, should be clean to merge. |
Keep reset recovery together with catchup ordering, OpenSSH short flags, and the per-session disconnect timeout so the branch can merge. Co-authored-by: Cursor <cursoragent@cursor.com>
etterminal re-advertises the client's timeout when it re-registers, so a resumed pump does not fall back to the server global. Co-authored-by: Cursor <cursoragent@cursor.com>
Raw terminal bytes were parsed as a packet length, which dropped the session and failed the Windows vcpkg tests. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Any way to test this without having to build it myself? Maybe a dev nightly build somewhere? Sorry if the questions is already answered elsewhere... |
|
There are a ton of changes so we'll cut a 8.0 release soon
…On Sun, Sep 27, 2026, 9:51 AM Peter ***@***.***> wrote:
*psennats* left a comment (MisterTea/EternalTerminal#793)
<#793 (comment)>
Any way to test this without having to build it myself? Maybe a dev
nightly build somewhere? Sorry if the questions is already answered
elsewhere...
—
Reply to this email directly, view it on GitHub
<#793?email_source=notifications&email_token=AACK5P6T62NUBVSDVMR3XF35RESPLA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKOBVGY4TEMBUGIY2M4TFMFZW63VMON2GC5DFL5RWQYLOM5S2KZLWMVXHJLDGN5XXIZLSL5RWY2LDNM#issuecomment-5856920421>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AACK5P45OK2ZY5CSYCOZ5RT5RESPLAVCNFSNUABEKJSXA33TNF2G64TZHM3TIMRSGMYTMMR3JFZXG5LFHM2TEMBXG4YDINRWGGQXMAQ>
.
Triage notifications, keep track of coding agent tasks and review pull
requests on the go with GitHub Mobile for iOS
<https://github.com/notifications/mobile/ios/AACK5P3DKCEM6FERKXNVIT35RESPLA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKOBVGY4TEMBUGIY2M4TFMFZW63VMON2GC5DFL5RWQYLOM5S2KZLWMVXHJKTGN5XXIZLSL5UW64Y>
and Android
<https://github.com/notifications/mobile/android/AACK5P4USSV7DPD5PFF6WI35RESPLA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKOBVGY4TEMBUGIY2M4TFMFZW63VMON2GC5DFL5RWQYLOM5S2KZLWMVXHJLTGN5XXIZLSL5QW4ZDSN5UWI>.
Download it today!
You are receiving this because you modified the open/close state.Message
ID: ***@***.***>
|
Sessions get a name, persist across client crashes and reboots, and survive
etserverrestarts.I started this work because ubuntu was killing all my sessions at 3am doing updates. Then continued because (surprise!) there was a memory leak in node eating all the memory on my laptop. And an NFS bug in osx was rebooting me.
For the last month, having ~20 sessions open across tabs in two ghostty windows has been my primary workflow.
QoL improvements have happened along the way including being noisier when stealing a session from an active session. Further improvements could be detecting and cleaning up stale sessions.
Client
et --name <n>creates or reattaches a named session. Direct connections persist by default with a short generated name;--no-persistopts out.et --listshows saved sessions with their captured terminal title and last heartbeat.--attachreattaches,--killterminates a named session on the server.~/.et/sessions/with owner-only permissions, atomic no-clobber writes, and SSH setup errors no longer echo server's output to prevent passkey leakageProtocol
Server
etterminalkeeps the pty alive when the router drops and re-registers with bounded backoff, sosystemctl restart etno longer kills sessions.Tests
I'm working on resolving these:High:
Reset recovery can be triggered by a known client ID without passkey proof, allowing disruption/data loss.doneMedium:
Windows router restart and --kill behavior are incomplete.doneRestart during initial Unix setup is not recovered.doneexternal/UniversalStacktrace moves backward to an ancestor commit.donename can silently ignore newly requested forwarding options.doneFixed /tmp paths and broad pkill patterns make some shell tests unsafe for concurrent runs.doneRejected:
Reset recovery is incompatible with older peers while the protocol version remains unchanged.I'm rejecting this one because this only matters when etserver restarts and comes up as the new version. Before this PR, etserver loses its keys and clients are dropped anyway. So in practice this can't be reached.