/tty7
Drive the tty7 terminal workbench from the shell with the `tty7` binary — list workspaces/tabs/panes, split a pane, send text or keystrokes into one, capture what is on a pane's screen, run a command in a real PTY and pass its exit code through, block until a pane finishes or
$ npx -y skills add l0ng-ai/tty7 --skill tty7 --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.Auto-invocation is when the right skill fires by itself at the right moment, driven by a FLOW.md router and a hook, instead of you invoking it by name. It is the difference between a skill being installed and a skill actually getting used.Read the full definition →
- You can call itInvoke it directly when you want it.
- Slash command
/tty7
Context preview
The summary Claude sees to decide when to auto-load this skill.
Drive the tty7 terminal workbench from the shell with the `tty7` binary — list workspaces/tabs/panes, split a pane, send text or keystrokes into one, capture what is on a pane's screen, run a command in a real PTY and pass its exit code through, block until a pane finishes or
SKILL.md
tty7.SKILL.mdname: tty7
description: >-
Drive the tty7 terminal workbench from the shell with the `tty7` binary — list workspaces/tabs/panes, split a pane, send text or keystrokes into one, capture what is on a pane's screen, run a command in a real PTY and pass its exit code through, block until a pane finishes or needs input, see which coding agents are running and which ports a pane is listening on. Use this whenever tty7, panes, workspaces, or `%42`/`@7`/"the other pane"/"the other agent" come up; whenever you want to hand work to another agent and collect the result ("get Claude/Codex to do X", "派个活", "let another agent handle this", running several agents in parallel and merging what they produce); whenever you need to start something long-running or interactive (dev server, REPL, ssh session, `tail -f`, a TUI) that should not sit blocking your Bash tool; whenever a program needs a real terminal to behave the way the user sees it; and whenever you need to look at or report on what is running in some *other* terminal on this machine. Cheap to check: if `$TTY7_PANE` is set you are already inside tty7 and every command here works with no setup.Driving tty7 from the command line
`tty7` is a thin, non-interactive client of the tty7 server. Every verb returns and exits; `--json` makes the output machine-readable. The GUI never has to be running — the server is what owns the panes.
First: where are you?
tty7 doctor
One table, and it answers everything you need before doing anything else: whether a server is reachable, whether the dialect matches, whether each agent's status hooks are installed, and whether `TTY7_CONFIG_DIR` / `TTY7_WS` / `TTY7_PANE` are set — i.e. whether you are running *inside* a tty7 pane.
Being inside a pane matters for two reasons: the address-taking verbs (`split`, `send`, `capture`, `procs`, `wait`, `pane close`) default to `$TTY7_PANE`, and `run --keep` files its pane into `$TTY7_WS`. Outside a tty7 shell you must name a target explicitly, and the error will say so rather than guessing.
The hooks row matters if you intend to delegate to another agent: without them an agent reports no status, so `tty7 wait` on it will only ever time out.
If `tty7 doctor` says the server is unreachable, stop and tell the user — do not run `tty7 server start` on your own initiative. Starting a server they didn't ask for changes what their GUI attaches to.
What are you here to do?
Four jobs, four shapes:
1. **Run something that shouldn't block you or needs a real TTY** — a dev server, a long test run, a TUI. [Running a command](#running-a-command-two-shapes). 2. **Talk to something stateful over time** — a REPL, `ssh`, a debugger. Same primitives: [send](#non-blocking-a-pane-you-talk-to-over-time), [read](#reading-a-pane), repeat. 3. **Look at what this machine is doing** — other panes, other agents, ports. [Looking around](#looking-around), strictly read-only. 4. **Hand work to another coding agent** — one worker or a fan-out of several. Read `references/delegation.md` first; the short version is [below](#handing-work-to-another-agent).
The Bash tool remains right for anything that starts, does its job, and exits without needing a terminal or an audience. A pane earns its keep when the process outlives your turn, needs a real PTY, or should be visible to the user in their tty7 window — that last one is often the whole point.
Addresses
| Shape | Means | Stable? | |---|---|---| | `%42` | a pane | yes — a pane keeps its id for its whole life | | `@7` | a tab, numbered across the **whole machine** in tree order | **no** — it shifts whenever a workspace or tab appears or disappears | | `@<full tab UUID>` | that same tab, by id | yes | | `api` / `76698a44` / a full UUID | a workspace, by name, by unique id prefix, or by id | yes |
Re-resolve `@N` right before you use it; never cache one across a step that creates or removes a tab. Pane ids, tab ids and workspace ids are safe to remember — so when you create a tab and mean to address it again later, keep the id `tty7 tab new --json` hands back rather than counting `@N` a second time.
The sigils are optional wherever an address is expected: `%42` and `42` are the same pane, `@7` and `7` the same tab. Ids copied out of `--json` paste straight back in.
Omitting the address inside a tty7 shell means "this pane" / "this workspace". An explicit address always wins over the environment.
Running a command: two shapes
Blocking, with a real exit code
tty7 run -- cargo test # streams to your stdout, exits with cargo's code
tty7 run --cwd /path -- make
tty7 run --keep -- cargo build # leaves the pane as a new tab afterwards
The command's output streams to your stdout as it happens, and `tty7` exits with the command's own exit code. This is the closest thing to a Bash call — the difference is the PTY and the fact that the user can see it.
Three things to know. `--keep` needs a workspace, so it only works inside a tty7 shell or with `--ws <workspace>`. With `--json`, the streamed output comes first and the JSON object last — the combined stream is *not* parseable as JSON, so read the last line. And the pane is 120 columns wide with no way to change it, so output that assumes a wider terminal wraps.
Non-blocking: a pane you talk to over time
This is the one that makes tty7 worth reaching for. Get a pane, send it work, come back later.
PANE=$(tty7 split --v) # or --h; splits $TTY7_PANE, prints "%83"
tty7 send "$PANE" 'npm run dev' --enter
`split` prints the new pane's address on stdout, which is what you capture into a variable. Without an axis it is a usage error — `--v` stacks the new pane below, `--h` puts it to the right.
Splitting `$TTY7_PANE` changes the user's visible layout, which is usually the point: they can watch the dev server you started. Say that you did it, and close the pane when you're done with it.
If you are *
Read more
name: tty7
description: >-
Drive the tty7 terminal workbench from the shell with the `tty7` binary — list workspaces/tabs/panes, split a pane, send text or keystrokes into one, capture what is on a pane's screen, run a command in a real PTY and pass its exit code through, block until a pane finishes or needs input, see which coding agents are running and which ports a pane is listening on. Use this whenever tty7, panes, workspaces, or `%42`/`@7`/"the other pane"/"the other agent" come up; whenever you want to hand work to another agent and collect the result ("get Claude/Codex to do X", "派个活", "let another agent handle this", running several agents in parallel and merging what they produce); whenever you need to start something long-running or interactive (dev server, REPL, ssh session, `tail -f`, a TUI) that should not sit blocking your Bash tool; whenever a program needs a real terminal to behave the way the user sees it; and whenever you need to look at or report on what is running in some *other* terminal on this machine. Cheap to check: if `$TTY7_PANE` is set you are already inside tty7 and every command here works with no setup.Driving tty7 from the command line
`tty7` is a thin, non-interactive client of the tty7 server. Every verb returns and exits; `--json` makes the output machine-readable. The GUI never has to be running — the server is what owns the panes.
First: where are you?
tty7 doctor
One table, and it answers everything you need before doing anything else: whether a server is reachable, whether the dialect matches, whether each agent's status hooks are installed, and whether `TTY7_CONFIG_DIR` / `TTY7_WS` / `TTY7_PANE` are set — i.e. whether you are running *inside* a tty7 pane.
Being inside a pane matters for two reasons: the address-taking verbs (`split`, `send`, `capture`, `procs`, `wait`, `pane close`) default to `$TTY7_PANE`, and `run --keep` files its pane into `$TTY7_WS`. Outside a tty7 shell you must name a target explicitly, and the error will say so rather than guessing.
The hooks row matters if you intend to delegate to another agent: without them an agent reports no status, so `tty7 wait` on it will only ever time out.
If `tty7 doctor` says the server is unreachable, stop and tell the user — do not run `tty7 server start` on your own initiative. Starting a server they didn't ask for changes what their GUI attaches to.
What are you here to do?
Four jobs, four shapes:
1. **Run something that shouldn't block you or needs a real TTY** — a dev server, a long test run, a TUI. [Running a command](#running-a-command-two-shapes). 2. **Talk to something stateful over time** — a REPL, `ssh`, a debugger. Same primitives: [send](#non-blocking-a-pane-you-talk-to-over-time), [read](#reading-a-pane), repeat. 3. **Look at what this machine is doing** — other panes, other agents, ports. [Looking around](#looking-around), strictly read-only. 4. **Hand work to another coding agent** — one worker or a fan-out of several. Read `references/delegation.md` first; the short version is [below](#handing-work-to-another-agent).
The Bash tool remains right for anything that starts, does its job, and exits without needing a terminal or an audience. A pane earns its keep when the process outlives your turn, needs a real PTY, or should be visible to the user in their tty7 window — that last one is often the whole point.
Addresses
| Shape | Means | Stable? | |---|---|---| | `%42` | a pane | yes — a pane keeps its id for its whole life | | `@7` | a tab, numbered across the **whole machine** in tree order | **no** — it shifts whenever a workspace or tab appears or disappears | | `@<full tab UUID>` | that same tab, by id | yes | | `api` / `76698a44` / a full UUID | a workspace, by name, by unique id prefix, or by id | yes |
Re-resolve `@N` right before you use it; never cache one across a step that creates or removes a tab. Pane ids, tab ids and workspace ids are safe to remember — so when you create a tab and mean to address it again later, keep the id `tty7 tab new --json` hands back rather than counting `@N` a second time.
The sigils are optional wherever an address is expected: `%42` and `42` are the same pane, `@7` and `7` the same tab. Ids copied out of `--json` paste straight back in.
Omitting the address inside a tty7 shell means "this pane" / "this workspace". An explicit address always wins over the environment.
Running a command: two shapes
Blocking, with a real exit code
tty7 run -- cargo test # streams to your stdout, exits with cargo's code tty7 run --cwd /path -- make tty7 run --keep -- cargo build # leaves the pane as a new tab afterwards
The command's output streams to your stdout as it happens, and `tty7` exits with the command's own exit code. This is the closest thing to a Bash call — the difference is the PTY and the fact that the user can see it.
Three things to know. `--keep` needs a workspace, so it only works inside a tty7 shell or with `--ws <workspace>`. With `--json`, the streamed output comes first and the JSON object last — the combined stream is *not* parseable as JSON, so read the last line. And the pane is 120 columns wide with no way to change it, so output that assumes a wider terminal wraps.
Non-blocking: a pane you talk to over time
This is the one that makes tty7 worth reaching for. Get a pane, send it work, come back later.
PANE=$(tty7 split --v) # or --h; splits $TTY7_PANE, prints "%83" tty7 send "$PANE" 'npm run dev' --enter
`split` prints the new pane's address on stdout, which is what you capture into a variable. Without an axis it is a usage error — `--v` stacks the new pane below, `--h` puts it to the right.
Splitting `$TTY7_PANE` changes the user's visible layout, which is usually the point: they can watch the dev server you started. Say that you did it, and close the pane when you're done with it.
If you are *
A terminal workbench in pure Rust: shells, persistent sessions, SSH, coding agents. GPU-rendered on Zed's gpui, VT core from Alacritty.
Repo: l0ng-ai/tty7

