- fzf for fuzzy search.
- kitty terminal(optional) for displaying app icons.
-
You can download the precompiled binary of Jiffy from the GitHub Releases page.
-
Move the binary to a directory included in your system's
PATH
(e.g.,/usr/local/bin
or~/bin
). -
After installing the binary, you can run jiffy from your terminal.
- Install QuickJs compiler
git clone --depth 1 https://github.com/bellard/quickjs.git && cd quickjs && make && sudo make install &&
- Get the Jiffy's source code and compile.
git clone --depth 1 https://github.com/5hubham5ingh/jiffy.git && git clone --depth 1 https://github.com/5hubham5ingh/justjs.git && git clone --depth 1 https://github.com/ctn-malone/qjs-ext-lib.git && cd jiffy && qjsc -flto main.js -o jiffy && sudo mv jiffy /usr/bin/
- Install QuickJs compiler
Jiffy allows you to define custom menus in menu.jsonc
and menu.js
files. These file should be
in your ~/.config/jiffy/
directory. The menu follows the JSON format.
1. menu.jsonc
This example defines a "Power Menu" with shutdown, reboot, and sleep options.
The exec
field specifies the command to run, and the description
gives a
brief explanation of each option.
2. menu.js
function getMenu() {
return {
"Hypr Windows": focusWindows(),
"Hypr keybinds": hyprKeyBinds(),
};
}
const hyprState = JSON.parse(await execAsync("hyprctl -j clients"));
function focusWindows() {
return hyprState.map((window) => ({
name: window.class,
description: window.title.replace("#", "_"), // replacing # as it is the internal delimeter for fzf
exec: `hyprctl dispatch focuswindow address:${window.address}`,
}));
}
const hyprBinds = JSON.parse(await execAsync("hyprctl -j binds"));
function hyprKeyBinds() {
const mods = generateModMaskMap();
return hyprBinds.map((keyBind) => ({
name: `${
(mods[keyBind.modmask] ?? [])?.join(" + ").concat(" ")
}${keyBind.key}`,
description: `${keyBind.description}`,
exec: `${keyBind.dispatcher} ${keyBind.arg}`,
}));
function generateModMaskMap() {
const modMaskMap = {};
function parseModMask(modmask) {
const modifiers = [];
if (modmask & 1) modifiers.push("SHIFT");
if (modmask & 4) modifiers.push("CTRL");
if (modmask & 8) modifiers.push("ALT");
if (modmask & 64) modifiers.push("SUPER");
return modifiers;
}
const validModifiers = [1, 4, 8, 64]; // Individual modifiers
let validMasks = [0];
for (const mod of validModifiers) {
const newMasks = [];
for (const mask of validMasks) {
newMasks.push(mask | mod); // Combine with existing masks
}
validMasks = [...validMasks, ...newMasks];
}
validMasks = validMasks.filter((mask) => mask !== 0);
for (const mask of validMasks) {
modMaskMap[mask] = parseModMask(mask).reverse();
}
return modMaskMap;
}
}
export default getMenu();
This example defines a dynamically generated menu for switching focus to another opened window and browse all key bind of Hyprland
.
You can launch Jiffy by running the following command:
jiffy [ARG] ...
-
Hide prompt and app's category:
jiffy --fzf-args='--prompt=" "' -c
-
Hide app description and refresh app's list:
jiffy --fzf-args="--preview-window=0" --no-cache
-
Change UI preset and inject custom JS:
jiffy -p 2 -i 'OS.exec(["kitty", "@", "set-spacing", "margin=0"])'
Run jiffy --help
to see more options.
You can switch between any modes or UI presets using following shotcut keys-
Shortcut | Action |
---|---|
shift+tab | Change UI preset |
tab | Change mode |
mainMod+space | Refresh application list for launcher |
mainMod+k | Show all keybinds |
- icons for custom command, UI should adjust if there is no icons in the menu
Feel free to contribute or open issues if you encounter any problems or have suggestions for new features.