sk(1)

๐Ÿ“ฆ
version 5.9.0 ยท 5 versions
, in arch rolling

๐Ÿ’… sk(1) โ€” Fuzzy Finder in rust! ๐Ÿฆ‹

okay so like, welcome to the sk page, bestie โ€” it's from the General Commands Manual and honestly it's giving main character energy from the very first line. โœจ We're gonna walk through the whole thing together, no cap, every single flag included. Buckle up. ๐ŸŽ€


๐ŸŒธ NAME ๐ŸŒธ

sk โ€” Fuzzy Finder in rust! ๐Ÿฆ€โœจ


๐ŸŒˆ SYNOPSIS ๐ŸŒˆ

okay so this is the big vibe-check wall of options. Don't panic, it's literally just every flag the thing accepts, laid out exactly like this:

sk [--tac] [--min-query-length] [--no-sort] [-t|--tiebreak] [-n|--nth]
[--with-nth] [--hide-nth] [-d|--delimiter] [-e|--exact] [--regex]
[--algo] [--case] [--typos] [--no-typos] [--normalize] [--split-match]
[--last-match] [--scheme] [-b|--bind] [-m|--multi] [--no-multi]
[--no-mouse] [-c|--cmd] [-i|--interactive] [-I ] [--color]
[--highlight-line] [--no-hscroll] [--keep-right] [--skip-to-pattern]
[--no-clear-if-empty] [--no-clear-start] [--no-clear] [--show-cmd-error]
[--cycle] [--disabled] [--disable-pattern] [--layout] [--reverse]
[--height] [--no-height] [--min-height] [--margin] [-p|--prompt]
[--cmd-prompt] [--selector] [--multi-selector] [--ansi] [--tabstop]
[--info] [--no-info] [--inline-info] [--header] [--header-lines]
[--separator] [--no-separator] [--border] [--border-no-collapse]
[--no-border] [--wrap] [--multiline] [--scrollbar] [--no-scrollbar]
[--history] [--history-size] [--cmd-history] [--cmd-history-size]
[--preview] [--preview-window] [--image] [-q|--query] [--cmd-query]
[--read0] [--print0] [--print-query] [--print-cmd] [--print-score]
[--print-header] [--print-current] [--output-format] [--no-strip-ansi]
[-1|--select-1] [-0|--exit-0] [--sync] [--pre-select-n]
[--pre-select-pat] [--pre-select-items] [--pre-select-file]
[-f|--filter] [--shell] [--shell-bindings] [--man] [--listen] [--remote]
[--popup] [--popup-name] [--log-level] [--log-file] [--expect]
[-h|--help] [-V|--version]

(yes, [-I ] really does have a space in it, that's not a typo, that's just how it is ๐Ÿ’€)


โœจ OPTIONS โœจ

these are the base-level, everyone-gets-them options. short and sweet, like a good coffee order. โ˜•

  • -h, --help โ€” prints the help text. and heads up: it goes "see a summary with -h", so if you want the short version you already know where to look ๐Ÿ‘€
  • -V, --version โ€” prints the version. that's it. that's the whole job. iconic behavior. ๐Ÿ‘‘

the part where sk actually finds stuff. this is the whole reason we're here, bestie. let's get into it. ๐Ÿ’…

  • --tac โ€” shows results in reverse order. ๐Ÿ”

ngl this one is often used in combination with --no-sort. they're like a package deal.

  • --min-query-length <MIN_QUERY_LENGTH> โ€” the minimum query length before it starts showing results. โณ

so like, it only shows results when your query is at least this many characters long. and in interactive mode with --cmd, it also waits before running the command. under --disabled it has no effect at all โ€” literally does nothing there, so don't bother. ๐Ÿ™ˆ

  • --no-sort โ€” does not sort the results. chaotic, but valid. ๐ŸŒ€

often used in combination with --tac. example time, keep this exactly:

history | sk --tac --no-sort
  • -t, --tiebreak <TIEBREAK> [default: score,begin,end] โ€” a comma-separated list of sort criteria to apply when the scores are tied. ๐Ÿค

think of it as the tiebreaker round in a beauty pageant. here's the criteria:

  • score: the score from the fuzzy match algorithm.
    • each criterion could be negated, e.g. (-index)
    • each criterion should appear only once in the list โ€” no duplicates, that's not the vibe ๐Ÿšซ

possible values:

  • score
  • -score
  • begin
  • -begin
  • end
  • -end
  • length
  • -length
  • index
  • -index
  • pathname
  • -pathname
  • -n, --nth <NTH> [default: ] โ€” which fields get matched. ๐ŸŽฏ

a field index expression can be a non-zero integer or a range expression ([BEGIN]..[END]). and --nth and --with-nth both take a comma-separated list of field index expressions. slay, very flexible.

examples:

1      The 1st field
2      The 2nd field
-1     The last field
-2     The 2nd to last field
3..5   From the 3rd field to the 5th field
2..    From the 2nd field to the last field
..-3   From the 1st field to the 3rd to the last field
..     All the fields
  • --with-nth <WITH_NTH> [default: ] โ€” fields to be transformed. ๐Ÿช„

see nth for the details, it's the same energy, just for transforming.

  • --hide-nth <HIDE_NTH> [default: ] โ€” fields to hide from the display while keeping them searchable. ๐Ÿซฃ

it takes the same comma-separated field index expressions as nth. the listed fields get removed from the displayed line but they remain part of the text used for matching โ€” so a query can still match them. characters in the hidden fields are ignored for match highlighting and horizontal scrolling. sneaky AND useful, we love that.

see nth for the field index expression syntax.

  • -d, --delimiter <DELIMITER> [default: [\t\n ]+] โ€” the delimiter between fields. โœ‚๏ธ

it's in regex format, and it defaults to AWK-style. escape sequences like \x00, \t, \n are supported. fancy. ๐Ÿ’…

  • -e, --exact โ€” runs in exact mode. no fuzzy, no vibes, just exact. ๐ŸŽฏ
  • --regex โ€” starts in regex mode instead of fuzzy-match. for the regex girlies. ๐ŸŒธ
  • --algo <ALGORITHM> [default: arinae] โ€” which fuzzy matching algorithm to use. ๐Ÿง 
    • arinae (ari): latest algorithm
    • skim_v2: legacy skim algorithm
    • clangd: used in clangd for keyword completion
    • fzy: algorithm from fzy (<https://github.com/jhawthorn/fzy>)
    • frizbee: algorithm used in the blink.cmp neovim plugin

possible values:

  • arinae: Arinae: typo-resistant & natural algorithm, default
  • clangd: Clangd fuzzy matching algorithm
  • fzy: Fzy matching algorithm (https://github.com/jhawthorn/fzy)
  • frizbee: Frizbee matching algorithm, typo resistant
  • skim_v2: Previous skim fuzzy matching algorithm (v2)
  • --case <CASE> [default: smart] โ€” case sensitivity. ๐Ÿ” 

determines whether or not to ignore case while matching. note: this is not used for the Frizbee matcher, which uses a penalty system to favor case-sensitivity without enforcing it. so like, frizbee plays by its own rules, respect it.

possible values:

  • respect: case-sensitive matching
  • ignore: case-insensitive matching
  • smart: smart case: case-insensitive unless query contains uppercase
  • --typos [<TYPOS>] [default: disabled] โ€” enables typo-tolerant matching. ๐Ÿซถ

when passed without a value (--typos), it uses the adaptive formula (pattern_length / 4). when passed with a value (e.g. --typos=2), it uses that exact number as the maximum allowed typos. and --typos=0 explicitly disables typo tolerance. applies to both the fzy and frizbee matchers. we love a forgiving queen. ๐Ÿ˜Œ

  • --no-typos โ€” disables typo-tolerant matching. back to strict mode, bestie. ๐Ÿšซ
  • --normalize โ€” normalizes unicode characters. ๐ŸŒ

when set, it normalizes accents and other unicode diacritics/others. so รฉ and e can finally be friends.

  • --split-match [<SPLIT_MATCH>...] โ€” enables split matching and sets the delimiter. โœ‚๏ธ

split matching runs the matcher in splits: foo:bar will match all items matching foo, then :, then bar if the delimiter is present โ€” or match normally if it's not. lowkey genius.

  • --last-match โ€” highlights the last match found, not the first one. ๐Ÿ”š

this makes tiebreak more pertinent on path items where we want to prioritize a match on the last parts. path girlies, this one's for you. ๐Ÿ›ค๏ธ

  • --scheme <SCHEME> [default: default] โ€” the search scheme. ๐ŸŽจ

possible values:

  • default: default scheme, no modifications to the options
  • path: path scheme: will find the furthest match in the item and set pathname as the main tiebreak
  • history: history scheme: will force index as the first tiebreak

๐ŸŽ€ a few more things about --bind ๐ŸŽ€

Multiple actions can be chained using + separator.

Example: sk --bind 'ctrl-a:select-all+accept'

Special behaviors โœจ

With the execute(...) and reload(...) actions, you can execute arbitrary commands without leaving sk. For example, you can turn sk into a simple file browser by binding the enter key to the less command like this:

sk --bind "enter:execute(less {})"

Note: if no argument is supplied to reload, the default command is run.

You can use the same placeholder expressions as in --preview.

sk switches to the alternate screen when executing a command. However, if the command is expected to complete quickly, and you aren't interested in its output, you might want to use execute-silent instead โ€” it silently executes the command without the switching. Note that sk will not be responsive until the command is complete. For asynchronous execution, start your command as a background process (i.e. appending &). ๐Ÿ‘€

With the if-query-empty and if-query-not-empty actions, you can specify which action to execute depending on the query condition. For example:

sk --bind 'ctrl-d:if-query-empty(abort)+delete-char'

If the query is empty, skim will execute abort, otherwise it executes delete-char. It's equal to 'delete-char/eof'. slay ๐Ÿ’…

  • -m, --multi โ€” turn on multiple selection, bestie. Uses Tab and S-Tab for selection by default.
  • --no-multi โ€” nope, no multiple selection, we're doing one thing at a time ๐Ÿซถ
  • --no-mouse โ€” mouse? off. gone. not invited to the party ๐Ÿ™ˆ
  • -c, --cmd <CMD> โ€” the command to invoke dynamically in interactive mode. It gets invoked using sh -c on Unix-like systems and cmd /c on Windows.
  • -i, --interactive โ€” start skim in interactive mode. In interactive mode, sk will run the command specified by the --cmd option and display the results. ๐Ÿ”ฅ
  • -I <REPLSTR> โ€” replace replstr with the selected item in commands. [default: {}]
  • --color <COLOR> โ€” set the color theme, aesthetic queen ๐ŸŽ€ Format: [BASE][,COLOR:ANSI[:ATTR1:ATTR2:..]] โ€” see the [THEME] section for details. Repeated --color options are merged in order, so a later value overrides an earlier one for the same element.
  • --highlight-line โ€” highlight the entire current line, not just the text. the whole vibe, not just the words โœจ
  • --no-hscroll โ€” disable horizontal scroll
  • --keep-right โ€” keep the right end of the line visible on overflow. Effective only when the query string is empty.
  • --skip-to-pattern <SKIP_TO_PATTERN> โ€” show the matched pattern at the line start. The line will start with the start of the matched pattern. Effective only when the query string is empty. Was designed to skip showing starts of paths of rg/grep results. e.g. sk -i -c "rg {q} --color=always" --skip-to-pattern '[^/]*:' --ansi
  • --no-clear-if-empty โ€” don't clear the previous line if the command returns an empty result. Don't clear previous items if a new command returns an empty result. This might be useful to reduce flickering when you're typing new commands and the half-complete commands aren't valid. It's not the default behavior because similar use cases for grep and rg have already been optimized, where empty query results actually mean "empty" and previous results should be cleared.
  • --no-clear-start โ€” don't clear items on start
  • --no-clear โ€” don't clear the screen on exit. Don't clear the finder interface on exit either. If skim was started in full screen mode, it will not switch back to the original screen, so you'll have to manually run tput rmcup to return. This option can be used to avoid flickering of the screen when your application needs to start skim multiple times in order. ๐Ÿ˜ญ careful with this one
  • --show-cmd-error โ€” show an error message if the command fails ๐Ÿ’€
  • --cycle โ€” cycle the results by wrapping around when scrolling ๐Ÿ”
  • --disabled โ€” disable matching entirely
  • --disable-pattern <DISABLE_PATTERN> โ€” disable items based on this regex pattern

๐Ÿฆ‹ LAYOUT ๐Ÿฆ‹

  • --layout <LAYOUT> โ€” set the layout. [default: default] Possible values:
    • default: display from the bottom of the screen
    • reverse: display from the top of the screen
    • reverse-list: display from the top of the screen, prompt at the bottom
  • --reverse โ€” shorthand for reverse layout, iykyk
  • --height <HEIGHT> โ€” height of skim's window. [default: 100%] Can either be a row count or a percentage. A negative row count will use term height - value as the height.
  • --no-height โ€” disable height (force full screen), main character energy ๐Ÿ‘‘
  • --min-height <MIN_HEIGHT> โ€” minimum height of skim's window as a non-negative row count. [default: 10] Must be a non-negative row count, not a percentage. Useful when the height is set as a percentage. Ignored when --height is not specified.
  • --margin <MARGIN> โ€” screen margin. [default: 0] For each side, it can be either a row count or a percentage of the terminal size. Format can be one of:
    • TRBL
    • TB,RL
    • T,RL,B
    • T,R,B,L

Example: 1,10%

  • -p, --prompt <PROMPT> โ€” set the prompt. [default: > ] ๐Ÿ’–
  • --cmd-prompt <CMD_PROMPT> โ€” set the prompt in command mode. [default: c> ]
  • --selector <SELECTOR_ICON> โ€” set the selected item icon. [default: >]
  • --multi-selector <MULTI_SELECT_ICON> โ€” set the multi-selected item icon. [default: >] ๐Ÿซถ

โœจ DISPLAY โœจ

  • --ansi โ€” bestie, this one parses the ANSI color codes straight out of your input strings ๐ŸŒˆ

Ok but heads up โ€” when you're using skim as a library, this flag does literally nothing ๐Ÿ˜ญ you gotta enable ansi parsing manually by injecting a cmd_collector like this:

use skim::prelude::*;

let _options = SkimOptionsBuilder::default()
  .cmd("ls --color")
  .cmd_collector(Rc::new(RefCell::new(SkimItemReader::new(
    SkimItemReaderOption::default().ansi(true),
    ))) as Rc<RefCell<dyn CommandCollector>>)
  .build()
  .unwrap();
  • --tabstop <TABSTOP> [default: 8] โ€” how many spaces make up one tab ๐Ÿซถ
  • --info <INFO> [default: default] โ€” where the matching-result count shows up ๐Ÿ’…
    • hidden โ€” do not display info at all, gone, invisible
    • inline[:SEP] โ€” display info in the same row as the input, with an optional non-default separator
    • default โ€” display info in a dedicated row above the input
    • left โ€” display all info left-aligned in a dedicated row above the input
    • right โ€” display all info right-aligned in a dedicated row above the input
    • inline-right[:SEP] โ€” display info right-aligned in the same row as the input, with an optional non-default separator
  • --no-info โ€” alias for --info=hidden ๐Ÿ™ˆ
  • --inline-info โ€” alias for --info=inline โœจ
  • --header <HEADER> โ€” set the header, displayed next to the info ๐Ÿ‘‘

The string you give gets printed as the sticky header. The lines show up in the order you gave them, top to bottom, no matter what the --layout option says, and they're not affected by --with-nth. Also, ANSI color codes get processed here even when --ansi is not set โ€” periodt.

  • --header-lines <HEADER_LINES> [default: 0] โ€” how many lines of the input get treated as header ๐ŸŽ€

The first N lines of your input become the sticky header. And when --with-nth is set, those lines get transformed exactly like all the other lines that follow.

  • --separator <SEPARATOR> โ€” draw a repeating horizontal separator on the status line ๐Ÿฆ‹

With inline info, it follows the status on the prompt line. With inline-right or hidden info, it occupies a separate line. Disabled by default, and an empty string also disables it. An enabled border row gets reused where possible.

  • --no-separator โ€” disable the horizontal separator, bye ๐Ÿ‘‹
  • --border [<BORDER>...] [default: none] โ€” draw borders around the UI components, it's giving framed ๐Ÿ–ผ๏ธ

Possible values:

  • force-off: ForceOff disables borders around popups too, set with no_border
  • none
  • plain
  • rounded
  • double
  • thick
  • light-double-dashed
  • heavy-double-dashed
  • light-triple-dashed
  • heavy-triple-dashed
  • light-quadruple-dashed
  • heavy-quadruple-dashed
  • quadrant-inside
  • quadrant-outside
  • --border-no-collapse โ€” do not collapse adjacent borders into a shared row or column ๐Ÿšซ
  • --no-border โ€” disables all borders, including in tmux/zellij popups ๐Ÿ’€
  • --wrap โ€” wrap items in the item list ๐ŸŽ
  • --multiline [<MULTILINE>] โ€” split item text into multiple display lines at the given separator character; defaults to \n if read0 is set, and \\n if not (matching literal \n in text) ๐Ÿงš

Each item's text gets split on the separator, and each part is displayed as its own separate line within that item's row. It's giving multi-line main character energy.

  • --scrollbar <THUMB> [default: โ–] โ€” set the scrollbar style for the item list ๐ŸŒธ

The optional value is what's used as the indicator.

  • --no-scrollbar โ€” disable the scrollbar in the item list, minimalism slay โœจ
  • --popup [<POPUP>...] โ€” run in a tmux or zellij popup, pop off queen ๐Ÿ‘‘

Format: sk --popup <center|top|bottom|left|right>[,SIZE[%]][,SIZE[%]]

Note: this will try to detect a Zellij session, then a Tmux session. Which means that in nested sessions, skim prioritizes Zellij over Tmux.

The popup pane is named after --popup-name (default: skim).

  • --popup-name <POPUP_NAME> โ€” name of the popup pane (Zellij) / title of the popup (tmux) ๐Ÿท๏ธ

Only used with --popup. Defaults to skim in Zellij; tmux popups get no title unless this is set. Oh and --border-label is accepted as an fzf-compatible alias, iykyk.


๐Ÿ•ฐ๏ธ HISTORY ๐Ÿ•ฐ๏ธ

  • --history <HISTORY_FILE> โ€” history file, bestie ๐Ÿ“–

Loads search history from the specified file and updates that file on completion.

When enabled, CTRL+N and CTRL+P are automatically remapped to next-history and previous-history.

  • --history-size <HISTORY_SIZE> [default: 1000] โ€” maximum number of query history entries to keep ๐Ÿ“
  • --cmd-history <CMD_HISTORY_FILE> โ€” command history file ๐Ÿ“œ

Loads command query history from the specified file and updates that file on completion.

When enabled, CTRL+N and CTRL+P are automatically remapped to next-history and previous-history (yes, same deal as above, it's that iconic).

  • --cmd-history-size <CMD_HISTORY_SIZE> [default: 1000] โ€” maximum number of query history entries to keep ๐Ÿ’œ

๐Ÿ‘€ PREVIEW ๐Ÿ‘€

  • --preview <PREVIEW> โ€” preview command, the moment you've all been waiting for ๐ŸŽฌ

Executes the given command with sh -c on linux and cmd /c on windows for the current line, and displays the result on the preview window. {} in the command is the placeholder that gets replaced with the single-quoted string of the current line. To transform the replacement string, specify field index expressions between the braces (see FIELD INDEX EXPRESSION for the deets).

Examples:

sk --preview='head -$LINES {}'
ls -l | sk --preview="echo user={3} when={-4..-2}; cat {-1}" --header-lines=1
  • --preview-window <PREVIEW_WINDOW> [default: right:50%] โ€” preview window layout ๐ŸชŸ

Format: [up|down|left|right][:SIZE][:hidden][:[no]wrap][:[no]pty][:+SCROLL[-OFFSET]]

Determines the layout of the preview window. If the argument ends with :hidden, the preview window will be hidden by default until the toggle-preview action is triggered. Long lines are truncated by default. Line wrap can be enabled with the :wrap flag. For more interactive commands, or previews that draw complex interfaces, the preview can use a PTY with the :pty flag.

Note: the preview will run in a PTY (interactive session) on Linux and when wrap is unset.

SIZE can be either:

  • 0, which will hide the preview window
  • A positive size (eg 20)
  • A percentage of the total size (eg 50%)
  • A negative size, which will set the size of everything but the preview to that value

+SCROLL[-OFFSET] determines the initial scroll offset of the preview window. SCROLL can be either a numeric integer or a single-field index expression that refers to a numeric integer. The optional -OFFSET part is for adjusting the base offset so you can see the text above it. It should be given as a numeric integer (-INTEGER), or as a denominator form (-/INTEGER) for specifying a fraction of the preview window height.

Examples:

# Non-default scroll window positions and sizes
sk --preview="head {}" --preview-window=up:30%
sk --preview="file {}" --preview-window=down:2

# Initial scroll offset is set to the line number of each line of
# git grep output *minus* 5 lines (-5)
git grep --line-number '' |
  sk --delimiter:  --preview 'nl {1}' --preview-window +{2}-5

# Preview with bat, matching line in the middle of the window (-/2)
git grep --line-number '' |
  sk --delimiter : \
      --preview 'bat --style=numbers --color=always --highlight-line {2} {1}' \
      --preview-window +{2}-/2
  • --image [<IMAGE>...] โ€” enable image preview, we're visual now ๐Ÿ–ผ๏ธโœจ

This renders the preview argument as an image instead of running it as a command.

If set to detect, or if no value is passed, it will try to detect the available image backends at startup โ€” which adds a small delay before the first render. If set to halfblocks, it will always use the halfblocks rendering method.

Note: the backend detection will not work when piping data into skim. Use SKIM_DEFAULT_COMMAND="find . -type f" sk --image instead of find . -type f | sk --image โ€” no cap, that's the move.

Possible values:

  • detect: Default โ€” automatically detect the available backend at startup
  • halfblocks: Force halfblocks if you want blurry previews but a faster startup, or if the detection fails

๐Ÿ’… SCRIPTING โœจ

okay so this is the stash of flags you reach for when you're scripting sk instead of just vibing in the TUI ๐Ÿซถ

  • -q, --query <QUERY> โ€” the initial query, bestie. the thing that's already typed in when sk opens ๐Ÿ‘‘
  • --cmd-query <CMD_QUERY> โ€” the initial query, but for interactive mode specifically ๐Ÿ’ซ
  • --read0 โ€” read the input delimited by ASCII NUL(\0) characters ๐Ÿซง
  • --print0 โ€” print the output delimited by ASCII NUL(\0) characters ๐Ÿ’€
  • --print-query โ€” print the query as the first line ๐Ÿ“
  • --print-cmd โ€” print the command as the first line (after print-query) ๐ŸŽ€
  • --print-score โ€” print the score after each item ๐Ÿ”ฅ
  • --print-header โ€” print the header as the first line (after print-score) ๐ŸŒธ
  • --print-current โ€” print the current (highlighted) item as the first line (after print-header) โญ
  • --output-format <OUTPUT_FORMAT> โ€” set the output format. If set, it overrides all print_ options. It gets expanded the same way as preview or commands โœจ
  • --no-strip-ansi โ€” print the ANSI codes, making the output exactly match the input even when --ansi is on ๐ŸŒˆ
  • -1, --select-1 โ€” do NOT enter the TUI if the query passed in -q matches only one item, just return it ๐ŸŽฏ
  • -0, --exit-0 โ€” do NOT enter the TUI if the query passed in -q doesn't match any item ๐Ÿ™ˆ
  • --sync โ€” synchronous search for multi-staged filtering. If you specify it, skim will launch the TUI finder only after the input stream is complete. e.g. sk --multi | sk --sync ๐Ÿฆ‹
  • --pre-select-n <PRE_SELECT_N> [default: 0] โ€” pre-select the first n items in multi-selection mode ๐Ÿ’œ
  • --pre-select-pat <PRE_SELECT_PAT> [default: ] โ€” pre-select the matched items in multi-selection mode. check the doc for the detailed syntax: https://docs.rs/regex/1.4.1/regex/ ๐Ÿงš
  • --pre-select-items <PRE_SELECT_ITEMS> [default: ] โ€” pre-select the items separated by newline character. Example: 'item1\nitem2' ๐Ÿ“
  • --pre-select-file <PRE_SELECT_FILE> โ€” pre-select the items read from this file ๐ŸŽ€
  • -f, --filter <FILTER> โ€” the query for filter mode ๐Ÿ”
  • --shell <SHELL> โ€” generate a shell completion script. Generates the completion script for the specified shell: bash, zsh, fish, etc. The output can be directly sourced or saved to a file for automatic loading. Examples: source <(sk --shell bash) (immediate use), sk --shell bash >> ~/.bash_completion (persistent use). Supported shells: bash, zsh, fish, powershell, elvish. Possible values are:
    • bash โ€” Bourne Again SHell
    • elvish โ€” Elvish shell
    • fish โ€” Friendly Interactive SHell
    • nushell โ€” Nushell (nu)
    • power-shell โ€” PowerShell
    • zsh โ€” Zsh
  • --shell-bindings โ€” generate shell key bindings โ€” only for bash, zsh and fish. Generates the key bindings script after the shell completions. see the --shell option for more details ๐Ÿ’ซ
  • --man โ€” generate the man page and output it to stdout ๐Ÿ“– (yes, sk can print its own man page, main character energy fr)
  • --listen [<LISTEN>...] โ€” run an IPC socket with an optional name (defaults to sk). The socket expects Actions in Ron format (similar to Rust code), see ./src/tui/event.rs for all possible Actions. To write to it, see the --remote option or the man page ๐Ÿ›ฐ๏ธ
  • --remote [<REMOTE>...] โ€” send commands to an IPC socket with an optional name (defaults to sk). The commands are read from stdin, one per line, in the same format as the actions in the bind flag. They can also be chained using + as a separator. All other arguments will be ignored ๐Ÿ“ก
  • --log-level <LOG_LEVEL> โ€” set the log level ๐ŸŽš๏ธ
  • --log-file <LOG_FILE> โ€” pipe log output to a file ๐Ÿ—‚๏ธ

๐ŸŒˆ DEPRECATED ๐Ÿซ 

  • --expect <EXPECT> [default: ] โ€” deprecated, kept for compatibility purposes. See accept() bind instead โœจ
lowkey do not use this one for new stuff, it's literally just vibing here so old configs don't break ๐Ÿ’€

๐Ÿ‘‘ MODES ๐Ÿ’…

Normal mode

In normal mode, sk reads the input from stdin and displays the results interactively, and the query is then used to fuzzily filter among the input lines. classic. iconic. the standard ๐ŸŽ€

Interactive mode

Interactive mode is a special mode that lets you run a command interactively and display the results. It's enabled by the --interactive (or -i) option, or by binding the toggle-interactive action (default: Ctrl+q). The command is specified with the --cmd option ๐Ÿฆ‹

Example: sk --cmd 'rg {} --color=always' --interactive will use rg to search for the query in the current directory and display the results interactively โœจ


๐Ÿ” SEARCH ๐ŸŒธ

By default, skim will start in extended search, giving some characters meaning. Example: ^test rs$ | sh$ will match items starting with test and ending with rs or sh ๐Ÿ’–

AND (space)

A space between terms acts as an 'and' operator and filters for items matching all the terms ๐Ÿค

OR (|)

A vertical bar between terms acts as an 'or' operator and filters for items matching one of the terms ๐ŸŒˆ

Exact match (')

If a term is prefixed by a ', sk will search for exact occurrences of that term. Exact search can be enabled by default with the --exact command-line flag. In exact mode, ' will disable exact matching for that term ๐ŸŽฏ

Anchored match (^|$)

If a term is prefixed by a ^ (resp. suffixed by a $), sk will search for matches starting (resp. ending) with that exact term โš“

Negation (!)

If a term is prefixed by !, sk will exclude the items that match this term ๐Ÿšซ

โœจ KEYBINDS โœจ

okay bestie, this is where skim becomes yours. You set bindings with the --bind option, which takes a comma-separated list of <trigger>:<action>[+action2] expressions. A trigger can be a key, a finder event, or an action name. Actions can take arguments, and you can write those either between parentheses like reload(ls) or after a colon like reload:ls. Both are valid, no cap. ๐Ÿ’…

๐Ÿ”‘ Available keys (aliases in parentheses)

hereโ€™s the whole key roster, literally every one:

  • ctrl-[a-z]
  • ctrl-space
  • ctrl-alt-[a-z]
  • alt-[a-zA-Z]
  • alt-[0-9]
  • f[1-12]
  • enter
  • space
  • bspace (bs)
  • alt-up
  • alt-down
  • alt-left
  • alt-right
  • alt-enter
  • alt-space
  • alt-bspace (alt-bs)
  • alt-/
  • tab
  • btab (shift-tab)
  • esc
  • del
  • up
  • down
  • left
  • right
  • home
  • end
  • pgup
  • pgdn
  • shift-up
  • shift-down
  • shift-left
  • shift-right
  • alt-shift-up
  • alt-shift-down
  • alt-shift-left
  • alt-shift-right
  • double-click
  • any single character

๐Ÿ›Ž๏ธ Bindable finder events

these are the finder moments skim can react to, and yes they all slap:

  • change: the query changes
  • start: skim enters its event loop; fired once
  • load: the reader and matcher finish consuming the current input; fired once per read, including reloads
  • result: filtering for the current query completes
  • focus: the focused item changes because of cursor movement or a result update
  • zero: the input stream is complete and the final search has no matches
  • one: the input stream is complete and the final search has exactly one match

๐ŸŽฌ Actions as binding triggers

Actions can also be used as binding triggers. A follow-up chain bound to an action name runs immediately after that action. Use the act- prefix for action triggers; it is recommended to avoid ambiguity and required when the action name is also a key, for example act-up:last.

Follow-up chains use non-recursive (noremap) semantics: their actions do not trigger further action bindings. Add suppress to skip the triggering action's default behavior, for example act-up:suppress+down. that little detail is lowkey important, so donโ€™t skip it. ๐Ÿซถ

๐Ÿ’ซ Actions

hereโ€™s the action buffet โ€” every single one, no skips:

  • abort โ€” Abort and exit with error
  • accept(...) โ€” Accept selection and exit with optional key. The argument is printed when the binding is triggered.
  • add-char(...) โ€” Add a character to the query
  • append-and-select โ€” Append to selection and select
  • backward-char โ€” Move cursor backward one character
  • backward-delete-char โ€” Delete character before cursor
  • backward-delete-char/eof โ€” Delete character before cursor or exit if the query is empty
  • backward-kill-word โ€” Delete word before cursor
  • backward-word โ€” Move cursor backward one word
  • beginning-of-line โ€” Move cursor to beginning of line
  • bind(...) โ€” Bind one or more keys to action chains. The argument is a comma-separated list of trigger:action[+action] bindings to add, using the same syntax as --bind, including action triggers such as act-up:last.
  • cancel โ€” Cancel current operation
  • clear-screen โ€” Clear the screen
  • delete-char โ€” Delete character under cursor
  • delete-char/eof โ€” Delete character or exit if empty
  • deselect-all โ€” Deselect all items
  • down(...) โ€” Move selection down by N items
  • end-of-line โ€” Move cursor to end of line
  • execute(...) โ€” Execute a command. The argument is a command, see COMMAND EXPANSION for details.
  • execute-silent(...) โ€” Execute a command silently. The argument is a command, see COMMAND EXPANSION for details.
  • first โ€” Jump to first item in list
  • forward-char โ€” Move cursor forward one character
  • forward-word โ€” Move cursor forward one word
  • if-query-empty(...) โ€” Execute action if query is empty
  • if-query-not-empty(...) โ€” Execute action if query is not empty
  • if-non-matched(...) โ€” Execute action if no items match
  • ignore โ€” Ignore the action
  • kill-line โ€” Delete from cursor to end of line
  • kill-word โ€” Delete word after cursor
  • last โ€” Jump to last item in list
  • next-history โ€” Move to next history entry (requires --history or --cmd-history)
  • half-page-down(...) โ€” Scroll down by half a page
  • half-page-up(...) โ€” Scroll up by half a page
  • page-down(...) โ€” Scroll down by a page
  • page-up(...) โ€” Scroll up by a page
  • preview-up(...) โ€” Scroll preview up
  • preview-down(...) โ€” Scroll preview down
  • preview-left(...) โ€” Scroll preview left
  • preview-right(...) โ€” Scroll preview right
  • preview-page-up(...) โ€” Scroll preview up by a page
  • preview-page-down(...) โ€” Scroll preview down by a page
  • previous-history โ€” Move to previous history entry (requires --history or --cmd-history)
  • redraw โ€” Redraw the screen
  • refresh-cmd โ€” Refresh the command
  • refresh-preview โ€” Refresh the preview
  • restart-matcher โ€” Restart the matcher
  • reload(...) โ€” Reload with optional new command
  • rotate-mode โ€” Rotate through matching modes
  • scroll-left(...) โ€” Scroll item list left
  • scroll-right(...) โ€” Scroll item list right
  • select-all โ€” Select all items
  • select-row(...) โ€” Select a specific row
  • select โ€” Select current item
  • suppress โ€” Suppress the default behaviour of the action this is bound to. Only meaningful as a follow-up bound to an action (e.g. act-up:suppress): it cancels that action's own effect, so the remaining follow-up chain runs in its place. On its own it is a no-op (equivalent to ignore).
  • set-cmd(...) โ€” Set the interactive-mode command and rerun it. The argument is an expanded expression, see COMMAND EXPANSION for details.
  • set-header(...) โ€” Set the header (or disable it on an empty value)
  • set-preview-cmd(...) โ€” Set the preview cmd and rerun preview. The argument is an expanded expression, see COMMAND EXPANSION for details.
  • set-query(...) โ€” Set the query to the expanded value. The argument is an expanded expression, see COMMAND EXPANSION for details.
  • toggle โ€” Toggle selection of current item
  • toggle-all โ€” Toggle selection of all items
  • toggle-in โ€” Toggle and move in
  • toggle-interactive โ€” Toggle interactive mode
  • toggle-out โ€” Toggle and move out
  • toggle-preview โ€” Toggle preview visibility
  • toggle-preview-wrap โ€” Toggle preview line wrapping
  • toggle-sort โ€” Toggle sorting
  • top โ€” Jump to first item in list (alias for First)
  • unbind(...) โ€” Unbind one or more keys. The argument is a comma-separated list of keys or action triggers (e.g. act-up) to unbind.
  • unix-line-discard โ€” Discard line (unix-style)
  • unix-word-rubout โ€” Delete word backward (unix-style)
  • up(...) โ€” Move selection up by N items
  • yank โ€” Yank (paste)

๐ŸŽ€ Default key bindings

out of the box, these are already wired up bestie:

  • alt-b โ€” backward-word
  • alt-bspace โ€” backward-kill-word
  • alt-d โ€” kill-word
  • alt-f โ€” forward-word
  • alt-h โ€” scroll-left
  • alt-l โ€” scroll-right
  • bspace โ€” backward-delete-char
  • btab โ€” toggle+up
  • ctrl-a โ€” beginning-of-line
  • ctrl-b โ€” backward-char
  • ctrl-c โ€” abort
  • ctrl-d โ€” abort
  • ctrl-e โ€” end-of-line
  • ctrl-f โ€” forward-char
  • ctrl-g โ€” abort
  • ctrl-h โ€” backward-delete-char
  • ctrl-j โ€” down
  • ctrl-k โ€” up
  • ctrl-l โ€” clear-screen
  • ctrl-left โ€” backward-word
  • ctrl-n โ€” down
  • ctrl-p โ€” up
  • ctrl-q โ€” toggle-interactive
  • ctrl-r โ€” rotate-mode
  • ctrl-right โ€” forward-word
  • ctrl-u โ€” unix-line-discard
  • ctrl-w โ€” unix-word-rubout
  • ctrl-y โ€” yank
  • del โ€” delete-char
  • double-click โ€” accept
  • down โ€” down
  • end โ€” end-of-line
  • enter โ€” accept
  • esc โ€” abort
  • home โ€” beginning-of-line
  • left โ€” backward-char
  • pgdn โ€” page-down
  • pgup โ€” page-up
  • right โ€” forward-char
  • shift-btab โ€” toggle+up
  • shift-down โ€” preview-down
  • shift-home โ€” beginning-of-line
  • shift-left โ€” backward-word
  • shift-right โ€” forward-word
  • shift-tab โ€” toggle+up
  • shift-up โ€” preview-up
  • tab โ€” toggle+down
  • up โ€” up

๐ŸŒˆ COMMAND EXPANSION

In the preview flag, execute, reload, set-query... binds, sk will expand placeholders. this is the secret sauce, bestie:

  • {} (or --replstr if used) will be expanded to the current item.
  • {q} (or {cq} for legacy reasons) will be expanded to the current query input.
  • {+} will be expanded to either the currently selected items in multi-select mode, or the current item in single-select.
  • {n} will be expanded to the index of the current item.
  • {+n} will be expanded to the index(es) of the corresponding {+} item(s).
  • {FIELD_INDEX_EXPRESSION} will be expanded to the field index expression run against the current item.
  • {+FIELD_INDEX_EXPRESSION} will be expanded to the field index expression run against the {+} item(s).

๐Ÿงฎ Field index expression

skim will expand some expressions between {..}. It will expand to the corresponding fields, separated by the --delimiter|-d option (see there for details). yes, this is giving โ€œtiny language inside your pickerโ€:

  • {n} will be the n-th field.
  • {n..m} will be the fields from n to m, inclusive, separated by a space
  • {-n} will be the n-th, starting from the end, -1 will be the last field etc.

๐ŸŒฑ ENVIRONMENT VARIABLES

๐Ÿ“ SKIM_DEFAULT_COMMAND

If set, skim will collect items with this command if no input is piped in. If not set, defaults to find . on unix-like systems and dir /s /b /A:-D on Windows. noted, bestie โ€” those defaults are exact. โœจ

๐ŸŒธ SKIM_DEFAULT_OPTIONS

Will be parsed and used as default options. Example: --reverse --multi

๐ŸŽ€ SKIM_OPTIONS_FILE

If the variable is set to the path of an existing file, the contents of this file will be parsed and used as default options. It supports # as a comment start, which can be escaped using ##. Example:

# Preview
--preview 'echo {}'
--preview-window 'left:30%' # Preview window
--reverse
--prompt '## '

๐Ÿฆ‹ NO_COLOR

If set to a non-empty value, will disable coloring. no color, no problem ๐Ÿ’…

๐ŸŽจ THEME ๐ŸŽจ

ok so you can ~theme~ this whole thing, and here's the whole menu, bestie:

  • none โ€” the base color scheme, plain and simple
  • molokai โ€” molokai 256color
  • light โ€” light 256color
  • 16 โ€” dark base16 theme
  • bw โ€” black & white theme, for the minimalists ๐Ÿ’…
  • dark | default โ€” dark 256color, and yes this is the default value
  • all 4 catppuccin variants โ€” the whole collection, we love a theme family:
    • catppuccin-latte
    • catppuccin-macchiato
    • catppuccin-frappe
    • catppuccin-mocha

๐ŸŒˆ the color names you can use

these are the little keywords that say what you're coloring:

  • normal (or an empty string) โ€” normal text
  • matched (or hl) โ€” matched text, the stuff you searched for
  • current (or fg+) โ€” current line foreground
  • bg+ โ€” current line background (special case: it always sets background, no notes)
  • current_match (or hl+) โ€” matched text in the current line
  • query โ€” query text
  • spinner โ€” spinner character
  • info โ€” info text (the match count)
  • prompt โ€” prompt text
  • cursor (or pointer) โ€” cursor/pointer, main character energy
  • selected (or marker) โ€” selected item marker
  • header โ€” header text
  • border โ€” border lines
  • separator โ€” the horizontal separator (independent of borders and headers, she does her own thing)
  • scrollbar โ€” item list scrollbar thumb

๐Ÿ–Œ๏ธ picking the part

adding -fg, _fg, -bg, _bg, -underline, _underline sets the corresponding part of the color. for instance, normal-fg (or simply fg) will set the foreground normal color. easy.

๐ŸŽฏ color formats

  • 0-255 โ€” ANSI terminal color
  • #rrggbb โ€” 24-bit color, fancy

โœจ attrs

  • x | regular โ€” resets the modifiers, use it before the others (order matters bestie, do it first)
  • b | bold
  • u | underline
  • c | crossed-out
  • d | dim
  • i | italic
  • r | reverse

๐Ÿ“ the example, look at her go

--color '16,normal-fg:0+bold,matched-fg:#ffffff+u,cursor-bg:#deadbe'

this will start with the base 16 theme and override it with a bold ANSI color 0 foreground (black), a hex ffffff (full white) underlined foreground for matched parts and a #deadbe (pale rose, apparently ๐ŸŽ€) cursor background. iconic behavior, no notes.

๐Ÿ“ก LISTEN/REMOTE ๐Ÿ“ก

skim can be controlled from other processes, using the --listen (and optionally --remote) flags. yes she's remote-controllable, she's that girl.

to achieve this, run the server instance using sk --listen optional_address (the address defaults to sk). it will then start listening on a named socket for instructions.

to send instructions, you can use sk --remote optional_address or any other tool that allows us to interact with such sockets, such as socat on linux:

echo 'ToggleIn' | socat -u STDIN ABSTRACT-CONNECT:optional_address

instructions correspond to skim's Actions and need to be sent in Ron format. when using sk --remote, pipe in action chains (see the KEYBINDS section), for instance:

echo 'up+select-row' | sk --remote optional_address

๐Ÿšช EXIT CODES ๐Ÿšช

  • 0 โ€” success slay ๐Ÿ’–
  • 1 โ€” no match
  • 130 โ€” interrupt (ctrl-c or esc)
  • others โ€” error ๐Ÿ˜ญ

๐Ÿท๏ธ VERSION ๐Ÿท๏ธ

v5.9.0


and that's the whole page babes ๐Ÿซถ โ€” this was sk 5.9.0, page sk(1), delivered fresh from that exact source and version. go forth and fuzzy-find something gorgeous โœจ๐Ÿ’…

๐Ÿ“ฆ where this page comes from