doc: Add install guide instructions.
This commit is contained in:
286
docs/guides/app-launcher.md
Normal file
286
docs/guides/app-launcher.md
Normal file
@@ -0,0 +1,286 @@
|
||||
# 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](../use-cases/app-launcher.md).
|
||||
|
||||
## Quick start: terminal
|
||||
|
||||
The simplest version. No GUI, no hotkeys, just an alias:
|
||||
|
||||
```sh
|
||||
# ~/.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:
|
||||
|
||||
```sh
|
||||
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`):
|
||||
|
||||
```sh
|
||||
#!/bin/sh
|
||||
# pikl-launch: open pikl as a GUI app launcher
|
||||
|
||||
compgen -c | sort -u \
|
||||
| pikl --mode gui \
|
||||
| xargs -I{} sh -c '{} &'
|
||||
```
|
||||
|
||||
```sh
|
||||
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](https://raycast.com) 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`:**
|
||||
|
||||
```bash
|
||||
#!/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 "{}"
|
||||
```
|
||||
|
||||
```sh
|
||||
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:
|
||||
|
||||
```bash
|
||||
#!/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](https://github.com/koekeishiya/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:
|
||||
|
||||
```sh
|
||||
# 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:
|
||||
|
||||
```sh
|
||||
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):
|
||||
|
||||
```sh
|
||||
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.
|
||||
Reference in New Issue
Block a user