Adds sainnhe/tmux-fzf and three bindings, to solve two workflow problems:
seeing what is running across many sessions/windows/panes, and moving a pane
into another window without hand-typing a join-pane target.
Changes
config/tmux/plugins/tmux-fzf — new submodule
config/tmux.conf — @plugin line plus prefix+P / prefix+W / prefix+S bound directly to the pane, window and session panels
prefix+F (the plugin's own top-level menu) comes for free. prefix+w
(choose-tree) is deliberately untouched — it costs nothing and stays as a
fallback where the plugin isn't installed.
Reasoning
Why a submodule rather than letting TPM clone it.~/.tmux symlinks to config/tmux, so anything TPM installs lands inside this repo as untracked
files and dirties git status. A submodule pins a version and installs via
the git submodule update --init already in install.sh, matching how tpm
itself is handled. TPM still sources it from the @plugin line and can still
update it.
Why TMUX_FZF_CLIENT on each binding. A command run via run-shell has
no client context, so tmux falls back to the most recently active client.
With a second client attached to the same session — a browser terminal over
ttyd, say — the action lands in the wrong terminal. The plugin's own binding
sets this; the direct bindings need it too.
No env-var configuration. The plan called for setting TMUX_FZF_PREVIEW
and TMUX_FZF_ORDER, but reading the source showed both were unnecessary:
preview defaults to on, and the order default already leads with
session/window/pane. Worth noting the plugin's README suggests setting TMUX_FZF_LAUNCH_KEY="C-f" in .tmux.conf — that is not valid tmux syntax
and would raise an unknown-command error. main.tmux reads these from the
environment only.
A planned install.sh change was dropped. The design assumed nothing
bootstrapped TPM. That was wrong: tpm is already a tracked submodule and install.sh already runs git submodule update --init. No installer change
is needed, which also avoids adding a network clone to the install path.
Testing
Verified against tmux 3.5a and fzf 0.38.0:
Config parses with no errors; server starts cleanly
prefix+P, prefix+W, prefix+S all register with the expected commands
Existing bindings (T, a, y, r, R, C) are unaffected
TPM sources the plugin and creates the prefix+F binding
pane.sh, window.sh, session.sh pass bash -n
The plugin's fzf-version detection resolves to fzf-tmux with preview
enabled and popup sizing (-p -w 62% -h 38% -m)
Not covered: the interactive fzf picker needs a real terminal, so driving the
pickers and performing an actual pane join is left to manual verification.
**Summary generated by LLM agent**
## What
Adds `sainnhe/tmux-fzf` and three bindings, to solve two workflow problems:
seeing what is running across many sessions/windows/panes, and moving a pane
into another window without hand-typing a `join-pane` target.
## Changes
- `config/tmux/plugins/tmux-fzf` — new submodule
- `config/tmux.conf` — `@plugin` line plus `prefix+P` / `prefix+W` /
`prefix+S` bound directly to the pane, window and session panels
`prefix+F` (the plugin's own top-level menu) comes for free. `prefix+w`
(`choose-tree`) is deliberately untouched — it costs nothing and stays as a
fallback where the plugin isn't installed.
## Reasoning
**Why a submodule rather than letting TPM clone it.** `~/.tmux` symlinks to
`config/tmux`, so anything TPM installs lands inside this repo as untracked
files and dirties `git status`. A submodule pins a version and installs via
the `git submodule update --init` already in `install.sh`, matching how `tpm`
itself is handled. TPM still sources it from the `@plugin` line and can still
update it.
**Why `TMUX_FZF_CLIENT` on each binding.** A command run via `run-shell` has
no client context, so tmux falls back to the most recently active client.
With a second client attached to the same session — a browser terminal over
ttyd, say — the action lands in the wrong terminal. The plugin's own binding
sets this; the direct bindings need it too.
**No env-var configuration.** The plan called for setting `TMUX_FZF_PREVIEW`
and `TMUX_FZF_ORDER`, but reading the source showed both were unnecessary:
preview defaults to on, and the order default already leads with
session/window/pane. Worth noting the plugin's README suggests setting
`TMUX_FZF_LAUNCH_KEY="C-f"` in `.tmux.conf` — that is not valid tmux syntax
and would raise an unknown-command error. `main.tmux` reads these from the
environment only.
**A planned `install.sh` change was dropped.** The design assumed nothing
bootstrapped TPM. That was wrong: `tpm` is already a tracked submodule and
`install.sh` already runs `git submodule update --init`. No installer change
is needed, which also avoids adding a network clone to the install path.
## Testing
Verified against tmux 3.5a and fzf 0.38.0:
- Config parses with no errors; server starts cleanly
- `prefix+P`, `prefix+W`, `prefix+S` all register with the expected commands
- Existing bindings (`T`, `a`, `y`, `r`, `R`, `C`) are unaffected
- TPM sources the plugin and creates the `prefix+F` binding
- `pane.sh`, `window.sh`, `session.sh` pass `bash -n`
- The plugin's fzf-version detection resolves to `fzf-tmux` with preview
enabled and popup sizing (`-p -w 62% -h 38% -m`)
Not covered: the interactive fzf picker needs a real terminal, so driving the
pickers and performing an actual pane join is left to manual verification.
Many concurrent sessions with many panes each make it hard to track what is
running where, and moving a pane between windows means join-pane with a
hand-typed target, so it rarely gets done.
tmux-fzf gives a fuzzy-searchable list of every session, window and pane with
a live preview of each, and implements break/join/swap as pane actions --
which is the pane-movement gap. fzf is already in apt.global, arch.global and
brew.global, so no new packages are needed.
Checked out as a submodule rather than left for TPM to clone on first
prefix+I: ~/.tmux symlinks to config/tmux, so a TPM-installed plugin lands
inside this repo as untracked files. The submodule pins a version and
installs via the existing "git submodule update --init". TPM still sources it
from the @plugin line and can still update it.
prefix+F is the plugin's own top-level menu. prefix+P/W/S skip straight to
the pane, window and session panels. TMUX_FZF_CLIENT pins each action to the
client that opened it, as the plugin's own binding does -- run-shell has no
client context, so tmux otherwise targets the most recently active client,
which is wrong when a second client is attached to the same session.
No env-var configuration was needed: preview is already on by default, and
the TMUX_FZF_* variables are read from the environment only, so the README's
suggestion to set them in .tmux.conf is not valid tmux syntax.
Tested against tmux 3.5a and fzf 0.38.0: config parses with no errors, all
three bindings register, existing bindings are unaffected, TPM sources the
plugin and binds prefix+F, the three scripts pass bash -n, and the plugin's
fzf-version detection resolves to fzf-tmux with preview enabled. The
interactive picker itself needs a real terminal and is left to manual check.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary generated by LLM agent
What
Adds
sainnhe/tmux-fzfand three bindings, to solve two workflow problems:seeing what is running across many sessions/windows/panes, and moving a pane
into another window without hand-typing a
join-panetarget.Changes
config/tmux/plugins/tmux-fzf— new submoduleconfig/tmux.conf—@pluginline plusprefix+P/prefix+W/prefix+Sbound directly to the pane, window and session panelsprefix+F(the plugin's own top-level menu) comes for free.prefix+w(
choose-tree) is deliberately untouched — it costs nothing and stays as afallback where the plugin isn't installed.
Reasoning
Why a submodule rather than letting TPM clone it.
~/.tmuxsymlinks toconfig/tmux, so anything TPM installs lands inside this repo as untrackedfiles and dirties
git status. A submodule pins a version and installs viathe
git submodule update --initalready ininstall.sh, matching howtpmitself is handled. TPM still sources it from the
@pluginline and can stillupdate it.
Why
TMUX_FZF_CLIENTon each binding. A command run viarun-shellhasno client context, so tmux falls back to the most recently active client.
With a second client attached to the same session — a browser terminal over
ttyd, say — the action lands in the wrong terminal. The plugin's own binding
sets this; the direct bindings need it too.
No env-var configuration. The plan called for setting
TMUX_FZF_PREVIEWand
TMUX_FZF_ORDER, but reading the source showed both were unnecessary:preview defaults to on, and the order default already leads with
session/window/pane. Worth noting the plugin's README suggests setting
TMUX_FZF_LAUNCH_KEY="C-f"in.tmux.conf— that is not valid tmux syntaxand would raise an unknown-command error.
main.tmuxreads these from theenvironment only.
A planned
install.shchange was dropped. The design assumed nothingbootstrapped TPM. That was wrong:
tpmis already a tracked submodule andinstall.shalready runsgit submodule update --init. No installer changeis needed, which also avoids adding a network clone to the install path.
Testing
Verified against tmux 3.5a and fzf 0.38.0:
prefix+P,prefix+W,prefix+Sall register with the expected commandsT,a,y,r,R,C) are unaffectedprefix+Fbindingpane.sh,window.sh,session.shpassbash -nfzf-tmuxwith previewenabled and popup sizing (
-p -w 62% -h 38% -m)Not covered: the interactive fzf picker needs a real terminal, so driving the
pickers and performing an actual pane join is left to manual verification.