mirror of
https://github.com/l0ng-ai/tty7.git
synced 2026-09-22 08:02:24 +00:00
The oh-my-zsh guard is not at the top of `lib/termsupport.zsh` — it fences off the cwd reporter at the end of the file, and the title hooks above it keep running over SSH. Say that instead. The list under "the shell is one tty7 does not integrate" is the set it *does* integrate, which read as its own opposite; turn the sentence around. Nushell has had the integration since #637 (`ShellKind::Nushell`, a `nu --config` wrapper), so give it a row in the shells table and stop listing it among the shells that have none. The per-profile toggle lives behind **Advanced**, as `docs/remote/ssh.mdx` and the section below already say, and the panel is the **Files** panel everywhere else in these docs. Claude-Session: https://claude.ai/code/session_01JRqYZ9E153WpSHGS2AW3BM
117 lines
6.1 KiB
Plaintext
117 lines
6.1 KiB
Plaintext
---
|
|
title: "Shell integration"
|
|
description: "What tty7 injects into your shell, and what it buys you."
|
|
---
|
|
|
|
A terminal that only sees bytes cannot tell a prompt from output, or a finished
|
|
command from a hung one. tty7's shell integration closes that gap: the shell
|
|
reports where prompts begin, what was submitted, what it exited with, and where
|
|
it is.
|
|
|
|
**You do not install it.** It is injected when the pane's shell starts, and
|
|
removes itself from the equation if you run the same shell elsewhere.
|
|
|
|
## Which shells
|
|
|
|
| Shell | How it is injected |
|
|
|---|---|
|
|
| **zsh** | A throwaway `ZDOTDIR` whose files source yours first, then tty7's. Your `TTY7_USER_ZDOTDIR` is preserved. |
|
|
| **bash** | An rcfile that sources your own first. |
|
|
| **fish** | A `-C` init command. |
|
|
| **PowerShell** | An encoded init command that wraps your existing `prompt` function and PSReadLine's line reader. |
|
|
| **nushell** | A `--config` wrapper whose `config.nu` sources yours first, then adds tty7's hooks. Local panes only. |
|
|
| **WSL** *(Windows)* | The distro's shell is bootstrapped with the same scripts. |
|
|
| **Remote panes** | The same three POSIX shells, bootstrapped over the SSH connection. Toggle per profile with **Settings → SSH →** a profile **→ Advanced → Session → Shell integration**. |
|
|
|
|
`TTY7_SHELL_INTEGRATION` is set once it is active, and guards against a second
|
|
injection when shells nest. It does not put the integration *into* a nested
|
|
shell — [shells you start yourself](#shells-you-start-yourself) have none.
|
|
|
|
<Note>
|
|
A shell launched with arguments *you* wrote — `shell.args`, or a
|
|
`custom_shells` entry — is left alone, because tty7's injection would
|
|
conflict with the flags you chose. Arguments tty7's own detection supplied
|
|
(Git Bash's `-i -l`, a WSL row's `--distribution`) do not count, so those
|
|
rows are still integrated.
|
|
</Note>
|
|
|
|
## What it reports
|
|
|
|
| Signal | Sequence | Used for |
|
|
|---|---|---|
|
|
| Prompt begins / input begins | `OSC 133;A`, `133;B` | The [prompt layer](/terminal/prompt): suggestions, completion, multi-line editing |
|
|
| Command submitted | `OSC 133;C` | Knowing a command is running; agent detection on Windows, where ConPTY exposes no foreground process group |
|
|
| Command finished, with exit code | `OSC 133;D` | The "finished after 42s" notification, failure marks in [history](/terminal/history) |
|
|
| Working directory | `OSC 7` | New tabs and splits opening in the right place, the sidebar's repo grouping, the git branch readout |
|
|
| Editing mode (vi / emacs) | `OSC 133;V` | Matching tty7's key handling to your shell's mode |
|
|
| Window title | `OSC 0` | Tab labels. Only PowerShell is given this — zsh, bash, and fish already set a title of their own, and tty7 reads whatever they emit |
|
|
|
|
## What turns off without it
|
|
|
|
Run a shell tty7 does not integrate with, and everything below still works —
|
|
it just falls back to less precise sources:
|
|
|
|
- Ghost suggestions, the completion menu, and <kbd>⌃ R</kbd>'s fuzzy history
|
|
- "Command finished" notifications and the failure marks in history search
|
|
- Exact working-directory tracking
|
|
|
|
Panes, splits, scrollback, search, SSH, and the CLI are unaffected.
|
|
|
|
The working-directory fallback is worth knowing in detail, because it is not
|
|
available everywhere. Where tty7 can see the pane's processes it reads the
|
|
foreground one's own working directory instead — a local pane on macOS or
|
|
Linux, or a pane in a remote workspace, where the `tty7-server` on that host
|
|
does the reading. It is a poll, not a report: it is sampled while the pane is
|
|
producing output, at most twice a second, so it can trail a `cd` until the
|
|
pane writes something again. A local pane on **Windows** and a pane connected
|
|
to an **SSH host** have no fallback at all — on the far end of an `ssh` there
|
|
is no process table to read, so a shell that does not report its directory
|
|
leaves the pane showing the last directory that did.
|
|
|
|
## Shells you start yourself
|
|
|
|
The injection happens when the pane's shell is *launched*. Type `zsh` at a
|
|
bash prompt — or `bash`, or `sh`, or `docker exec … sh` — and that second
|
|
shell is a new process, launched by your shell rather than by tty7. It emits no
|
|
prompt marks and no `OSC 7`, and the pane keeps showing the directory the
|
|
outer shell last reported until you exit back to it.
|
|
|
|
On your own machine this is usually invisible, because prompt frameworks
|
|
report the directory themselves: oh-my-zsh does it from
|
|
`omz_termsupport_cwd` in `lib/termsupport.zsh`. **Over SSH it is not.** That
|
|
file returns early when `SSH_CLIENT` or `SSH_TTY` is set, so on a remote host
|
|
a zsh you started by hand reports nothing at all, and neither does tty7.
|
|
|
|
To get integration into that shell, make it the shell tty7 starts:
|
|
|
|
- **A remote host.** tty7 asks the host for `$SHELL` when it connects and
|
|
bootstraps that shell, so `chsh -s /bin/zsh` (then reconnect) is what
|
|
switches it. A login script under **Advanced → Session** that runs `zsh`
|
|
does *not* — those lines are typed into the session after the shell is
|
|
already up, so they nest like anything else. Neither does `exec zsh` from
|
|
your `.bashrc`: it replaces the process tty7 set up.
|
|
- **A local pane.** Set `shell` in [config](/reference/configuration), and
|
|
leave `args` out — arguments you write turn the injection off.
|
|
|
|
[If the Files panel stopped following a nested shell →](/reference/troubleshooting#the-directory-stopped-following-my-shell)
|
|
|
|
## Per-pane history
|
|
|
|
When `per_pane_history` is on, the integration is also what makes it work. It
|
|
runs *after* your own rc file — which is the only reason it can: `$HISTFILE` is
|
|
yours to set, wherever you like, and nothing outside the shell knew where it
|
|
pointed until then.
|
|
|
|
The sequence is: seed the pane's private file from your real history so it does
|
|
not start blank, record how much was seeded, repoint `$HISTFILE`, and merge
|
|
everything past that mark back when the pane closes.
|
|
|
|
[More about history →](/terminal/history#one-history-or-one-per-pane)
|
|
|
|
## Remote shells
|
|
|
|
For a remote workspace or an SSH pane, the same scripts are sent over the
|
|
connection at login, so a remote pane reports its cwd, exit codes, and prompt
|
|
marks exactly like a local one. Turn it off for a particular host under that
|
|
profile's **Advanced → Session**.
|