Skip to content

Hyprland Integration

Raffi knows when it runs inside Hyprland. It starts your apps through Hyprland, lists and closes windows, switches workspaces, and can focus an app that is already open instead of starting it again.

Use Hyprland’s Lua configuration (0.55 and later) to bind a key to plain raffi:

~/.config/hypr/hyprland.lua
hl.bind("SUPER + R", hl.dsp.exec_cmd("raffi"))

Hyprland still supports Hyprlang. Use Lua as the default here, and switch from the Hyprlang form if Hyprland deprecates it.

~/.config/hypr/hyprland.conf
bind = SUPER, R, exec, raffi

Raffi asks Hyprland to start the app you pick, so the app is Hyprland’s child, as if Hyprland had started it from a binding. See launch to change that.

Raffi’s window has the class com.chmouel.raffi. This Lua rule makes it float in the middle of the screen without a border:

Lua
hl.window_rule({
name = "raffi",
match = { class = "^(com\\.chmouel\\.raffi)$" },
float = true,
center = true,
size = { "(monitor_w*0.45)", "(monitor_h*0.78)" },
border_size = 0,
})

For Hyprlang (0.53 and later), use:

hyprland.conf
windowrule {
name = raffi
match:class = ^(com\.chmouel\.raffi)$
float = on
center = on
size = (monitor_w*0.45) (monitor_h*0.78)
border_size = 0
}

Raffi is translucent by default (opacity: 0.95), and Hyprland blurs what shows through while decoration:blur:enabled is on, which is the default. See Transparency and Blur.

--app-name changes the class, so a binding can open Raffi with its own rules, such as a wider window for the file browser in a light theme:

hl.bind("SUPER + SHIFT + H",
hl.dsp.exec_cmd("raffi --app-name com.chmouel.raffi.fb -t light -i '~/Downloads/'"))
hl.window_rule({
name = "raffi-files",
match = { class = "^(com\\.chmouel\\.raffi\\.fb)$" },
float = true,
center = true,
size = { "(monitor_w*0.8)", "(monitor_h*0.7)" },
border_size = 0,
})

Hyprlang equivalent:

bind = SUPER SHIFT, H, exec, raffi --app-name com.chmouel.raffi.fb -t light -i '~/Downloads/'
windowrule {
name = raffi-files
match:class = ^(com\.chmouel\.raffi\.fb)$
float = on
center = on
size = (monitor_w*0.8) (monitor_h*0.7)
border_size = 0
}

-i fills the search box, so a key can open Raffi straight into an addon:

hl.bind("SUPER + W", hl.dsp.exec_cmd("raffi -i 'win '"))
hl.bind("SUPER + V", hl.dsp.exec_cmd("raffi -i 'clip '"))
hl.bind("SUPER + B", hl.dsp.exec_cmd("raffi -i 'tabs '"))

Hyprlang equivalent:

bind = SUPER, W, exec, raffi -i "win "
bind = SUPER, V, exec, raffi -i "clip "
bind = SUPER, B, exec, raffi -i "tabs "

The window switcher lists your windows with their state (fullscreen, pinned, floating, grouped, XWayland) and their monitor. Ctrl+D closes the selected window, Ctrl+Enter moves it to your current workspace, and Ctrl+Tab switches to a list of workspaces, special ones included. The lists follow Hyprland as windows open, close and move.

In the clipboard browser, Ctrl+Enter pastes the chosen item into the window you were using.

Turn on raise_running and Enter on an app that has a window open focuses that window. Ctrl+Enter still starts a new one.

raffi.yaml
general:
raise_running: true

Raffi matches the window class from hyprctl clients. Launchers can opt in or out with raise, and set window_class when the class differs from the binary name. See Entries.

ifcompositor shows a launcher only inside Hyprland:

launchers.yaml
hyprpicker:
binary: hyprpicker
args: ["-a"]
description: "Pick a colour"
ifcompositor: hyprland

raffi -p prints the chosen command and starts nothing, if you prefer to start it yourself:

hl.bind("SUPER + R", hl.dsp.exec_cmd(
[=[choice=$(raffi -p); [ -n "$choice" ] && hyprctl dispatch "hl.dsp.exec_cmd([==[$choice]==])"]=]))

With Hyprlang, use:

bind = SUPER, R, exec, (val=$(raffi -p); [ -n "$val" ] && hyprctl dispatch exec "$val")

The [ -n ... ] check skips hyprctl when you close Raffi without picking anything. With a Lua config, hyprctl dispatch takes a Lua expression, so hyprctl dispatch exec ... fails there. Addon results such as emoji or snippets run inside Raffi and print nothing.

  • Raffi does not appear: check that raffi is on Hyprland’s PATH (try an absolute path in the binding) and look at hyprctl rollinglog.
  • To see what Raffi asks Hyprland, run it with --debug-file /tmp/raffi.log.