Files
pikl/docs/guides/app-launcher.md
J. Champagne f6f1efdf8e
Some checks failed
CI / Lint (push) Has been cancelled
CI / Test (push) Has been cancelled
doc: Add install guide instructions.
2026-03-14 12:50:27 -04:00

7.3 KiB

App Launcher Setup

Use pikl as a keyboard-driven application launcher. Bind a hotkey, type a few characters, hit Enter, and your app launches. This guide covers terminal, Hyprland, i3, and macOS setups.

For the design rationale and feature roadmap, see the app launcher use case.

Quick start: terminal

The simplest version. No GUI, no hotkeys, just an alias:

# ~/.bashrc or ~/.zshrc
alias launch='compgen -c | sort -u | pikl | xargs -I{} sh -c "{} &"'

Run launch, type to filter, Enter to run the selection in the background. That's it.

With descriptions (experimental)

You can pull one-line descriptions from man pages using whatis. This is noticeably slow on systems with thousands of binaries (it shells out per binary), so treat it as a nice-to-have rather than the default:

launch-rich() {
  compgen -c | sort -u | while IFS= read -r cmd; do
    desc=$(whatis "$cmd" 2>/dev/null | head -1 | sed 's/.*- //')
    printf '{"label":"%s","sublabel":"%s"}\n' "$cmd" "$desc"
  done | pikl --format '{label} <dim>{sublabel}</dim>' \
       | jq -r '.label' \
       | xargs -I{} sh -c '{} &'
}

This works, but it's slow. Caching the output of the whatis loop to a file and refreshing it periodically would make it usable day-to-day. A built-in indexing solution is on the roadmap but not built yet.

Hyprland

Hyprland is a first-class target. pikl uses iced_layershell to render as a Wayland layer-shell overlay, so it floats above your desktop like rofi does.

The launcher script

Save this somewhere in your PATH (e.g. ~/.local/bin/pikl-launch):

#!/bin/sh
# pikl-launch: open pikl as a GUI app launcher

compgen -c | sort -u \
  | pikl --mode gui \
  | xargs -I{} sh -c '{} &'
chmod +x ~/.local/bin/pikl-launch

Keybinding

Add to ~/.config/hypr/hyprland.conf:

bind = SUPER, SPACE, exec, pikl-launch

Reload with hyprctl reload or restart Hyprland.

With .desktop files (future)

When pikl gains .desktop file parsing (or a helper script emits structured JSON from XDG desktop entries), you'll get proper app names, descriptions, and categories instead of raw binary names. The keybinding and workflow stay the same, only the input to pikl changes.

i3

i3 runs on X11, so pikl opens as an override-redirect window rather than a layer-shell overlay. Same launcher script, different keybinding syntax.

The launcher script

Same pikl-launch script as Hyprland above. pikl auto-detects X11 vs Wayland, so no changes needed.

Keybinding

Add to ~/.config/i3/config:

bindsym $mod+space exec --no-startup-id pikl-launch

Reload with $mod+Shift+r.

Notes

  • --no-startup-id prevents the i3 startup notification cursor from spinning while pikl is open.
  • If pikl doesn't grab focus automatically, you may need to add an i3 rule:
    for_window [class="pikl"] focus
    

macOS with Raycast

Raycast is the best way to bind a global hotkey to pikl on macOS. You create a script command that Raycast can trigger from its search bar or a direct hotkey.

Prerequisites

  • Raycast installed
  • pikl installed (cargo install pikl)
  • pikl in your PATH (cargo's bin directory is usually ~/.cargo/bin, make sure it's in your shell PATH)

Create the script command

Raycast script commands are shell scripts with a special header. Create this file in your Raycast script commands directory (usually ~/.config/raycast/scripts/ or wherever you've configured it):

pikl-launch.sh:

#!/bin/bash

# Required parameters:
# @raycast.schemaVersion 1
# @raycast.title App Launcher (pikl)
# @raycast.mode silent
# @raycast.packageName pikl

# Optional parameters:
# @raycast.icon :rocket:

# Scan /Applications for .app bundles, pipe to pikl, open the result
find /Applications ~/Applications -maxdepth 2 -name '*.app' 2>/dev/null \
  | sed 's|.*/||; s|\.app$||' \
  | sort -u \
  | pikl --mode gui \
  | xargs -I{} open -a "{}"
chmod +x pikl-launch.sh

The silent mode tells Raycast not to show any output window. pikl handles its own GUI.

Assign a hotkey

  1. Open Raycast preferences (Cmd+,)
  2. Go to Extensions
  3. Find "App Launcher (pikl)" under Script Commands
  4. Click the hotkey field and press your preferred combo (e.g. Ctrl+Space, Opt+Space, etc.)

With structured JSON input

For a richer experience with app metadata, you can parse the Info.plist files inside .app bundles:

#!/bin/bash

# Required parameters:
# @raycast.schemaVersion 1
# @raycast.title App Launcher (pikl)
# @raycast.mode silent
# @raycast.packageName pikl

for app in /Applications/*.app ~/Applications/*.app; do
  [ -d "$app" ] || continue
  name=$(basename "$app" .app)
  # Pull the bundle identifier for metadata
  bundle_id=$(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" \
    "$app/Contents/Info.plist" 2>/dev/null)
  printf '{"label":"%s","meta":{"bundle":"%s","path":"%s"}}\n' \
    "$name" "$bundle_id" "$app"
done \
  | pikl --mode gui \
  | jq -r '.meta.path' \
  | xargs -I{} open "{}"

This version gives pikl structured data to work with. When pikl gains frecency sorting, your most-launched apps will float to the top automatically.

Alternative: skhd

If you don't use Raycast, skhd is a standalone hotkey daemon:

# ~/.config/skhd/skhdrc
ctrl + space : pikl-launch-mac.sh

Where pikl-launch-mac.sh is the same script as above, minus the Raycast header comments.

Customizing the launcher

These tips apply to all platforms.

Filter fields

If your input includes structured JSON with metadata, tell pikl which fields to search:

# Search both label and sublabel when filtering
pikl --filter-fields label,sublabel

Hooks

Run something when the launcher opens or when an item is selected:

pikl --mode gui \
  --on-select-exec 'jq -r .label >> ~/.local/state/pikl-launch-history'

This logs every launch to a history file, which could feed into frecency sorting later.

Starting in normal mode

If you prefer to land in vim normal mode (navigate first, then / to filter):

pikl --mode gui --start-mode normal

What's not built yet

A few things mentioned in this guide depend on features that are still in development:

  • GUI frontend (phase 8): the --mode gui flag and layer-shell/X11 rendering. Until this ships, you can use the TUI versions in a drop-down terminal (like tdrop, kitty's --single-instance, or a quake-mode terminal).
  • Frecency sorting: tracking launch frequency and boosting common picks. On the roadmap.
  • .desktop file parsing: structured input from XDG desktop entries with proper names, icons, and categories. On the roadmap.
  • Description caching/indexing: a way to build and maintain a local index of binary descriptions so the launcher can show what each app does without the slow whatis loop. On the roadmap.

GNOME, KDE, and other desktops

These aren't supported as app launcher environments right now. Hyprland, i3, and macOS are the environments the dev team uses daily, so that's where the effort goes. The main blocker for GNOME on Wayland is the lack of layer-shell support, which means pikl can't render as an overlay the same way it does on wlroots-based compositors.

If you use one of these environments and want to help, PRs and discussion are welcome.