skim
A fuzzy finder written in Rust — a faster, feature-rich alternative to fzf with a built-in TUI, multi-selection, and preview support.
skim (invoked as sk) is a fuzzy finder for the terminal written in Rust. It
fills the same role as fzf — pipe any list of items into it and interactively
filter down to a selection — but is implemented entirely in Rust, supports
multi-line items, and has a built-in preview window with syntax highlighting
when paired with bat.
Features
- Fuzzy matching — type any substring of an item and skim filters the list in real time
- Multi-select — press
Tabto mark multiple items and pass them all to the output - Preview window — show a preview of the selected item (e.g. file contents
via
bat) in a split pane - Interactive mode — optionally run a command for each keystroke, enabling dynamic search over external data sources
fzf-compatible — supports most offzf's command-line flags andFZF_DEFAULT_OPTS-style environment variables, making it a drop-in replacement in most scripts- Regex or fuzzy — toggle between fuzzy matching and exact regex matching at runtime
- Colour themes — fully configurable colours via command-line flags or environment variables
- Library API — can be used as a Rust library (
skimcrate) to embed fuzzy finding in your own applications
Installation
cargo install skim
Or via your system package manager:
# macOS
brew install skim
# Debian / Ubuntu (Debian 12+)
apt install skim
# Fedora
dnf install skim
# Arch Linux
pacman -S skim
# Nix
nix-env -iA nixpkgs.skimUsage
# Fuzzy-find a file in the current directory tree
sk --ansi -c 'fd --type f'
# Pipe any list into skim
ls | sk
# Multi-select files and open them in your editor
vim $(fd -e rs | sk -m)
# With a preview window showing file contents
sk --preview 'bat --color=always {}'
# Fuzzy search git log
git log --oneline | sk
# Interactively search command history
history | sk
# Use as a directory changer
cd $(fd --type d | sk)Shell integrations
Ctrl+R history search
Add to your shell config to replace the default history search:
# bash (~/.bashrc)
export SKIM_DEFAULT_OPTIONS="--reverse --height 40%"
source "$(sk --bash)"
# zsh (~/.zshrc)
source "$(sk --zsh)"
# fish (~/.config/fish/config.fish)
sk --fish | sourceCtrl+T file picker
# Insert a selected file path at the cursor
# Enabled automatically by the shell integration aboveAlt+C directory jumper
# cd into a selected directory
# Also enabled by the shell integrationKey bindings
| Key | Action |
|---|---|
| Type | Filter the list |
↑ / ↓ or Ctrl+p / Ctrl+n | Move up / down |
Tab | Toggle selection (multi-select mode) |
Shift+Tab | Deselect item |
Enter | Accept selection |
Esc / Ctrl+c | Cancel |
Ctrl+a | Select all |
Ctrl+d | Deselect all |
? | Toggle preview window |
Configuration
Set defaults via the SKIM_DEFAULT_OPTIONS environment variable:
export SKIM_DEFAULT_OPTIONS="
--reverse
--height 50%
--preview 'bat --style=numbers --color=always {}'
--preview-window right:60%
--bind 'ctrl-f:page-down,ctrl-b:page-up'
"Interactive mode
The -i / --interactive flag reruns a command for every keystroke, enabling
dynamic external search:
# Search files using ripgrep interactively as you type
sk -i -c 'rg --color=always --line-number "{}"' \
--ansi \
--preview 'bat --color=always $(echo {} | cut -d: -f1)'As a Rust library
cargo add skimuse skim::prelude::*;
use std::io::Cursor;
let options = SkimOptionsBuilder::default()
.height(Some("50%"))
.multi(true)
.build()
.unwrap();
let input = "item1\nitem2\nitem3".to_string();
let item_reader = SkimItemReader::default();
let items = item_reader.of_bufread(Cursor::new(input));
let selected = Skim::run_with(&options, Some(items))
.map(|out| out.selected_items)
.unwrap_or_default();
for item in selected {
println!("{}", item.output());
}