Vicinae
5 min read
Vicinae is a high-performance, native command launcher for Linux, inspired by Raycast. It's written in C++/Qt with a QML UI; extensions are React/TypeScript that produce a serialized UI tree the native core renders — no browser involved.
Out of the box it serves as an app launcher, window switcher, clipboard manager, file search, calculator, emoji picker, snippet/text expander, font browser, and volume controller. It is extensible via the Raycast-compatible TypeScript SDK, script commands, and a dmenu mode.
Architecture
Vicinae runs as a background server (daemon); the window is just a client you toggle. It does not implement global shortcuts — you bind a key in your compositor/DE to a vicinae command (usually a deeplink).
bash
vicinae server # start the daemon (foreground)
vicinae toggle # show/hide the window
vicinae version
Or run it as a systemd user service (recommended when your compositor is started via systemd, e.g. uwsm):
bash
systemctl --user enable --now vicinae.service
journalctl --user -u vicinae # view logs
On first start Vicinae uses a lot of CPU while it populates the file index.
A typical Hyprland setup:
ini
# ~/.config/hypr/hyprland.conf
exec-once = vicinae server # omit if using uwsm
bind = $mainMod, Space, exec, vicinae vicinae://toggle
Installation
| Method | Command |
|---|---|
| Install script (AppImage) | curl -fsSL https://vicinae.com/install | bash |
| Arch (AUR) | yay -S vicinae-bin (also vicinae, vicinae-git) |
| Fedora (COPR) | dnf copr enable quadratech188/vicinae && dnf install vicinae |
| Fedora (Terra) | sudo dnf install vicinae |
| Gentoo | jaredallard's overlay → emerge gui-apps/vicinae |
| Nix | nix shell github:vicinaehq/vicinae (run without installing) |
The install script drops the AppImage and runtime deps under /usr/local/lib/vicinae, symlinks binaries into PATH, installs desktop files and default themes, and bundles vicinae-node for TypeScript extensions. Custom prefix: ... | bash -s -- --prefix ~/.local. Uninstall: ... | bash -s -- --uninstall.
Third-party extensions need Node.js ≥ 20 on PATH, otherwise you get extension manager is not running.
NixOS / Home Manager
Vicinae ships a flake with NixOS and Home Manager modules.
nix
# home.nix
services.vicinae = {
enable = true;
systemd = {
enable = true;
autoStart = true;
environment.USE_LAYER_SHELL = 1;
};
settings = {
close_on_focus_loss = true;
pop_to_root_on_close = true;
favicon_service = "twenty";
font.normal = { size = 12; family = "Maple Nerd Font"; };
theme = {
dark.name = "vicinae-dark";
light.name = "vicinae-light";
};
launcher_window.opacity = 0.98;
};
};
Extensions and their preferences can be declared too; secrets are best injected via sops-nix templates imported into services.vicinae.settings.imports rather than written in plaintext. See Nix / NixOS.
Configuration
Settings live in ~/.config/vicinae/settings.json (JSONC — JSON with comments). Vicinae loads vicinae config default, then merges the user file on top. The file must be read- and writable, since GUI changes are written back to it. Open settings in-app with Ctrl+' or the "Open Settings" command.
bash
vicinae config default # print the fully-documented default config
vicinae server --config FILE # use an alternate config
Split config across files with the imports array (merged before the main file, never modified by Vicinae) — useful for read-only/managed configs:
jsonc
{
"imports": ["base_config.json", "keybinds.json"],
// ...
}
password-type extension preferences are stored in the internal SQLite DB, not the config file.
Useful environment variables
| Variable | Effect |
|---|---|
QT_SCALE_FACTOR=1.5 | Scale the launcher window (set per-process) |
QT_QUICK_FLICKABLE_WHEEL_DECELERATION | Lower → faster scrolling |
USE_LAYER_SHELL=1 | Use wlr-layer-shell (Wayland) |
Terminal apps are launched per the xdg-terminal-exec spec — set your terminal in ~/.config/xdg-terminals.list (e.g. kitty.desktop).
Deeplinks
Vicinae is controlled via the vicinae:// URL scheme (the raycast:// scheme works interchangeably). Invoke with the vicinae binary directly (faster than xdg-open):
bash
vicinae vicinae://toggle
vicinae vicinae://launch/clipboard/history # launch a command
vicinae 'vicinae://launch/clipboard/history?toggle=true'
vicinae 'vicinae://launch/power' # filter root search to a provider
vicinae vicinae://theme/set/gruvbox
Window controls: vicinae://toggle, open, open?popToRoot=true, close, pop_to_root, pop_current. Grab any command's deeplink with the "Copy Deeplink" action in the root search. Bind these to keys in your window manager — that's how you get global shortcuts.
Extending Vicinae
Three approaches, from simplest to most powerful:
Build a quick list view from newline-delimited stdin, like the classic dmenu:
bash
echo -e 'option 1\noption 2\noption 3' | vicinae dmenu --placeholder "Select option"
vicinae dmenu --placeholder "Pick file" < options.txt
Script commands
Any executable script becomes a command via three header directives (Raycast-compatible). Drop scripts in ~/.local/share/vicinae/scripts:
python
#!/usr/bin/env python3
# @vicinae.schemaVersion 1
# @vicinae.title My Script
# @vicinae.mode fullOutput
# @vicinae.argument1 { "type": "text", "placeholder": "name" }
print("Hello world!")
mode can be fullOutput, compact, or silent. Optional directives: @vicinae.icon, @vicinae.argument{1..3} (up to 3), @vicinae.exec (custom command line, no executable bit needed), @vicinae.keywords, @vicinae.description. Scaffold with vicinae script template --title "My Script" --lang=python.
TypeScript extensions
Full React/TypeScript extensions using the @vicinae/api package — declarative components that rerender on state change, with all Node APIs available. The API closely mirrors Raycast's, so many Raycast extensions work, and Vicinae integrates both the Vicinae store and the Raycast store.
tsx
import { ActionPanel, Action, List } from "@vicinae/api";
export default function FruitList() {
return (
<List searchBarPlaceholder="Search fruits...">
<List.Item
title="Apple"
icon="🍎"
actions={
<ActionPanel>
<Action.CopyToClipboard title="Copy emoji" content="🍎" />
</ActionPanel>
}
/>
</List>
);
}
Scaffold with the in-app "Create Extension" command, then npm install and npm run dev (with the server running) for live development.
Theming
Themes are TOML files (since v0.15.0) supporting inheritance, hot reload, and color manipulation. Every theme inherits from a base (vicinae-dark / vicinae-light), so you only override what changes.
toml
[meta]
version = 1
name = "My Custom Theme"
variant = "dark"
inherits = "vicinae-dark"
[colors.core]
background = "#1E1E2E"
foreground = "#CDD6F4"
accent = "#89B4FA"
bash
vicinae theme template > ~/.local/share/vicinae/themes/my-theme.toml
vicinae theme set my-theme # theme id = filename without .toml
Integrates with matugen to generate themes from your wallpaper for a system-wide cohesive palette.