Open the files and links your agent just mentioned.
termscope turns terminal output into a jump list. It reads the active pane's
visible terminal viewport, finds real files and URLs, then opens the selected
target beside the conversation you were already reading.
visible terminal viewport
│
▼
Ctrl-Shift-A → pick a visible file → nvim opens src/main.py:42
Ctrl-E → pick a visible link → browser opens it
termscope-herdr-demo.mp4
Agents constantly mention files: stack traces, changed tests, docs, configs,
links, PRs. termscope lets you keep up without doing the little dance:
select text, copy, cd, paste, fix the path, add the line number.
If it's visible in the pane and exists in the repo, you can jump to it.
Termscope stays conservative:
- scans only the active pane's visible text
- verifies paths against the repo/worktree on disk
- preserves
file:linetargets - falls back to a full repo picker when no visible file matches
- uses a session-modal Herdr popup, leaving the tiled pane layout untouched
- Herdr
>= 0.7.4or tmux - Python
>= 3.10 fd- Homebrew when a Herdr plugin install needs to add or upgrade Television
- Television
>= 0.15(provisioned automatically when needed) batis optional for syntax-highlighted previewsnvimfor the default file-open actionopenon macOS orxdg-openon Linux for default-app opens
Native Windows is not claimed yet. WSL may work through wslview when your WSL
environment provides it.
herdr plugin install iurysza/termscopeThe install includes a visible build step that installs or upgrades Television
through Homebrew when tv is missing or older than 0.15. It never installs
Homebrew itself; a missing Homebrew installation aborts cleanly before the
plugin is registered.
For local development (plugin link does not run install-time build steps):
git clone https://github.com/iurysza/termscope.git
cd termscope
./scripts/install-dependencies.sh
herdr plugin link "$PWD"Verify Herdr sees the actions:
herdr plugin action list --plugin termscopeHerdr plugins register actions; keybindings still live in your
~/.config/herdr/config.toml.
[[keys.command]]
key = "ctrl+shift+a"
type = "plugin_action"
command = "termscope.open"
description = "visible-screen file picker"
[[keys.command]]
key = "ctrl+e"
type = "plugin_action"
command = "termscope.open-links"
description = "visible-screen link picker"Reload config:
herdr server reload-config| Key | Action |
|---|---|
Ctrl-Shift-A |
Open visible file picker |
Ctrl-E |
Open visible link picker |
File picker controls:
| Key | Action |
|---|---|
Enter |
Open in a new Neovim split beside the source pane |
Ctrl-O |
Open with the default app |
Ctrl-Y |
Agent pane: send /plannotator-annotate <file>; shell pane: run plannotator annotate <file> |
Ctrl-S |
Toggle appearance order / alphabetical sort |
Link picker controls:
| Key | Action |
|---|---|
Enter |
Open URL in the browser/default opener |
Ctrl-Y |
Copy URL to clipboard |
Ctrl-S |
Toggle appearance order / alphabetical sort |
Herdr is the main plugin target, but the same picker works in tmux.
set -g @termscope "/path/to/termscope/termscope"
bind-key -n C-S-a run-shell "tmux display-popup -E -w 80% -h 60% '#{@termscope} pick --pane-path #{q:pane_current_path} --pane-id #{q:pane_id}'"
bind-key -n C-e run-shell "tmux display-popup -E -w 80% -h 60% '#{@termscope} links --pane-path #{q:pane_current_path} --pane-id #{q:pane_id}'"
bind-key -T copy-mode-vi C-S-a run-shell "tmux display-popup -E -w 80% -h 60% '#{@termscope} pick --pane-path #{q:pane_current_path} --pane-id #{q:pane_id}'"
bind-key -T copy-mode-vi C-e run-shell "tmux display-popup -E -w 80% -h 60% '#{@termscope} links --pane-path #{q:pane_current_path} --pane-id #{q:pane_id}'"
bind-key -T copy-mode-vi 'o' send -F -X copy-pipe-and-cancel "#{@termscope} open --mode nvim --pane-path #{q:pane_current_path} --pane-id #{q:pane_id}"
bind-key -T copy-mode-vi 'O' send -F -X copy-pipe-and-cancel "#{@termscope} open --mode default --pane-path #{q:pane_current_path} --pane-id #{q:pane_id}"
bind-key -T copy-mode-vi P run-shell "tmux display-popup -E -w 80% -h 60% '#{@termscope} pick --pane-path #{q:pane_current_path} --pane-id #{q:pane_id}'"In tmux copy-mode these bindings preserve the scrolled viewport instead of jumping back to the live bottom of the pane.
| Environment variable | Purpose |
|---|---|
TERMSCOPE_OPENER |
Override default opener, e.g. open -a Zen or open -a Firefox |
TERMSCOPE_SORT |
Default sort mode: appearance or alpha |
TERMSCOPE_LOG |
Path to the JSON event log |
TERMSCOPE_DEBUG_DIR |
Directory for per-run debug dumps |
Examples:
export TERMSCOPE_OPENER='open -a Zen'
export TERMSCOPE_SORT=alphaSee what the scanner would offer without opening Television:
./termscope scan --pane-path "$PWD" --pane-id "$HERDR_PANE_ID" --multiplexer herdrEnable debug dumps:
export TERMSCOPE_DEBUG_DIR=/tmp/termscope-debugEach run writes the captured screen, indexed files, candidates, and final selection decision.
Herdr plugin actions run without a TTY, so termscope.open first opens an
80% × 60% session-modal popup. The popup inherits the source pane id/cwd,
captures visible text with herdr pane read --source visible, scans the repo
with fd, and runs Television. Two bundled channels let Ctrl-S cycle between
appearance and alphabetical order. File previews use bat when available and a
built-in text preview otherwise.
When you choose a file, Termscope asks Herdr to split beside the source pane and
runs nvim +line path. For URLs, it uses the default opener unless
TERMSCOPE_OPENER is set.
python3 -m py_compile termscope termscope_herdr.py
python3 -m unittest discover -s tests
herdr plugin link "$PWD"
herdr plugin action invoke termscope.openThe repo intentionally has no package manager or build step. Herdr installs it
by cloning the repo and reading herdr-plugin.toml.
MIT © iury souza
