Files
tty7/docs/terminal/links.mdx
T
l0ng-ai 89426fb5c4 fix(links): keep the path when a template token holds an absent value
`link_file_command` dropped a whole token whose value was missing. That is
right for `--line={line}`, where the flag means nothing without it, but the
same rule threw the file away in `code --goto {path}:{line}:{column}` —
which is VS Code's own spelling, and one of the three examples the docs
offer, `zed {path}:{line}` being another. Clicking a link that carried no
line number ran `code --goto` with no file and opened nothing, silently.

A token that has already produced the path now keeps it and stops there,
taking the separator that introduced the absent value with it so the
argument ends at the path rather than at a bare `:`. Tokens with no path in
them still go entirely, so the documented flag behaviour is unchanged.

This edge was noted in a test that asserted it as a "sharp edge" rather
than fixing it; that test now asserts the file opens.
2026-08-16 17:05:52 +08:00

80 lines
3.2 KiB
Plaintext

---
title: "Links"
description: "Opening URLs, files, and localhost ports straight out of the terminal."
---
Hold <kbd>⌘</kbd> (<kbd>Ctrl</kbd> on Windows and Linux) and links under the
pointer underline; click to open one.
## URLs
Anything that looks like a URL is detected, including one the shell wrapped
across two lines — tty7 stitches it back together before opening it.
Turn detection off with **Settings → Terminal → Links → Detect URLs**
(`link_url: false`).
## Files
A file path in the output — a compiler error, a test failure, a `grep -n` hit —
opens in tty7's own editor, on the line the link named, and the Files panel
selects it if it is open. A path to a directory opens the Files panel on it
instead.
Both absolute and relative paths are detected. A relative one is measured
against the directory the pane is working in, and then against the repository
around it — which is what makes a path a build tool printed from the workspace
root resolve while the shell sits in a member directory. A path that matches
nothing under either says so rather than doing nothing.
Paths in a pane connected to another machine are resolved *on that machine*,
so the underline appears a moment after the pointer settles rather than
instantly. A pane running `ssh` typed into a local shell has no host that can
answer for its paths, so file links are off there.
**Settings → Terminal → Links → Open files with** picks what a click opens:
| Mode | Opens in |
| --- | --- |
| Built-in editor | tty7's editor, at `:line:column`. The default. |
| Default app | Whatever the OS associates with the file type. |
| Command | A command of your own — see below. |
A file on another machine always opens in the built-in editor, whichever mode
is set: a path that was just resolved on the far side means nothing to a local
`open` or `code`, which would show this machine's copy of that path or nothing
at all.
Under **Command**, the command runs with placeholders substituted:
```
code --goto {path}:{line}:{column}
zed {path}:{line}
herdr edit {path} --line={line}
```
`{path}`, `{line}`, and `{column}` are filled in from the link. A value the
link does not carry is dropped rather than passed empty, along with whatever
introduced it: `--line={line}` disappears entirely, and `{path}:{line}` on a
link with no line number becomes just the path, with no trailing colon.
The settings are `link_file_open` (`internal`, `system`, or `command`) and
`link_file_command` in `config.json`. A config written before `link_file_open`
existed keeps working: one that set a command stays on **Command**, and one
that did not moves to the built-in editor.
## localhost ports
<kbd>⌘</kbd>-clicking `localhost:3000` opens it in your browser, which is only
useful if the server is on this machine.
When the pane is inside an SSH session it usually is not. Turn on **Settings →
Terminal → Links → Forward SSH loopback links** (`ssh_loopback_forward: true`)
and tty7 opens a temporary port forward through that connection first, so the
link reaches the server on the remote machine.
<Tip>
For a forward you want to keep, set one up properly instead —
[port forwarding](/remote/port-forwarding).
</Tip>