Benjamin Shawki
Potters.Tools

Using FZF as a Universal Launcher on Sway

SwayFZFLinuxWindow ManagerProductivity

Every picker, launcher, and selector on my desktop is just a list piped into FZF inside a floating terminal window. No rofi, no dmenu, no wofi. Just FZF.

The idea is simple: if you can generate a list, you can make a launcher. The Sway window manager makes this trivial with for_window rules that turn any terminal into a centered floating picker.

The Application Launcher

This one-liner replaces a traditional application launcher entirely:

bash
bindsym $mod+d exec foot --app-id='launcher' -- bash -c 'compgen -c | sort -u | fzf | xargs -r swaymsg -t command exec;'
for_window [app_id="^launcher$"] floating enable, border none, resize set width 50 ppt height 50 ppt, move position center

compgen -c lists every executable on your $PATH. Pipe it through sort -u to deduplicate, let FZF do the fuzzy matching, and xargs -r swaymsg -t command exec tells Sway to launch whatever you picked. The for_window rule makes it float, removes the border, sizes it to 50% of the screen, and centers it.

That is the entire application launcher. No config files, no plugins, no daemon running in the background.

The Emoji Picker

Same pattern, different list. The emoji picker reads from a CSV file and pipes it through FZF:

bash
bindsym $mod+colon exec $USER_BIN/emoji-picker/emoji-picker.sh
for_window [app_id="^emoji-picker$"] floating enable, border none, resize set width 65 ppt height 60 ppt, move position center

The script itself processes a CSV of emojis with awk, presents them in FZF with a preview pane showing the emoji large, and copies the selection to clipboard:

bash
emoji_data=$(awk -F ', ' '{gsub(/"/, "", $2); print $1 "\t" $2}' "$EMOJI_FILE")

selected=$(echo -e "$emoji_data" | fzf --reverse --border rounded \
  --prompt "Find emoji: " \
  --preview "echo -e {1}" \
  --preview-window up:1 \
  --header "Select an emoji (press ESC to cancel)" \
  --info inline)

if [ -n "$selected" ]; then
    emoji=$(echo "$selected" | awk '{print $1}')
    echo -n "$emoji" | wl-copy
    notify-send "Emoji copied to clipboard" "$emoji"
fi

The CSV is just emoji, "description" pairs. Adding new emojis is editing a text file.

The Monitor Profile Switcher

I switch between an LG UltraGear ultrawide, an XREAL One Pro, HDMI displays, and the laptop's internal screen. Each has different resolution, refresh rate, and scaling needs. An FZF picker lets me switch between them with $mod+m:

bash
bindsym $mod+m exec foot --app-id='monitor-profile' -- "$HOME/dotfiles/sway/profiles/fzf-monitor-profile.sh" &
for_window [app_id="^monitor-profile$"] floating enable, border none, resize set width 60 ppt height 40 ppt, move position center

The script defines profiles as a simple bash array with descriptions:

bash
profiles=(
    "Auto-detect:Automatically detect and apply appropriate profile"
    "LG UltraGear:3440x1440@160Hz, internal display disabled"
    "XREAL One Pro:1920x1080@120Hz 1.5x scale, internal display disabled"
    "HDMI Only:External HDMI 1920x1080@60Hz, internal display disabled"
    "Dual Default:External monitor on top, laptop screen centered below"
    "Internal Only:Use only laptop display"
)

selected=$(printf '%s\n' "${profiles[@]}" | fzf --prompt="Select monitor profile: " --height=40% --reverse)

The selected profile name maps to a function in a shared monitors.conf that calls the appropriate swaymsg output commands. The auto-detect option runs a setup script that reads connected monitors via swaymsg -t get_outputs and picks the right profile by model name.

The Pattern

Every one of these follows the same three-step recipe:

  1. Launch foot (or any terminal) with a unique --app-id
  2. Pipe a list into fzf and do something with the result
  3. Add a for_window rule in your Sway config to float and size the window

My reading list manager ($mod+o), and my tmux session chooser ($mod+Shift+Return). Every new picker is just another script and two lines in the Sway config.

The best part is that FZF's fuzzy matching is consistently excellent across all of them. Learn one interface, use it everywhere.

Using FZF as a Universal Launcher on Sway | Potters.Tools Blog | Potters Tools