`--enter` is documented as sugar for `--key enter`, but the send dispatch
counted only `args.keys`, so `tty7 send %42 --enter` answered "needs TEXT
... or a --key to press" and pressed nothing. The key list is now built
before the dispatch and the dispatch counts it, so a marked address with
`--enter` and nothing else runs what the pane already has typed, and a
bare `send --enter` presses Enter where the caller sits.
An unmarked id is deliberately left out of that promotion. #567 made the
address slot take bare ids, and `send 83 --key C-c` addressing pane 83 is
fine because `--key` says "press this" and nothing else. `--enter` does
not: `send 2 --enter` reads at least as much like typing 2 into your own
pane and running it, and turning it into a keystroke at pane 2 would be
the silent retarget #567 spent its diff closing. It stays a loud error,
now naming both spellings (`send %83 --enter`, `send %PANE 83 --enter`)
rather than only the typing one.
The reference, the bundled skill reference, `send --help` and the
`--enter` help all said the old thing in slightly different words; they
now say the same thing as each other and as the code.
Co-authored-by: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com>
* fix(cli): refuse a broken send address instead of typing it into your pane (#538)
A lone positional that starts with `%` but fails parse_pane (`%3x`) used
to fall through to the text branch: the typo was typed into the caller's
own pane and any --key followed it there, so one wrong character
redirected an interrupt to whatever the caller was looking at. The guard
now propagates the parse error when the `%` is followed by a digit —
"clearly tried to write an address" — and leaves `%`-led text whose
second character is not a digit (`%s/foo/bar/`, `%!sort`) on the text
path it always was, per the review's narrowing.
The explicit address slot also accepts bare ids now: `pane ls --json`
prints `83`, not `%83`, and refusing the bare form made the workaround
for the typo hole (`"%${TTY7_PANE#%}"`) uglier than the hole. This
matches what pane_from_env already accepted and closes the missing-`%`
variant of the same mistake.
Tests cover the branch with a `Context { pane: Some("5") }` — every
existing send test used `Context::default()`, where the fallback errors
OUTSIDE_SHELL before the guard is reachable, which is why the hole had
no test.
Also correct the `ws rm` docs (#539): the reference claimed its panes
become orphans found via `pane ls --all`, but the code has hung them up
since #319; only a hang-up failure (reported by pane id) leaves
orphans. The site reference, the skill reference, and `ws rm --help`
now say so.
* fix(cli): keep the send guard to what actually looks like an address
The narrowing was described more widely than it works: a digit-led token
that fails to parse (`3x`) still types, only `%` then a digit refuses, so
the reference and the skill both promised an error that never comes. Say
what the code does and point at the two-argument form as the way to type
an address-shaped string anyway.
Now that the `%` is optional, `parse_pane` also has to be stricter than
`u64::from_str`, which accepts a leading `+`: a bare `+5` meant as text
would otherwise address pane 5. An address is digits and nothing else,
and `pane_from_env` delegates rather than repeating the read.
The broken-address arm parsed twice and ended in an `unreachable!` that
a future edit could walk into; one match on the parse result carries the
error out directly. A lone bare id is the one behaviour this takes away,
so it says how to type the number instead, and a test pins that it never
quietly presses a key at the pane the id names.
---------
Co-authored-by: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com>
`skills add` does not refresh a skill that is already installed, so the
one install line left existing users with no documented way forward.
Add the `skills update tty7` counterpart to both READMEs and give the
agent-skill page a short Updating section covering update and remove.
* feat(cli): wait on commands, press keys, and reap orphan panes
`tty7 wait` was the orchestration primitive for agents only. A pane with
nothing reporting agent status read as `idle`, so `--until idle` returned
success instantly about a shell that was midway through a build, and there
was no state that meant "the command finished" at all.
Panes with no agent now report `no-agent`, and `free` ends the wait when the
foreground command has exited — the process-tree question `procs` could
already answer but nothing could block on. `send --key` covers the keystrokes
text cannot express, which is what a worker stopped at `waiting` is usually
asking for. `pane close` takes several panes and `--orphans` clears what an
interrupted `run` leaves behind. `doctor` finally performs the hooks check
its own help has advertised.
The skill shipped in this repo predated `wait` entirely and taught a
hand-rolled `procs` polling loop with no notion of delegation; it now covers
the loop, and its agent statuses, `ws rm` orphan claim and not-implemented
list are corrected against the code.
* fix(cli): close the gaps review found in wait, --key and pane close
Five things the first pass got wrong, in the order they bite.
`--until free --changed` waited on a command it had already missed: the
"something ran" edge is only set by a poll that catches the pane busy, and a
command that starts and finishes inside one 500ms interval never is. That is
indistinguishable from a command that never ran, so the timeout now names both
doors instead of letting a finished build read as a hang.
`free` also outranked the agent ladder, which is backwards. A pane whose depth-0
process *is* the agent — the tree cannot tell that apart from a shell at its
prompt — reads free for its whole turn, so a `waiting` the caller explicitly
asked for could be overwritten by a process-tree fact and then withheld by the
`--changed` rule that comes with it. `free` is now consulted only when none of
the requested agent states answered, which is both cheaper and what the docs
already claimed. An empty process tree is "we could not see in" rather than
"free" for the same reason `no-agent` exists.
`--key M-X` sent `ESC x`: the whole spelling was folded to lowercase, which is
free for Ctrl (the C0 rule clears the case anyway) and wrong for Alt, where the
character rides through as itself.
`send --help` listed the key vocabulary by hand next to the table it is a list
of; it had already drifted by one alias. It is generated now.
And a `pane close` batch that could not close everything raised an error, which
left `--json` holding prose exactly when a cleanup script needs to know which
panes are still its problem. It exits 1 with `{"closed":[…],"failed":[…]}`, with
the complaint still on stderr so `-q` reports it.
---------
Co-authored-by: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com>
Audited every page under docs/ against the source. Fixes for what the
code actually does:
- agents: the status vocabulary is idle/working/waiting/done, not
running/waiting/idle; hook rows grow a separate Uninstall button; the
Settings table labels read "Copilot CLI" and "Grok Build"; Copy Session
ID lives in the tab's context menu, not the pane's
- cli: `pane ls --all` reports the owning workspace id, not "tty7-cli";
document bare `tty7 [PATH]` as the GUI launcher it is instead of listing
it as unimplemented; note `active_tab` and the `diagnostics` array; wait
also defaults to $TTY7_PANE
- git: the branch dropdown is a plain list with no search box and no
stash-and-switch, and checkout is not a palette command; quote the diff
overlay's own overflow notice rather than the sidebar's
- window: the unread marker tracks a finished agent turn, not any output;
rows cannot be dragged across groups; the sidebar and `tty7 tab ls`
resolve labels differently; drop Toggle Commit History and Checkout to
from the palette's Git group; ~/.ssh/config aliases are not palette
entries
- terminal: Ctrl+R dedups by command text and shows no directory; Esc does
not dismiss a ghost suggestion; document Cmd+Enter
- remote: GSSAPI is an ordinary Auth choice, not a managed-connection-only
mechanism
- fonts: Maple Mono NF CN leads the chain on Windows and Linux only; list
the real per-platform defaults
- settings paths: the three Links settings and per-pane history were filed
under the wrong sections
The in-app switch that wrote `~/.claude/skills/tty7-orchestration` was
removed in da6df70, before any release carried it — `git grep` finds it in
no tag. The changelog entry recording it landed the same day, written from
the branch's state rather than the tree's, and the documentation site (#478)
was then written from the changelog, so the feature reappeared on three
pages describing something the app has never shipped.
The orchestration page now says what is true: nothing is installed for you,
the agent-facing contract is `skills/tty7` and you add it yourself with
`npx skills add l0ng-ai/tty7`. That skill covers driving panes; `wait` is
documented on the orchestration page itself, so neither page promises what
the other holds.
38 pages under docs/, written against the source rather than the README:
config keys and their clamps from core::config, default keybindings from
ui::keymap, every CLI verb and flag from tty7-cli, agent aliases and
hook/fork/resume support from core::cli_agent, and Settings paths taken
from the actual en-US strings.
docs/features.md and its zh-CN translation are retired — everything in
them now lives in a page of its own, plus the two things they carried
that nothing else did (IME input, the performance notes). README and
README.zh-CN point at docs/ instead.
Screenshots and videos are placeholders for now: docs/images/placeholder.svg
with a caption naming what each shot should be.
Co-authored-by: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com>