CLI and Node.js helpers for interactive fzf multi-select flows that need:
- preselected values on startup
- preselected values moved to the top
- a simple command instead of hand-assembling
fzfflags every time
The package is intentionally small. It focuses on a polished multi-select UX for both library and CLI usage.
Keys and labels must be unique, must not contain carriage returns or newlines, and must not contain the active delimiter string. The library throws a descriptive error when that contract is violated.
npm install fzf-selectfzf itself must also be installed and available in PATH.
Library usage:
import { promptFzfMultiSelect } from "fzf-select";
const items = [
{ id: "ts", label: "TypeScript" },
{ id: "go", label: "Go" },
{ id: "py", label: "Python" }
];
const selected = promptFzfMultiSelect({
items,
selectedKeys: ["ts", "py"],
prompt: "stack> ",
header: "Tab toggles selection. Enter confirms.",
getKey: (item) => item.id,
getLabel: (item) => item.label
});
console.log(selected);CLI usage:
fzf-select \
--items 'TypeScript,Go,Python,Rust' \
--selected-keys 'TypeScript, Python' \
--prompt 'stack> ' \
--header 'Tab toggles selection. Enter confirms.'Or with files:
fzf-select \
--items-file ./items.json \
--selected-file ./selected.json \
--prompt 'stack> ' \
--header 'Tab toggles selection. Enter confirms.'You can also pass inline JSON:
fzf-select \
--items-json '[{"id":"ts","label":"TypeScript"},{"id":"go","label":"Go"},{"id":"py","label":"Python"}]' \
--selected-keys ts,py \
--prompt 'stack> ' \
--header 'Tab toggles selection. Enter confirms.'By default the command prints the selected items as formatted JSON.
--items: comma-separated plain items where each value is both key and label--items-json: inline JSON array of items--items-file: path to JSON file with an array of items--selected-keys: comma-separated keys that start selected and sorted to the top--selected-file: path to JSON file with an array of selected keys--key-field: object field used as stable key, defaultid--label-field: object field used as visible label, defaultlabel--prompt,--header,--height:fzfpresentation settings--output:json,keys, orlabels
--selected-keys trims incidental spaces around comma-separated values. If a key must keep leading or trailing spaces exactly, use --selected-file.
Return selected object rows:
fzf-select --items-json '[{"id":"ts","label":"TypeScript"},{"id":"go","label":"Go"}]'Read items from a file:
fzf-select --items-file ./items.json --selected-file ./selected.jsonReturn only keys:
fzf-select \
--items-json '[{"id":"ts","label":"TypeScript"},{"id":"go","label":"Go"}]' \
--output keysUse plain string items instead of objects:
fzf-select --items-json '["TypeScript","Go","Python"]' --selected-keys PythonUse the short plain-items mode:
fzf-select --items 'TypeScript,Go,Python' --selected-keys 'TypeScript, Python'The core value here is not just wrapping fzf, but preserving a specific UX in a reusable CLI:
- known selections are visible immediately
- known selections are already toggled on
- the list starts with the most likely choices
That makes repeated interactive flows much faster in real CLI tools.
npm test
npm run check