mirror of
https://github.com/l0ng-ai/tty7.git
synced 2026-09-22 00:02:23 +00:00
ccc98b90a9ee96bb705a1ff967c15af29c5dcee9
* fix(input): stop the Windows/Linux keymap and CRLF pastes from breaking the shell Two problems a Windows user hit within an hour of installing tty7, both from code that only ever had macOS in mind. A bracketed paste forwarded the clipboard byte for byte. Text copied on Windows carries \r\n, and vim counts CR and LF as two line breaks, so pasting code into it left a blank line under every line. Fold \r\n to \n inside the paste markers so a Windows clipboard produces exactly what the same paste already produced on Linux and macOS. The non-bracketed path keeps converting to CR: with no paste mode to tell text from typing, a line break has to arrive as the byte Return sends. `secondary` means Cmd on macOS and Ctrl everywhere else, and the default keymap was carried over from macOS unchanged, which put window actions on top of terminal control codes. Ctrl+D could not send EOF, Ctrl+[ could not send ESC, and Ctrl+W, Ctrl+K, Ctrl+P, Ctrl+J, Ctrl+T, Ctrl+Q and Ctrl+S were all taken. These bindings carry no context, so they match before the terminal sees the key -- apply_readline_ctrl already sends EOF for ^D, it was just unreachable. Off macOS, ctrl-<letter> and ctrl-[ ] \ space now belong to the terminal and window actions move to ctrl-shift-*, the convention GNOME Terminal, Konsole, Windows Terminal and WezTerm share. Tabs move to Alt+1-9 and pane focus to Alt+arrow, since Ctrl+Alt+arrow is workspace switching under GNOME. Ctrl+S keeps saving in the code panel but propagates when the editor is unfocused, so a shell still gets XOFF. Shift+Insert pastes. macOS is untouched, and a user's own rebindings still win over the defaults. A test walks the default table and rejects any chord that lands on a control code, so the next binding added cannot quietly bring this back; a second one rejects two actions claiming the same chord, which is how the reshuffle caught NewTab colliding with ReopenClosedTab. Refs #269 * fix(history): keep one history store per machine, not one per install tty7 owns ^R at the prompt and shows its own fuzzy menu, but `history.rs` had no notion of where a command had run: `load()` read one file and `append()` wrote one file, so an ssh session was offered the commands typed on the local machine. That is worse than an empty menu -- the entries look plausible until one of them runs against the wrong box. History is now scoped. The local store keeps its existing path, so nobody loses what they have; each remote gets its own file under `history.d/`, named after the target with a hash appended so a label that is not a filename ("me@box:/srv") cannot escape the directory or collide with another host. A pane picks its scope from the innermost remote it can see -- the ssh target reported by shell integration, else its host id -- and follows it when that changes, clearing the menu and reloading in the background rather than showing the previous machine's entries while it waits. A reload that lands after the pane has moved on again is dropped. On a remote workspace, where a Host impl exists, the far end's own ~/.zsh_history and ~/.bash_history are read through the same channel git status and file listings already use, so the first ^R on a freshly connected box has something in it. Bare ssh has no Host to read through and falls back to what tty7 recorded itself for that target, which is still the right machine's commands. Refs #269 * fix(test): the control-code guard must admit Ctrl+S, which falls through The guard forbade every bare ctrl-letter default, but EditorSave staying on Ctrl+S is the design: its handler propagates whenever the editor does not have focus, so the terminal still receives XOFF. The guard's real invariant is "no default may swallow a control code" -- an action that falls through does not swallow. EditorSave is exempted by name, with the condition for earning a spot written next to the list. The test is vacuous on macOS (secondary parses to Cmd), which is why the contradiction only surfaced on the Linux runner. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(history): never seed an inner ssh target from the workspace host's files remote_shell_history_sources gated only on "scope is remote and host is remote", so a pane that ssh'ed onward from a remote workspace -- scoped to the inner target -- was seeded from the workspace host's ~/.zsh_history: another machine's commands in the menu, the exact confusion scoping exists to prevent. The Host can only reach the workspace machine's home, so seeding is now reserved for the host's own scope; a pane with a remote_context falls back to what tty7 recorded for that target, exactly like bare ssh from a local pane. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> --------- Co-authored-by: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com> Co-authored-by: thomas <thomas@gmail.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
tty7
A terminal workbench: shells, sessions, SSH, coding agents.
Pure Rust · GPU rendering on Zed's gpui · VT core from Alacritty
English · 简体中文
Why
- Fast — ~2× the throughput of Alacritty, Ghostty, or Kitty (benchmarks)
- Sessions persist — quit or reboot; your shells keep running, no tmux
- Editor-grade input — completion, syntax highlighting, history search built in; zero config for zsh, bash, fish, PowerShell
- Agent-aware — recognizes Claude Code & co. in a pane: status, notifications, session resume
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 libs bundled |
What's inside
| 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 |
| Coding agents | per-pane agent detection (~17 CLIs): status dot, notifications, branch + diff, resume after reboot, tray icon that signals "needs your input" |
| SSH | native russh stack: profiles with keychain secrets, SFTP panel, port forwarding, jump hosts |
Details for every row: docs/features.md. Keybindings: ⌘ , opens Settings — browse and remap everything, tmux preset included (full list).
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 IO — 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 daemon 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%