mirror of
https://github.com/l0ng-ai/tty7.git
synced 2026-09-22 00:02:23 +00:00
3dc63e2d873a2485b510d5acc6560ef1be184eb4
A daemon can survive quit-and-stop with its endpoint unlinked and its pidfile gone while still holding the singleton seat (#667). Every later launch then spawns a daemon that stands down against the lock and times out red, and nothing on the machine can recover: stop answers "not running", ensure_running reaps only through the pidfile, and flock cannot say who the holder is. Two roads led there, and both are closed: - The reap identified a daemon by proc_pidpath alone, which fails outright for a live process whose binary was deleted — every nightly update replacing the installation. The identity check now falls back to the kernel's comm name (proc_name on macOS, /proc/pid/comm on Linux, both recorded at exec and immune to deletion), strips Linux's " (deleted)" marker, and — decisively — no longer deletes the pidfile of a live process it cannot identify: the record was the only handle left on the survivor. - When the pidfile is gone entirely, the pid the claimant now writes into daemon.lock at claim time is the handle of last resort. The lock file is never deleted and holding the flock is the definition of being the server, so while the seat is held its content names the holder; stop() and the reap fall back to it, and a confirmed reap clears the record (only under a momentarily-free seat) so a stale number cannot outlive its process. Unix-only: the Windows seat is share_mode(0), unreadable while held. Every road back now clears a stranded seat, not just the GUI's: ensure_running's stale cleanup is factored into spawn::reap_stranded, tty7 server start runs it too, and tty7 server stop no longer takes "nobody answered" for "nothing to stop" when the seat is still held. A short grace keeps the reap away from a daemon that is merely mid-handoff or mid-startup — where health is an answered handshake, never a bare connect: a wedged daemon's listener still completes connections out of the kernel's backlog. The startup-timeout errors name the seat-holding pid, with the kill advice identity-gated so a stale record never tells anyone to kill an innocent process. Two liveness corrections round it out: a zombie now reads as dead — it answers kill(pid, 0) like the living but holds no lock and no image, and no signal can end it, so counting it alive spent both reap timeouts on a corpse (the GUI never waits on the daemons it spawns, so crashed daemons are zombies as a rule) — and stop() only pays the process-exit wait for a shutdown it actually delivered, instead of watching an unreached survivor not move for five seconds. The guard tests were each verified to fail against the behavior they pin (fallbacks, the handshake criterion, the grace, and the wait gate removed by mutation) before being trusted green; the zombie probe semantics (proc_pidinfo failing for a zombie that still answers signal 0) were measured, not assumed.
feat(ssh): name panes after their host, reach the host form from where you are, and test a connection (#566)
tty7
A terminal workbench: persistent sessions, remote work, agents.
Pure Rust · GPU rendering on Zed's gpui · VT core from Alacritty
English · 简体中文
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 macOS, Windows, and Linux 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/.
Built on gpui and alacritty_terminal · Apache-2.0 · Discord · Changelog
Description
A terminal workbench in pure Rust: shells, persistent sessions, SSH, coding agents. GPU-rendered on Zed's gpui, VT core from Alacritty.
ai-agentsalacrittyclaude-codecoding-agentcross-platformdaemondeveloper-toolsgpugpuilinuxmacosptyrustshellsshterminalterminal-emulatorterminal-multiplexertmuxwindows
Readme
Apache-2.0
34 MiB
Languages
Rust
99.1%
Shell
0.5%
PowerShell
0.2%
Inno Setup
0.1%