dfzf redefines how you interact with windows in sway and i3, letting you switch windows with fzf
, sorted by recency — no more cycling or losing your mind. Unlike traditional workspaces or tabbing, it frees you from relying on mental cartography, using name- and time-based navigation to keep access effortless, even with dozens of windows.
No more mental gymnastics. Just type to fuzzy-match and access recent windows first — eventually, you’ll rely solely on dfzf-windows for seamless navigation.
Click to expand description of the GIF
This GIF shows dfzf-windows in action:
- List the current windows, recent ones come first
- Inspect the windows previews, including terminal
- Mark the windows either as "urgent" or "important"
- Kills windows one by one until none are left
- Bonus: Notice a bit of "inception" in the
dfzf-windows
preview...
Using dfzf
invites you to rethink how you use your window manager:
- No more tabs — Use
dfzf-windows
to manage windows efficiently, without relying on tabbed layouts. - No more workspaces — Replace static workspaces with a flexible color tagging system. Assign multiple tags to a single window for powerful cross-grouping and faster navigation.
- No more bars — Free up screen space and ditch the traditional bar. Invoke minimal, dedicated popups for clock, system monitor, system info, wifi, and more — only when needed.
These make your desktop cleaner, more dynamic, and easier to manage — with more pixels dedicated to what actually matters — always full-screen !
- ⏱️ Instant access — switch to any window instantly, regardless of how many are open.
- 🔍 Recent-first navigation — fuzzy-search windows by name, with recent ones prioritized.
- 🧠 Low cognitive load — remember what and when, not where.
dfzf relies on dfzf-daemon
to track window focus changes via IPC, storing the order of recently used windows in their marks. It uses dfzf-mark
to add or remove marks, such as "important" marks (shown in red). And don't worry if you're already using marks — dfzf won't interfere with your existing setup.
Just make sure the daemon is running when you try dfzf for the first time!
dfzf
is more than a window switcher — it's a full toolkit for your desktop, built with speed, consistency, and minimalism in mind:
Tool | Description | i3 | Sway |
---|---|---|---|
dfzf-windows |
Navigate windows by title or time | ✅ | ✅ |
dfzf-scrollbacks |
Fuzzy-search within all your terminals at once | ✅ | ✅ |
dfzf-launcher |
Launch desktop apps or cmds in terminal | ✅ | ✅ |
dfzf-notify |
Browse past notifications | ❌ | ✅ |
dfzf-tasks |
Manage caldav tasks | ✅ | ✅ |
dfzf-clipboard |
Searchable clipboard with image/text preview | ❌ | ✅ |
dfzf-password |
Copy and preview entries from pass | ✅ | ✅ |
dfzf-mail |
View, preview and delete emails | ✅ | ✅ |
dfzf-exit |
Logout, reboot, suspend, hibernate | ❌ | ✅ |
dfzf-tools |
Clock, calendar, top, wifi, bluetooth, fetch popup | ✅ | ✅ |
dfzf-hub |
Invoke other dfzf commnands | ✅ | ✅ |
dfzf-term |
Terminal management (kill/new/toggle/scratchpad) | ✅ | ✅ |
Feature / Terminal | Kitty | Foot | Alacritty |
---|---|---|---|
dfzf-windows Terminal Preview |
✅ Full | ❌ Not supported | ❌ Not supported |
dfzf-scrollbacks Support |
✅ Full | ❌ Not supported | ❌ Not supported |
dfzf-clipboard Image Preview |
✅ Full | 🔻 Degraded | |
Press escape to kill popup |
✅ Full | ||
Everything else | ✅ Full | ✅ Full | ✅ Full |
Prerequisite
In general, dfzf needs:
- sway or i3, with default layout
tabbed
- fzf
- kitty version >= 0.42.1 OR alacritty OR foot
- jq version >= 1.7
- nerdfonts to display the glyphs (see nerdfont section)
Moreover, each tool can have specific dependencies described in the Features
section.
Also be sure fzf
is accessible from sway/i3, by moving it to /usr/local/bin/
(instead of default ~/.cargo/bin
place)
or setup sway/i3 path correctly
#~/.config/sway/config
set $PATH /usr/local/bin:/opt/bin:$PATH
Download the releases
- Download/copy the binaries into
/usr/local/bin/
or anywhere in your PATH. - Download the deb package, and
sudo dpkg -i
it on debian/ubuntu.
Build/install dfzf-daemon
cd dfzf-utils
curl https://sh.rustup.rs -sSf | sh
rustup update nightly
cargo +nightly build --release
find dfzf-utils -type f -executable -name "dfzf-*" |xargs -I@ sudo cp @ /usr/local/bin/
Nerdfont
Glyph are used in some dfzf modules (windows, tasks). If you don't wan't them you can override the config that way:
#~/.config/dfzf/dfzf.conf
windows_glyph_rules_json='[{"glyph": ""}]'
You can install nerdfont by running this script (source). Also snap apps cannot access to .local/share/fonts
, reason I personally install them into ~/.fonts
instead.
#!/bin/bash
declare -a fonts=(
BitstreamVeraSansMono
CascadiaCode
CodeNewRoman
DroidSansMono
FiraCode
FiraMono
Go-Mono
Hack
Hermit
JetBrainsMono
Meslo
Noto
Overpass
ProggyClean
RobotoMono
SourceCodePro
SpaceMono
Ubuntu
UbuntuMono
)
version=$(curl -s 'https://api.github.com/repos/ryanoasis/nerd-fonts/releases/latest' | jq -r '.name')
fonts_dir="${HOME}/.fonts"
if [[ ! -d "$fonts_dir" ]]; then
mkdir -p "$fonts_dir"
fi
for font in "${fonts[@]}"; do
zip_file="${font}.zip"
download_url="https://github.com/ryanoasis/nerd-fonts/releases/download/${version}/${zip_file}"
echo "Downloading $download_url"
wget "$download_url"
unzip "$zip_file" -d "$fonts_dir"
rm "$zip_file"
done
find "$fonts_dir" -name 'Windows Compatible' -delete
fc-cache -fv
Sway configuration
exec --no-startup-id dfzf-daemon # reboot to make the daemon running
exec wl-paste --watch cliphist -max-items 1000 store # for dfzf-clipboard
exec mako # for the dfzf-notifs
exec swaymsg workspace 1, layout tabbed
workspace_auto_back_and_forth no
# FOR FOOT OR ALACRITTY
#set $term foot
#set $term alacritty
#set $dfzf_term foot --app-id=dfzf-popup -e
#bindsym $mod+Tab exec --no-startup-id $dfzf_term dfzf-windows
#bindsym $mod+l exec --no-startup-id $dfzf_term dfzf-hub
# FOR KITTY
set $term kitty -1
exec --no-startup-id kitty -1 --start-as hidden
exec --no-startup-id kitty -1 --instance-group dfzf --start-as hidden -o 'map escape close_window' -o 'listen_on=unix:/tmp/kitty-dfzf'
bindsym $mod+Tab exec --no-startup-id kitty -1 --class=dfzf-popup -e dfzf-windows
bindsym $mod+l exec --no-startup-id kitty -1 --instance-group dfzf --class=dfzf-popup -e dfzf-hub
bindsym $mod+n exec dfzf-term scratchpad $term
bindsym ctrl+slash exec dfzf-term toggle $term
bindsym shift+ctrl+slash exec dfzf-term kill $term
for_window [app_id="^dfzf-popup$"] floating enable, sticky enable, resize set 60 ppt 70 ppt, border pixel 6
# optional: hide the tabs
font pango:monospace 0.001
default_border none
default_floating_border none
titlebar_padding 1
titlebar_border_thickness 0
I3 configuration
exec --no-startup-id dfzf-daemon # reboot to make the daemon running
workspace_layout tabbed
workspace_auto_back_and_forth no
# FOR FOOT OR ALACRITTY
#set $term foot
#set $term alacritty
#set $dfzf_term foot --app-id=dfzf-popup -e
#bindsym $mod+Tab exec --no-startup-id $dfzf_term dfzf-windows
#bindsym $mod+l exec --no-startup-id $dfzf_term dfzf-hub
# FOR KITTY
set $term kitty -1
exec --no-startup-id kitty -1 --start-as hidden
exec --no-startup-id kitty -1 --instance-group dfzf --start-as hidden -o 'map escape close_window' -o 'listen_on=unix:/tmp/kitty-dfzf'
bindsym $mod+Tab exec --no-startup-id kitty -1 --class=dfzf-popup -e dfzf-windows
bindsym $mod+l exec --no-startup-id kitty -1 --instance-group dfzf --class=dfzf-popup -e dfzf-hub
bindsym $mod+n exec dfzf-term scratchpad $term
bindsym ctrl+slash exec dfzf-term toggle $term
bindsym shift+ctrl+slash exec dfzf-term kill $term
for_window [class="^dfzf-popup$"] floating enable, sticky enable, resize set 60 ppt 70 ppt, border pixel 6
# optional: hide the tabs
font pango:monospace 0
default_border none
default_floating_border none
# reset font for the bar
bar {
font pango:monospace 10 # needed
status_command i3status
}
user configuration [optional]
you can override default configurations:
# ~/.config/dfzf/dfzf.conf
#kitty only: regexp to match the prompt
windows_prompt_pattern="^[>$%] "
#remove pattern from the window's title
windows_title_rm_pattern=' —[^—]*?— Mozilla Firefox'
# rename the application classes
windows_app_id_map_json='{"evolution": "mail", "kitty": "terminal", "jetbrains-idea-ce": "jetbrains"}'
# assign glyphs to application classes
windows_glyph_rules_json='[
{ "field": "name", "regex": "vim\\b", "glyph": " " },
{ "field": "app_id", "regex": "terminal", "glyph": " " },
{ "field": "app_id", "regex": "firefox", "glyph": " " },
{ "field": "app_id", "regex": "jetbrains", "glyph": " " },
{ "field": "app_id", "regex": "gimp", "glyph": " " },
{ "field": "app_id", "regex": "thunar|nautilus", "glyph": " " },
{ "field": "app_id", "regex": "thunderbird|evolution|geary|mailspring|k9mail|mail", "glyph": " " },
{ "glyph": " " }
]'
# override the exit list and respective commands
exit_options=(
"l: Lock (swaylock)"
"e: Restart GDM"
"s: Lock and Suspend"
"r: Reboot"
"S: Shutdown"
"h: Hibernate"
)
exit_cmd_l='swaylock -e -F -f -k -c 000000'
exit_cmd_e='sudo /usr/bin/systemctl restart gdm'
exit_cmd_s='swaylock -e -F -f -k -c 000000 && systemctl suspend'
exit_cmd_r='sudo reboot'
exit_cmd_S='shutdown now'
exit_cmd_h='sudo /bin/systemctl hibernate'
tools_clock_cmd="tty-clock -c -C 4 -s"
tools_calendar_cmd="~/.venv/3.11.6/bin/khal interactive"
tools_top_cmd="gotop"
Kitty configuration [optional]
#~/.config/kitty/kitty.conf
confirm_os_window_close 0
allow_remote_control yes
listen_on unix:/tmp/kitty
Windows terminal preview in kitty:
the terminal preview compares the i3/sway window title with the kitty title. In some case there is duplicates, and we cannot determinate the right terminal. So the current hack is to add 2 random characters to the title so that they get unique. For that, you will have to disable kitty title handling and tweak the shell title. Here for zsh:
#~/.config/kitty/kitty.conf
shell_integration no-title
tweak zsh:
# ~/.oh-my-zsh/lib/termsupport.zsh
case "$TERM" in
cygwin|xterm*|putty*|rxvt*|konsole*|ansi|mlterm*|alacritty*|st*|foot*|contour*)
print -Pn "\e]2;${2:q} /$(< /dev/urandom tr -dc A-Za-z0-9 | head -c 2)\a" # set window name
print -Pn "\e]1;${1:q} /$(< /dev/urandom tr -dc A-Za-z0-9 | head -c 2)\a" # set tab name
Firefox [optional]
Install the below extensions:
- tabs are windows
- hostname in windows title
I use this template
{title} - {href} —
, together with this variable in dfzf config to bring perfect ff titles.
# remove pattern from the window's title
windows_title_rm_pattern=' —[^—]*?— Mozilla Firefox'
Chromium [optional]
Install the below extensions:
- new-tab-new-window
- either URL in title or Title morph
Windows
- windows ordered by last access
- cycle previous window
- terminal scrollback preview (kitty only)
keybindings:
-
Return
: focus window -
ctrl-b
: toggle color blue -
ctrl-g
: toggle color green -
ctrl-o
: toggle color orange -
ctrl-r
: toggle color red -
B
: filter color blue -
G
: filter color green -
O
: filter color orange -
R
: filter color red -
ctrl-k
: kill window -
ctrl-u
: toggle urgent (yellow color) -
ctrl-i
: toggle important (red color) -
ctrl-j
: preview windows -
escape
: return to current windows (works after previews) -
ctrl-t
: will toggle tilling to the multi-selected windowssudo apt install jq ripgrep
Scrollbacks
Scrollbacks let you fuzzy-search across all your terminal histories (Kitty only) and focus the right one — great for digging up lost work from vague command memories.
sudo apt install ripgrep
Hub
The hub lets you launch any dfzf command with a single keystroke — one keybinding to rule them all.
Clipboard
- list latest mails
- preview text mails
ctrl-j
: preview html mails in the browser
sudo apt install jq himalaya
Notifications
- list notification ordered
Return
: notification actionctrl-k
: kill notificationctrl-h
: toggle notif history
sudo apt install jq mako-notifier
Tasks
Manage caldav tasks:
ctrl-t
: new taskctrl-e
: edit taskctrl-k
: delete taskctrl-d
: set status done for taskctrl-r
: sync tasks with remote caldavctrl-l
: choose the collection
pip install todoman vdirsyncer
Tools
Set of tools not related with fzf, but useful even to drop the sway bar.
- resource usage: top, htop, gotop ...
- calendar: khal, calcurse ...
- clock: tty-clock ...
- wifi
- bluetooth
- fetch: fastfetch
Terminal Management
dfzf-term
allows you to attach a companion terminal to any existing window, including terminals, Firefox, or any other application. It provides the ability to toggle the companion terminal between hidden, split, and stacked views for enhanced workflow management.
Key Bindings:
Ctrl + /
- Create or toggle companion terminal visibilityShift + Ctrl + /
- Kill the companion terminalCtrl + N
- Create a new independent terminal
Global Scratchpad Terminal:
dfzf-term scratchpad [terminal_command]
provides a floating scratchpad terminal that can be toggled from any workspace:
- Creates a floating terminal window sized at 90% of screen
- Automatically moves to scratchpad and centers on screen
- Toggles between hidden (in scratchpad) and visible states
- Works across both sway and i3 window managers
- Independent of companion terminal functionality
Smart Path Detection: The companion terminal automatically detects and opens in the appropriate working directory based on the focused window:
- JetBrains IDE: Extracts project path from window title
[/path/to/project]
- Neovim/Vim: Extracts path from terminal title ending with
- NVIM
or^vim
- Terminal: Extracts path from window title using pattern before
/[a-zA-Z]{2}
- Firefox: Defaults to home directory
Layout Intelligence:
- Seamlessly toggles between hidden, split, and stacked layouts
- Maintains focus on the primary application while providing quick terminal access
- Automatically manages window organization when creating or destroying companion terminals
Works with any application window, providing universal terminal access across your entire workspace.
dfzf
is the combination ofd
menu andfzf
- dfzf-daemon comes from i3-back
- dfzf-launcher comes from sway-launcher-desktop
- wofi-scripts has inspired dfzf-windows
- swayr: a window-switcher & more for sway
- i3-tools: switch to previous window
This project is licensed under the GNU General Public License v3.0.