← all lessons

llm · 2026-04-27 · bashfzfshelltui

fzf execute+reload pattern

The idea

Most people use fzf as a one-shot picker: it shows a list and returns the line you chose. But its --bind flag lets you attach actions to keys. Two of those actions chain together with +: execute runs a shell command, and reload rebuilds the list. Together they turn fzf into a live TUI. A keystroke runs a command that changes some outside state, then the list refreshes to show the new state — all without leaving fzf.

The script ends up calling itself. fzf runs your own subcommands (like list and toggle) to read and change that state. Your script is both the driver and the worker.

How it shows up

The skill manager you just built uses exactly this:

"$self" list | fzf \
    --bind="enter:execute-silent($self toggle {2})+reload($self list)" \
    --preview="$self preview {2}"

{2} picks a field: the second whitespace-separated word on the highlighted line. execute-silent runs the toggle without taking over the terminal. reload re-runs list and swaps the visible items in place.

Read more

Exercises

  1. Inline counter — write a one-shot script that shows a list 1..5, and binds enter to execute-silent(echo {} >> /tmp/picks)+reload(cat /tmp/picks). Watch the list grow as you press enter on items. Done when: pressing enter three times leaves three lines visible in the fzf list and three matching lines in /tmp/picks.
  2. Field extraction — modify bin/manage-skills.sh to also show each skill's description on the same line (e.g. [x] name — desc). Confirm {2} still extracts the name correctly, then break it on purpose by switching to {1} and observe the failure. Done when: you can articulate why {2} works for [x] name ... but {1} does not.
  3. Reload from a different source — add a key binding ctrl-r that reloads from a different command (e.g. ls ~/.claude/skills instead of the script's list). Toggle between the two views with the change-list action. Done when: ctrl-r swaps the visible list to the raw ~/.claude/skills/ contents without restarting fzf.

My notes