Hongwei Qinandl0ng-ai 557bfd3f3a fix(ui): resync local windows when the daemon comes back as a new process (#553) (#569)
* fix(ui): resync local windows when the daemon comes back as a new process (#553)

From the client's side a killed daemon is indistinguishable from one
whose shells all exited at once — its DeathReporter says nothing while
it shuts down, and a taskkill says nothing ever — so the window kept
showing every pane with its last title, and the reconnect then pushed
that dead layout back up as the new daemon's truth. On Windows a
force-killed daemon can even leave the shells themselves alive but
permanently unreachable.

The control handshake already carries an instance id per server
process, and the remote path already compared it (server_restarted);
the local link never did. Now LocalLink remembers the hello instance —
across invalidate(), deliberately, or the restart path's own first move
would blind the comparison — and a changed instance on reconnect routes
every local window through resync_after_local_daemon_change instead of
on_link_up: the dead link is dropped first, then hydrate rebuilds from
the machine tree and each pane comes back from its scrollback snapshot
with the "new shell" banner.

note_instance moves to tree_sync as the shared comparison (empty
instance = server predates the field, never a restart, never
overwrites), with the remote callers and their tests repointed. The
restart-server action now uses the same helper instead of open-coding
invalidate + resync, which also fixes it rebuilding only the current
window when several local windows are open.

Per the review, the title wording ("process exited" while the link was
down) and the missing Respawn menu item are a separate PR: the current
wording is pinned by a_dropped_link_does_not_claim_the_process_exited
and changing it is its own decision.

* docs(changelog): entry for the local-daemon reconnect resync (#553)

* fix(ui): keep the reconnect's own link when the daemon came back new

The reconnect installs the new daemon's client and then, on a changed
instance, called the helper that starts by dropping it. The link the
handshake had just proved good was thrown away, every window's pull went
out with nothing to send it on, and the layout had to wait for the next
tick to connect a second time.

That is not only wasted work. `hydrate` gives the link fifteen seconds to
come back and then owes the window a `Replace` — and a `Replace` is
abandoned the moment the window has tabs, which in this scenario it
always does: the dead ones still on screen are the whole bug. So a slow
second connect turned the resync into nothing at all, silently.

Split the helper: `resync_after_local_daemon_change` still invalidates
first, for the restart-server path whose link really does point at a
server it killed, and `resync_local_windows_from_tree` is the half the
reconnect wants, with the fresh link left in place.

The two note_instance tests that moved here with the function now say
what tree_sync's own tests say; the one that is this module's — the slot
is per host — stays.

---------

Co-authored-by: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com>
2026-08-13 09:05:04 +08:00
2026-08-12 18:41:37 +08:00
2026-08-12 18:41:37 +08:00

tty7

tty7

A terminal workbench: persistent sessions, remote work, agents.

Pure Rust · GPU rendering on Zed's gpui · VT core from Alacritty


CI Version License Discord

English · 简体中文


tty7 with a tab sidebar of agent sessions across several repos, running Claude Code

Why

  • Performance — ~2× the throughput of Alacritty, Ghostty, or Kitty (benchmarks)
  • Persistent sessions — quit or reboot; your shells and supported agent sessions keep running, no tmux
  • Editor-grade input — suggestions, completion, highlighting, history search
  • Remote development — files, repos, panes, and git data stay on the remote machine
  • Native SSH — profiles, SFTP, port forwarding, and jump hosts
  • Agent-aware — Claude Code, Codex & co.: status, notifications, git context
  • CLI + Skills — agents create panes, run commands, and inspect output

Install

Native builds for each platform on Releases:

macOS …-macos-arm64.dmg · …-x86_64.dmg drag into Applications
Windows …-setup.exe · portable ….zip
Linux …-x86_64.AppImage chmod +x and run — X11/Wayland libraries bundled

What's inside

Editor-grade input ghost suggestions from history · explained tab completion · syntax highlighting · multi-line editing · click places the caret · ⌃ R fuzzy history
Window tabs & splits · ⌘ P palette · ⌘ F scrollback search · nine themes · IME
Agent-aware per-pane detection (18 CLIs): status dot · notifications · branch + diff · resume after reboot · tray icon when input is needed
Remote workspaces remote files, repos, changes, diffs, worktrees, tabs, and panes · reconnect from any client and continue where you left off
CLI + Skills bundled tty7 CLI · agent skill · pane/workspace control · real PTY commands · output, process, port, and agent status
SSH native russh stack: profiles with keychain secrets · SFTP panel · port forwarding · jump hosts · one-time, unprivileged tty7-server install

Full documentation lives in docs/keyboard shortcuts · config.json · CLI reference. The agent-facing CLI interface is also documented in skills/tty7/SKILL.md.

Install the skill with:

npx skills add l0ng-ai/tty7    # install
npx skills update tty7         # update later

Benchmarks

Same machine, same day, same 155×40 grid — Apple M1 Pro, macOS 26.3.1, five-run averages (2026-07-04):

tty7 Alacritty Ghostty Kitty
Plaintext I/O — 11 MB cat (lower = better) 95 ms 239 ms 179 ms 185 ms
DOOM-fire frame rate (higher = better) 888 fps 485 fps 552 fps 617 fps
Cold-launch memory 116 MB¹ 105 MB 128 MB 130 MB

¹ GUI 105 MB + the persistent server 11 MB.

Methodology and one-command reproduction: scripts/bench/.


S
Description
A terminal workbench in pure Rust: shells, persistent sessions, SSH, coding agents. GPU-rendered on Zed's gpui, VT core from Alacritty.
Readme Apache-2.0
34 MiB
Languages
Rust 99.1%
Shell 0.5%
PowerShell 0.2%
Inno Setup 0.1%