MIT Rust + floem Wayland (wlr-layer-shell) Windows (Scoop)

Pick anything.
hjkl-fast.

Vim-modal picker. Rofi replacement.

Seven modes — dmenu, drun, run, ssh, emoji, clipboard, calc — on a real Wayland layer-shell overlay with exclusive keyboard grab. On Windows the same binary opens a regular top-level window. One binary, no daemon, no phone-home.

pikr — drun
fir 3 / 412
Firefox web browser
Fire Studio scene graph editor
Firmware Finder device tools
NORMAL j/k move · / search · <CR> launch · : ex · <Esc> quit

why

A launcher shaped like a vim picker.

01 — KEYS

Vim-modal navigation

Normal, Insert and Visual. j/k move. gg/G snap. Ctrl-d/Ctrl-u half-page. / search. : ex command. Count prefixes work — 5j jumps five rows. Insert-entry motions match vim: i, a, A, I.

02 — FUZZY

nucleo matcher

The same fuzzy matcher Helix ships. Match positions highlight inline so you can see why a row scored where it did.

03 — MODES

Seven sources, one keymap

dmenu · drun · run · ssh · emoji · clipboard · calc, all behind a single Mode trait. Pick with --show, or switch live from the ex line.

04 — RENDER

floem + layer-shell

Built on floem (vello GPU render, reactive views). Layer-shell ships today through pinned floem + winit forks — real overlay, exclusive zone, exclusive keyboard grab — while the upstream split (lapce/floem#1077, the menus feature gate) is still open. The [patch.crates-io] entries come out when both land on crates.io.

05 — SINGLE BIN

No daemon. No state.

Cold-start picker, exit on accept. No background service. Config is pure TOML, never auto-written, in-memory defaults when absent.

06 — WAYLAND

Native, not wrapped

No Qt, no Electron, no web view — floem draws every pixel (GTK3 comes along transitively for floem's menu backend on Linux). Needs a compositor advertising wlr-layer-shell-unstable-v1 — Hyprland, sway, niri, river, wayfire. GNOME Mutter doesn't advertise it; X11 support was dropped and there is no windowed-fallback flag.

07 — STDIN

Pipe anything

echo "$(ls)" | pikr --dmenu picks a line. Stdout is clean — wire pikr into shell pipelines the way you'd wire fzf.

08 — DETACHED

Launches don't leak

Every spawn gets stdin, stdout and stderr nulled, so the launched app never captures pikr's file descriptors or scribbles over a dmenu pipeline. pikr exits right after accept; the child keeps running.

09 — PRIVACY

Zero telemetry

No analytics, no update pings, no usage stats. No HTTP client anywhere in the dependency tree. Local config, local defaults.

10 — RANKING

Frecency + query history

Accepts bump a per-mode counter with half-life decay, so the apps you actually launch float above equally-matching rows. Queries are remembered per mode — Ctrl-P/Ctrl-N walk back through them. Both live in plain TOML under $XDG_STATE_HOME/pikr/.

11 — VISUAL

Pick a range, launch it

v/V anchors a range over the result list; Enter executes every row in it. Twelve emoji, four apps, a block of dmenu lines — one accept.

modes

Seven sources of selectable rows, one keymap.

Modes implement a single Mode trait: collect() -> Vec<Entry>, and every entry carries a payload — print to stdout, spawn detached, or set the clipboard. Picker state, key dispatch, matcher, and UI are mode-agnostic; execution never goes back through the mode. Plugin host (WASM / dyn) is tracked as a followup.

--dmenu / -d
dmenu
Read newline-separated entries from stdin, print the accepted selection to stdout. Drop-in for shell pipelines. Compatible with rofi's -dmenu flag.
--show drun
drun
Unix: scan $XDG_DATA_DIRS/applications/*.desktop, honor Hidden / NoDisplay, parse Exec= per the freedesktop spec, resolve icons through the active XDG icon theme. Windows: walk both Start Menu trees, parse the .lnk shortcuts in parallel, pull icons out via SHGetFileInfo and cache them as PNG.
--show run
run
Walk $PATH, dedupe, and filter by the executable bit on Unix or by %PATHEXT% on Windows (where the row shows the stem, so you type firefox, not firefox.exe). The selection is spawned directly — no shell, so nothing interpolates.
--show ssh
ssh
Hosts parsed out of ~/.ssh/config (plus /etc/ssh/ssh_config on Unix). Accept opens the session in $TERMINAL, else the first one found — alacritty / kitty / foot / xterm on Unix, Windows Terminal / pwsh / cmd on Windows.
--show emoji
emoji
Searchable Unicode emoji picker — rows read 😀 grinning face so the matcher has a name to chew on; only the bare character goes to stdout.
--show clipboard
clipboard
Unix: rows come from cliphist list, and accepting pipes the entry back through cliphist decode | wl-copy — so it needs those two on $PATH. Windows: the current clipboard text, written back via the native API; per-item history there is still open.
--show calc
calc
Reactive expression evaluator (evalexpr) — the result updates as you type, no Enter required until you want it. An empty query lists past expressions; pick one to load it back for editing.

Flags for the awkward cases.

-p / --prompt prompt text in the input row
-P / --password mask the query with ● — matcher still sees the real text
--filter pre-fill the query on launch (aliases: query, prefill)
-e / --message non-interactive message modal, Esc dismisses
--mode start in normal instead of insert (insert is the default)
--width / -l window width in px (720) / visible result rows (8)
--config load a specific config.toml instead of the XDG one

keys

The bindings you already know.

Three modes, vim semantics. pikr opens in Insert so you can just start typing; Esc drops to Normal, i goes back, and v opens a Visual range over the results. Start in Normal instead with --mode normal.

normal mode · navigation
j / k move down / up
gg / G top / bottom
Ctrl-d / Ctrl-u half-page down / up
5j count prefix · jump 5 rows
h / l move the caret inside the query
normal mode · action
i / a / A / I enter insert · before, after, end, start
v / V visual range over the result list (same key exits)
/ start search
: ex command line
Enter accept selection — or the whole range, in visual
Esc cancel · exits 1 so pipelines can branch on dismissal
insert mode · the query bar
Shift-Enter accept the raw query instead of the highlighted row
Ctrl-P / Ctrl-N previous / next query from this mode's history
Ctrl-W / Ctrl-U delete word back / to start of line
Ctrl-A / Ctrl-E caret to start / end (readline)
ex commands
:dmenu switch to dmenu mode
:drun switch to drun mode
:run switch to run mode
:ssh / :emoji switch to ssh / emoji mode
:clipboard / :calc switch to clipboard / calc mode
:q quit

install

Native packages on every tagged release — .deb, .rpm, AUR, Homebrew, Scoop.

Every tag ships x86_64 Linux (glibc), Windows MSVC, and macOS (Intel + Apple Silicon) binaries, plus a Debian .deb and a Fedora/RHEL .rpm, each with a SHA-256 sidecar. aarch64 Linux and musl are out for now — the cross-compile plumbing for floem's GTK deps is still being sorted, and the Alpine .apk is parked behind it. On Linux the picker is Wayland-only: a compositor advertising wlr-layer-shell-unstable-v1 is required. macOS binaries build and install, but the launcher's window behaviour there hasn't been validated end to end yet.

pikr — Arch Linux (AUR)
$ yay -S pikr-bin
$ paru -S pikr-bin
$ pikr
pikr — macOS (Homebrew)
$ brew install kryptic-sh/tap/pikr
$ pikr
pikr — Debian / Fedora
# Debian / Ubuntu / Mint / Pop!_OS
$ curl -fsSLO https://github.com/kryptic-sh/pikr/releases/latest/download/pikr_*_amd64.deb
$ sudo dpkg -i pikr_*_amd64.deb

# Fedora / RHEL / Rocky / Alma / openSUSE
$ sudo dnf install https://github.com/kryptic-sh/pikr/releases/latest/download/pikr-*.x86_64.rpm
pikr — Windows (Scoop)
> scoop bucket add kryptic https://github.com/kryptic-sh/scoop-bucket
> scoop install kryptic/pikr
pikr — from source
$ git clone https://github.com/kryptic-sh/pikr
$ cd pikr
$ cargo build --release

# Linux build deps: libgtk-3-dev + libxkbcommon-dev
# binary in target/release/pikr