tmux-fzf-url is a tmux plugin that extracts URLs from terminal content and lets users quickly open them via fzf fuzzy selection, without using a mouse.
- Language: Bash + Rust (via xre)
- Dependencies:
fzf,tmux,bash,xre(auto-installed to$SCRIPT_DIR/bin/) - Platform: Linux / macOS
βββ fzf-url.tmux # Plugin entry point: reads tmux options, registers keybinding
βββ fzf-url.sh # Core logic: captures pane content, extracts URLs, opens selection
βββ test/
β βββ libs/ # bats-core, bats-assert, bats-support (git submodules)
β βββ test_helper.bash # Shared setup: source fzf-url.sh, load assertions
β βββ *.bats # Test files for each extraction function
βββ .github/workflows/test.yml # CI: cross-platform test matrix (ubuntu + macOS)
βββ README.md # User documentation
βββ LICENSE.txt # MIT license
βββ FUNDING.yml # Sponsorship info
The plugin consists of two scripts:
-
fzf-url.tmuxβ Entry point loaded by TPM (or manually). Reads user configuration from tmux global options (@fzf-url-*) and binds a key to invokefzf-url.shwith the resolved parameters. -
fzf-url.shβ Core script invoked at runtime. It:- Captures the current tmux pane content (screen or scrollback)
- Pipes content through
xre --strip-ansiwhich handles ANSI stripping, multi-pattern URL extraction (with priority-based overlap prevention), replacement, and deduplication in a single pass - Optionally applies a user-defined custom pattern (
@fzf-url-custom-pat/@fzf-url-custom-sub) - Numbers results and presents them via fzf for interactive selection (version-aware:
fzf --tmuxfor >= 0.53.0, otherwisefzf-tmux) - Opens selected URLs using
xdg-open,open,$BROWSER, or a custom command
All options are tmux global options set via set -g:
| Option | Default | Description |
|---|---|---|
@fzf-url-bind |
u |
Key binding (after tmux prefix) |
@fzf-url-history-limit |
screen |
Scrollback lines to capture |
@fzf-url-fzf-options |
'' |
Custom fzf-tmux flags |
@fzf-url-open |
'' |
Custom command to open URLs |
@fzf-url-custom-pat |
'' |
Custom xre regex pattern for extraction |
@fzf-url-custom-sub |
'' |
Replacement template for custom pattern |
The plugin extracts the following URL formats from pane content:
- Standard URLs β
https?://,ftp://,file:// - WWW URLs β
www.example.com(auto-prefixed withhttp://) - IP addresses β
192.168.1.1:8080/path(wrapped ashttp://) - Git SSH URLs β
git@github.com:user/repo(converted tohttps://) - GitHub shorthand β
'user/repo'or"user/repo"(converted tohttps://github.com/) - Custom patterns β via
@fzf-url-custom-pat/@fzf-url-custom-sub
- Keep the codebase minimal β the entire plugin is two short shell scripts plus
xrefor extraction. - The scripts use Bash features (
[[ ]],$(...), etc.) and requirebash. - URL extraction is handled by
xrevia thexre_extractwrapper function. Pattern priority ensures higher-priority patterns (e.g., full URLs) consume byte ranges before lower-priority patterns (e.g., barewww.domains) can match overlapping text. - When modifying fzf invocation, maintain backward compatibility with older fzf versions (the
version_gefunction handles version detection). - Pane content is captured via
tmux capture-pane -J -p -eand passed raw toxre --strip-ansi. - Log output from URL opening goes to
/tmp/tmux-$(id -u)-fzf-url.log.
Automated tests use bats-core (added as git submodules):
# First-time setup (if cloned without --recurse-submodules)
git submodule update --init --recursive
# Run all tests
./test/libs/bats-core/bin/bats test/*.batsThe test suite covers the unified xre_extract function (all URL types, dedup, ANSI stripping), version_ge, and integration scenarios. URL extraction logic is also tested by xre's own Rust test suite. fzf-url.sh exposes a source guard (__FZF_URL_TESTING=1) so tests can source the functions without executing the main logic.
GitHub Actions CI runs the tests on both ubuntu and macOS to catch GNU/BSD compatibility issues.
Manual testing is still recommended for end-to-end verification:
- Install the plugin in a tmux session (via TPM or source
fzf-url.tmux) - Display content containing various URL formats in the pane
- Press
prefix + u(or configured key) and verify URLs are correctly extracted and selectable