mirror of
https://github.com/l0ng-ai/tty7.git
synced 2026-09-22 08:02:24 +00:00
The CLI's own --help calls it "built for coding agents", but `capture` handed back the daemon's raw PTY bytes, which is the least readable thing it emits, and every verb panicked when its reader hung up. `capture --plain` replays those bytes through a terminal grid instead of stripping escapes from them, using the same alacritty_terminal rev the GUI renders panes with. The difference is not cosmetic: only the grid knows that a break at the pane's width was a wrap rather than a newline, that a CR meant "overwrite this line" rather than "end it", and which cell a wide char shares with its spacer. A regex gets the easy 90% and then invents the rest — on one real pane it turned 1193 lines into 2806. The size each segment needs comes for free: the daemon already sends DaemonMsg::Size right before every Snapshot, and the CLI was discarding it. Panes here measure 249 and 86 columns, so the hardcoded 120 would have wrapped both in the wrong places. Observing still resizes nothing. The pipe fix is two mechanisms with one contract. On Unix SIGPIPE goes back to its default disposition, which covers every write site at once and ends the process the way it ends `cat` (141). Windows has no such signal, so stdio::out recognizes the hung-up write and leaves quietly. Before this, 16 of 19 verbs printed a panic and a backtrace note for `tty7 ls | head -1`; `run` instead reported it as a failure with exit 1. Also adds skills/tty7, the Claude skill for driving this CLI. It shipped with a Python ANSI stripper, which is what prompted --plain; the script is gone. alacritty_terminal moves to [workspace.dependencies] so the GUI and the CLI cannot drift onto two revs of the fork.
67 lines
2.4 KiB
TOML
67 lines
2.4 KiB
TOML
# The thin console CLI: the `tty7` on the user's PATH.
|
|
# A control/pane-protocol client of tty7-server — the GUI is never required.
|
|
# Kept apart from the GUI binary on purpose (subsystem, upgrade file locks,
|
|
# millisecond cold start).
|
|
[package]
|
|
name = "tty7-cli"
|
|
version.workspace = true
|
|
edition.workspace = true
|
|
description = "tty7's command line: a thin client for the tty7 server — workspaces, tabs, panes, agents, no GUI required"
|
|
repository = "https://github.com/l0ng-ai/tty7"
|
|
license = "Apache-2.0"
|
|
publish = false
|
|
|
|
[[bin]]
|
|
name = "tty7"
|
|
path = "src/main.rs"
|
|
|
|
[dependencies]
|
|
# Protocol types only (ControlRequest/ReplyOk, the machine tree, PaneProcs).
|
|
# Default features: no gssapi, no remote-install — the CLI is a client of a
|
|
# server that already exists, it never links krb5 or an HTTP fetcher.
|
|
tty7-core = { path = "../tty7-core" }
|
|
|
|
anyhow.workspace = true
|
|
serde_json.workspace = true
|
|
|
|
# The command grammar. Not in [workspace.dependencies] because this is its only
|
|
# user, same as the GUI package's own single-user pins (regex, memchr, …).
|
|
clap = { version = "4", features = ["derive"] }
|
|
|
|
# Column alignment in the tables. Byte length is not display width: a CJK
|
|
# workspace name or cwd is two columns per char, and padding by len() puts
|
|
# every column after it out of line. Already in the tree via alacritty.
|
|
unicode-width = "0.2"
|
|
|
|
# The VT parser behind `capture --plain`. A pane's replay is a byte stream, and
|
|
# recovering the text from it is a terminal's job, not a regex's: only the grid
|
|
# knows that a break at column 120 was a wrap rather than a newline, that a CR
|
|
# meant "overwrite this line", or which cell a wide char and its spacer share.
|
|
# The same crate the GUI renders with, at the same rev, so the two agree about
|
|
# what a pane says.
|
|
alacritty_terminal.workspace = true
|
|
|
|
[target.'cfg(unix)'.dependencies]
|
|
libc = "0.2"
|
|
|
|
[dev-dependencies]
|
|
tempfile = "3"
|
|
|
|
# The e2e harness puts its throwaway daemon in a Job Object wired to
|
|
# KILL_ON_JOB_CLOSE, so a hard-killed test run cannot leak servers.
|
|
[target.'cfg(windows)'.dev-dependencies]
|
|
windows-sys = { version = "0.59", features = [
|
|
"Win32_Foundation",
|
|
"Win32_Security",
|
|
"Win32_System_JobObjects",
|
|
] }
|
|
|
|
# The end-to-end suite drives the compiled tty7.exe against a real isolated
|
|
# server; its own main doubles as that server process, so no libtest harness.
|
|
[[test]]
|
|
name = "cli_e2e"
|
|
harness = false
|
|
|
|
[lints]
|
|
workspace = true
|