tmux-open-urls.md (2899B)
1 # tmux trick #3: open URLs without the mouse 2 3 *This post is part of a [series](../../series)* 4 5 My [last post in this series](../2026-05-17-tmux-clipboard) on copy mode 6 was inspired by an old `.tmux.conf` file that I found in a backup folder. 7 In that same file I also had a command that selects all URLs that are 8 visible in the current pane, shows them to the user in a 9 [dmenu](https://tools.suckless.org/dmenu) session, and opens the 10 selected URL in a browser. This command is bound to `C-b u` with 11 the following configuration line: 12 13 ``` 14 bind u run "tmux capture-pane; tmux show-buffer | urlgrep | dmenu -l | xargs firefox" 15 ``` 16 17 This command is a great example of UNIX program composability. Let's break it down! 18 19 ## The pipeline 20 21 First, `tmux capture-pane` copies all the text of the current pane in 22 its copy buffer. Then `tmux show-buffer` prints the current copy buffer 23 to standard output - we talked about this last time. 24 25 This text is then [piped](https://en.wikipedia.org/wiki/Pipeline_(Unix)) 26 into `urlgrep`, a custom script that I wrote by copy-pasting a regular 27 expression from some StackOverflow answer: 28 29 ``` 30 #!/bin/sh 31 32 protocols='http|https|ftp|sftp|gemini|mailto' 33 valid_chars="][a-zA-Z0-9_~/?#@!$&'()*+=.,;:-" 34 regex="(($protocols):|www\.)[$valid_chars]+" 35 36 egrep -o "$regex" 37 ``` 38 39 This [grep](../2023-08-20-grep) command selects all URLs from its standard 40 input and prints them out one per line. These URLs are then sent to dmenu, 41 a graphical tool that prompts the user to select one of the items it received 42 in its standard input. The `-l` option is used to change `dmenu`'s layout so 43 that it shows one option per line. 44 45 The user's selection is then printed by `dmenu` to standard output; so we 46 use `xargs` to convert it to an argument for the `firefox` command. And 47 that's it! You can now follow links from your terminal using only your keyboard. 48 49 ## Caveats 50 51 If a URL is broken into multiple lines, my `urlgrep` script is only going to 52 select it until the end of the first line, so you won't be able to open 53 it correctly with this configuration. However, I found this to be a common 54 issue in many terminal emulators. 55 56 ## Update 2026-07-05 57 58 Shortly after this post was published, a reader emailed me his modified 59 version of the binding: 60 61 ``` 62 bind u { 63 capture-pane -J 64 display-popup -w 80% -T "Select URL to open" -E "tmux show-buffer | urlview" 65 } 66 ``` 67 68 This taught me three things: 69 70 1. `urlview` can replace my custom combo of scripts - cool! But I kinda like 71 my scripts, I think I'll keep using them. 72 2. Using `display-popup` to show a "window" inside the tmux session. This can 73 be useful e.g. if one is not running a graphical session at all. I can 74 use it together with the `-m fzf` option for my `dmenu-urlselect`. 75 3. The `-J` option for `capture-pane` to preserve trailing spaces and join 76 any wrapped lines. This may solve the caveat I mentioned above! 77 78 Thanks Johannes!