Fuzzy a general fuzzy finder that saves you time in rust!

Overview

Crates.io Build & Test

Life is short, skim!

Half of our life is spent on navigation: files, lines, commands… You need skim! It is a general fuzzy finder that saves you time.

skim demo

skim provides a single executable: sk. Basically anywhere you would want to use grep, try sk instead.

Table of contents

Installation

The skim project contains several components:

  1. sk executable -- the core.
  2. sk-tmux -- script for launching sk in a tmux pane.
  3. Vim/Nvim plugin -- to call sk inside Vim/Nvim. check skim.vim for more Vim support.

Package Managers

Distribution Package Manager Command
macOS Homebrew brew install sk
macOS MacPorts sudo port install skim
Fedora dnf dnf install skim
Alpine apk apk add skim
Arch pacman pacman -S skim

Install as Vim plugin

Via vim-plug (recommended):

Plug 'lotabout/skim', { 'dir': '~/.skim', 'do': './install' }

Hard Core

Any of the following applies:

  • Using Git
    $ git clone --depth 1 [email protected]:lotabout/skim.git ~/.skim
    $ ~/.skim/install
  • Using Binary: directly download the sk executable.
  • Install from crates.io: cargo install skim
  • Build Manually
    $ git clone --depth 1 [email protected]:lotabout/skim.git ~/.skim
    $ cd ~/.skim
    $ cargo install
    $ cargo build --release
    $ # put the resulting `target/release/sk` executable on your PATH.

Usage

skim can be used as a general filter (like grep) or as an interactive interface for invoking commands.

As filter

Try the following

# directly invoke skim
sk

# or pipe some input to it: (press TAB key select multiple items with -m enabled)
vim $(find . -name "*.rs" | sk -m)

The above command will allow you to select files with ".rs" extension and open the ones you selected in Vim.

As Interactive Interface

skim can invoke other commands dynamically. Normally you would want to integrate it with grep, ack, ag, or rg for searching contents in a project directory:

# works with grep
sk --ansi -i -c 'grep -rI --color=always --line-number "{}" .'
# works with ack
sk --ansi -i -c 'ack --color "{}"'
# works with ag
sk --ansi -i -c 'ag --color "{}"'
# works with rg
sk --ansi -i -c 'rg --color=always --line-number "{}"'

interactive mode demo

Key Bindings

Some commonly used key bindings:

Key Action
Enter Accept (select current one and quit)
ESC/Ctrl-G Abort
Ctrl-P/Up Move cursor up
Ctrl-N/Down Move cursor Down
TAB Toggle selection and move down (with -m)
Shift-TAB Toggle selection and move up (with -m)

For full list of key bindings, check out the man page (man sk).

Search Syntax

skim borrowed fzf's syntax for matching items:

Token Match type Description
text fuzzy-match items that match text
^music prefix-exact-match items that start with music
.mp3$ suffix-exact-match items that end with .mp3
'wild exact-match (quoted) items that include wild
!fire inverse-exact-match items that do not include fire
!.mp3$ inverse-suffix-exact-match items that do not end with .mp3

skim also supports the combination of tokens.

  • Whitespace has the meaning of AND. With the term src main, skim will search for items that match both src and main.
  • | means OR (note the spaces around |). With the term .md$ | .markdown$, skim will search for items ends with either .md or .markdown.
  • OR has higher precedence. So readme .md$ | .markdown$ is grouped into readme AND (.md$ OR .markdown$).

In case that you want to use regular expressions, skim provides regex mode:

sk --regex

You can switch to regex mode dynamically by pressing Ctrl-R (Rotate Mode).

exit code

Exit Code Meaning
0 Exit normally
1 No Match found
130 Abort by Ctrl-C/Ctrl-G/ESC/etc...

Customization

The doc here is only a preview, please check the man page (man sk) for a full list of options.

Keymap

Specify the bindings with comma separated pairs (no space allowed), example:

sk --bind 'alt-a:select-all,alt-d:deselect-all'

Additionally, use + to concatenate actions, such as execute-silent(echo {} | pbcopy)+abort.

See the KEY BINDINGS section of the man page for details.

Sort Criteria

There are five sort keys for results: score, index, begin, end, length, you can specify how the records are sorted by sk --tiebreak score,index,-begin or any other order you want.

Color Scheme

It is a high chance that you are a better artist than me. Luckily you won't be stuck with the default colors, skim supports customization of the color scheme.

--color=[BASE_SCHEME][,COLOR:ANSI]

The configuration of colors starts with the name of the base color scheme, followed by custom color mappings. For example:

sk --color=current_bg:24
sk --color=light,fg:232,bg:255,current_bg:116,info:27

See --color option in the man page for details.

Misc

  • --ansi: to parse ANSI color codes (e.g., \e[32mABC) of the data source
  • --regex: use the query as regular expression to match the data source

Advanced Topics

Interactive mode

With "interactive mode", you could invoke command dynamically. Try out:

sk --ansi -i -c 'rg --color=always --line-number "{}"'

How it works?

skim's interactive mode

  • Skim could accept two kinds of source: command output or piped input
  • Skim has two kinds of prompts: A query prompt to specify the query pattern and a command prompt to specify the "arguments" of the command
  • -c is used to specify the command to execute while defaults to SKIM_DEFAULT_COMMAND
  • -i is to tell skim open command prompt on startup, which will show c> by default.

If you want to further narrow down the results returned by the command, press Ctrl-Q to toggle interactive mode.

Executing external programs

You can set up key bindings for starting external processes without leaving skim (execute, execute-silent).

# Press F1 to open the file with less without leaving skim
# Press CTRL-Y to copy the line to clipboard and aborts skim (requires pbcopy)
sk --bind 'f1:execute(less -f {}),ctrl-y:execute-silent(echo {} | pbcopy)+abort'

Preview Window

This is a great feature of fzf that skim borrows. For example, we use 'ag' to find the matched lines, once we narrow down to the target lines, we want to finally decide which lines to pick by checking the context around the line. grep and ag has an option --context, skim can do better with preview window. For example:

sk --ansi -i -c 'ag --color "{}"' --preview "preview.sh {}"

(Note the preview.sh is a script to print the context given filename:lines:columns) You got things like this:

preview demo

How does it work?

If the preview command is given by the --preview option, skim will replace the {} with the current highlighted line surrounded by single quotes, call the command to get the output, and print the output on the preview window.

Sometimes you don't need the whole line for invoking the command. In this case you can use {}, {1..}, {..3} or {1..5} to select the fields. The syntax is explained in the section "Fields Support".

Last, you might want to configure the position of preview windows, use --preview-window.

  • --preview-window up:30% to put the window in the up position with height 30% of the total height of skim.
  • --preview-window left:10:wrap, to specify the wrap allows the preview window to wrap the output of the preview command.
  • --preview-window wrap:hidden to hide the preview window at startup, later it can be shown by the action toggle-preview.

Fields support

Normally only plugin users need to understand this.

For example, you have the data source with the format:

<filename>:<line number>:<column number>

However, you want to search only when typing in queries. That means when you type 21, you want to find a that contains 21, but not matching line number or column number.

You can use sk --delimiter ':' --nth 1 to achieve this.

Also you can use --with-nth to re-arrange the order of fields.

Range Syntax

  • -- to specify the num-th fields, starting with 1.
  • start.. -- starting from the start-th fields, and the rest.
  • ..end -- starting from the 0-th field, all the way to end-th field, including end.
  • start..end -- starting from start-th field, all the way to end-th field, including end.

Use as a library

Skim can be used as a library in your Rust crates.

First, add skim into your Cargo.toml:

[dependencies]
skim = "*"

Then try to run this simple example:

` by default let item_reader = SkimItemReader::default(); let items = item_reader.of_bufread(Cursor::new(input)); // `run_with` would read and show items from the stream let selected_items = Skim::run_with(&options, Some(items)) .map(|out| out.selected_items) .unwrap_or_else(|| Vec::new()); for item in selected_items.iter() { print!("{}{}", item.output(), "\n"); } } ">
extern crate skim;
use skim::prelude::*;
use std::io::Cursor;

pub fn main() {
    let options = SkimOptionsBuilder::default()
        .height(Some("50%"))
        .multi(true)
        .build()
        .unwrap();

    let input = "aaaaa\nbbbb\nccc".to_string();

    // `SkimItemReader` is a helper to turn any `BufRead` into a stream of `SkimItem`
    // `SkimItem` was implemented for `AsRef` by default
    let item_reader = SkimItemReader::default();
    let items = item_reader.of_bufread(Cursor::new(input));

    // `run_with` would read and show items from the stream
    let selected_items = Skim::run_with(&options, Some(items))
        .map(|out| out.selected_items)
        .unwrap_or_else(|| Vec::new());

    for item in selected_items.iter() {
        print!("{}{}", item.output(), "\n");
    }
}

Given an Option, skim will read items accordingly, do its job and bring us back the user selection including the selected items, the query, etc. Note that:

  • SkimItemReceiver is crossbeam::channel::Receiver>
  • If it is none, it will invoke the given command and read items from command output
  • Otherwise, it will read the items from the (crossbeam) channel.

Trait SkimItem is provided to customize how a line could be displayed, compared and previewed. It is implemented by default for AsRef

Plus, SkimItemReader is a helper to convert a BufRead into SkimItemReceiver (we can easily turn a File for String into BufRead). So that you could deal with strings or files easily.

Check more examples under examples/ directory.

FAQ

How to ignore files?

Skim invokes find . to fetch a list of files for filtering. You can override that by setting the environment variable SKIM_DEFAULT_COMMAND. For example:

$ SKIM_DEFAULT_COMMAND="fd --type f || git ls-tree -r --name-only HEAD || rg --files || find ."
$ sk

You could put it in your .bashrc or .zshrc if you like it to be default.

Some files are not shown in Vim plugin

If you use the Vim plugin and execute the :SK command, you might find some of your files not shown.

As described in #3, in the Vim plugin, SKIM_DEFAULT_COMMAND is set to the command by default:

let $SKIM_DEFAULT_COMMAND = "git ls-tree -r --name-only HEAD || rg --files || ag -l -g \"\" || find ."

That means, the files not recognized by git will not shown. Either override the default with let $SKIM_DEFAULT_COMMAND = '' or find the missing file by yourself.

Differences to fzf

fzf is a command-line fuzzy finder written in Go and skim tries to implement a new one in Rust!

This project is written from scratch. Some decisions of implementation are different from fzf. For example:

  1. skim is a binary as well as a library while fzf is only a binary.
  2. skim has an interactive mode.
  3. skim supports pre-selection
  4. The fuzzy search algorithm is different.
  5. UI of showing matched items. fzf will show only the range matched while skim will show each character matched. (fzf has this now)
  6. skim's range syntax is Git style: now it is the same with fzf.

How to contribute

Create new issues if you meet any bugs or have any ideas. Pull requests are warmly welcomed.

Comments
  • `sk` suddenly stop working (no response)

    `sk` suddenly stop working (no response)

    Hi, I am a big fan of Rust and has since moved to sk from fzf. Thanks for the great work.

    Before updating 0.8.1, sk was working fine at all. After updating, all of a sudden it just stops working. sk does not have any response. I use fzf side-by-side with sk and fzf is still working as normal.

    Using pacman. I removed skim. Reinstall it. Issue persists.

    # Start cleanly
    bash --noprofile --norc
    
    fzf
    # working normally
    
    sk
    # no response
    sk
    # no response
    sk
    # no response
    
    echo $?
    # 101
    sk --version
    # 0.8.1
    sk --help
    # Usage: sk [options]
    #   Options
    #     -h, --help           print this help menu
    #     --version [...]
    # [truncated ..............................................]
    
    cat /etc/os-release
    #    1 NAME="Arch Linux"
    #    2 PRETTY_NAME="Arch Linux"
    #    3 ID=arch
    #    4 BUILD_ID=rolling
    #    5 ANSI_COLOR="0;36"
    #    6 HOME_URL="https://www.archlinux.org/"
    #    7 DOCUMENTATION_URL="https://wiki.archlinux.org/"
    #    8 SUPPORT_URL="https://bbs.archlinux.org/"
    #    9 BUG_REPORT_URL="https://bugs.archlinux.org/"
    #   10 LOGO=archlinux
    
    
    bug 
    opened by JodyStats 23
  • 'abort' doesn't abort all the time

    'abort' doesn't abort all the time

    When running find|sk --bind 'enter:execute(echo {})+abort', skim doesn't always abort.

    That is, the selection is printed, then a newline. But the caret stays on an empty line below, skim keeps running, and hitting enter again doesn't get us back to the shell. Typing ctrl-c is needed to end the program.

    Tested on Ubuntu 19.04 running konsole, bash 5.0.3 and skim 0.7.0.

    cannot-reproduce 
    opened by ngirard 12
  • Reuse as a library?

    Reuse as a library?

    I'd like to reuse skim inside my own application. With this, I mean reusing skim as a library. Inside my code, I'd like to pass Skim my sources, hand over control to skim which runs its CLI and once the user selects something, returns the selected items back to me. Mainly these are the features I'd like to have:

    • fuzzy finding, including interactivity and options (multi, non-multi).
    • providing my own input source, while decoupling the text that is shown to the user from what I get returned.

    A possible API could be this:

    /// Defined by skim.
    pub trait SkimItem: Send {
       /// The text displayed to the user.
       fn display(&self) -> Cow<&str>;
    }
    
    struct MyItem {
       .... many interesting fields.
    }
    
    impl SkimItem for MyItem {...}
    
    let (tx, rx) = channel::<MyItem>();
    // Launch a thread, send MyItems as they are generated into `tx`.
    let mut skim = Skim::with_sender(rx, SkimOptionsBuilder::new().multi_select(true).ignore_case(true));
    let result = skim.query_user();  // Consumes `sk`.
    
    /// Join the producing thread. `result` is now either an Err or a Vec<SkimItem>, so I know what was selected.
    

    I looked through the code and it seemed like this was not very easy to do right now, since the clap::ArgMatches is passed around instead of option structs and the UI and filtering code is a bit interleaved. Do you think this is a feasible feature request?

    opened by SirVer 12
  • Ignoring files

    Ignoring files

    It would be nice to be able to ignore certain files (e.g., dotfiles). It would be really nice if fzf-rs could read .gitignore etc (like ack, ag, and friends).

    opened by Stebalien 9
  • [ Fedora ] Error: Unable to find a match: skim

    [ Fedora ] Error: Unable to find a match: skim

    ❯ sudo dnf install skim
    Last metadata expiration check: 4:59:00 ago on Wed 24 Jun 2020 17:13:12 +0530.
    No match for argument: skim
    Error: Unable to find a match: skim
    
    opened by kaushalyap 8
  • Exact matching mode without case sensitivity?

    Exact matching mode without case sensitivity?

    It seems the fuzzy matching mode is always case insensitive, and the exact matching mode is always case sensitive.

    However, is there any way to get the contiguous matching mode that exact provides (i.e. match whole words) while not having to also match the case? In other words, is it possible to set exact mode to case insensitivity, or smart-case?

    For explanation: My use case is full-text searching my notes (with rg) and then searching over the output with skim. Matching the output with the fuzzy matcher mostly shows completely unrelated notes, and exact matching shows the perfect answers except for always having to search for the right case.

    opened by marty-oehme 8
  • [Library] nth option is broken?

    [Library] nth option is broken?

    examples/nth.rs:

    extern crate skim;
    use skim::prelude::*;
    use std::io::Cursor;
    
    pub fn main() {
        let input = "foo 123";
    
        let options = SkimOptionsBuilder::default()
            .nth(Some("2"))
            .query(Some("f"))
            .build()
            .unwrap();
        let item_reader = SkimItemReader::default();
    
        dbg!(options.nth);
    
        let items = item_reader.of_bufread(Cursor::new(input));
        let selected_items = Skim::run_with(&options, Some(items))
            .map(|out| out.selected_items)
            .unwrap_or_else(|| Vec::new());
    
        for item in selected_items.iter() {
            print!("{}{}", item.output(), "\n");
        }
    }
    
    cargo run --example nth
    

    It generates a match foo 123 although it shouldn't match anything (2nd field consists of numbers, we match on a letter). Am I doing anything wrong?

    skim in terminal works as expected

    > echo "foo 123" | sk --nth=1 --filter f
    foo 123
    > echo "foo 123" | sk --nth=2 --filter f
    # no output, exit code 1
    
    opened by murlakatamenka 7
  • skim panic - attempt to unwrap None value

    skim panic - attempt to unwrap None value

    Using a function like this and selecting some process (just tried random until it broke) as skims' selection produces a panic:

    $ fkill
    thread '<unnamed>' panicked at 'called `Option::unwrap()` on a `None` value', 27
    
    function fkill -d 'fuzzy kill processes'
      ps -ef | sed 1d | sk --multi
    end
    
    cannot-reproduce 
    opened by bryaan 7
  • Integration with `ripgrep` not working

    Integration with `ripgrep` not working

    I have sk 0.9.1 and rg 12.1.1 installed, both via cargo-install. Both sk and rg are in my path, and they work well independently. But I cannot integrate them with sk --ansi -i -c 'rg --color=always --line-number "{}"'. Nevertheless, sk is working with grep. ( I don't have ag or ack so I cannot test these ).

    opened by lebensterben 6
  • Skim not working properly with ansi input

    Skim not working properly with ansi input

    Using:

    fd --color always | sk --ansi
    

    Displays most colors, but not for current-directory files seemingly, whereas

    fd --color always | fzf --ansi
    

    Does what I expect. I'm not sure exactly where this issue is, but I'm noticing it now using this as my default file finder over fzf.

    opened by johnpyp 6
  • Support tiebreak based on length of original text.

    Support tiebreak based on length of original text.

    Hi @lotabout thanks for skim I'm enjoying it.

    One thing I have wished for is tiebreaking based on the length of the original text, in my case shorter strings are preferred. This lets me select longer strings by continuing to type in Vim rather than use the arrow keys I have included an example below of the default behaviour of skim. In this example lets say we are selecting the build_script_mod directory by typing mod.

    Before, just sk: Screen Shot 2019-09-23 at 10 57 20 pm

    After, running sk --tiebreak=score,length: Screen Shot 2019-09-23 at 11 09 17 pm

    This may accidentally help with https://github.com/lotabout/skim/issues/213.

    opened by aldhsu 6
  • No more executables in releases?

    No more executables in releases?

    In the README, it says in installation section that one can head to releases to get ready executables. I went there and there's only zipped source code.

    I scrolled down and it seems that back in the day, exe used to come with releases but not any more, can we have them again please?

    opened by thisismygitrepo 0
  • Implement fzf's --info option

    Implement fzf's --info option

    I use sk as a drop-in replacement for fzf. It worked fine until recently I use zoxide's interactive mode 'zi'. It relies on 'fzf --info' option to work. It would be great to have both rust applications works together.

    opened by zou000 0
  • Performance improvements: `sk` now comparable to `fzf`

    Performance improvements: `sk` now comparable to `fzf`

    Benchmark 1: sk --query=hopscotchbubble -e --exit-0 < ../countwords/kjvbible_x10.txt
      Time (mean ± σ):     115.2 ms ±   0.6 ms    [User: 247.2 ms, System: 36.0 ms]
      Range (min … max):   113.6 ms … 116.4 ms    25 runs
    
    ...
    
    Benchmark 2: fzf --query=hopscotchbubble -e --exit-0 < ../countwords/kjvbible_x10.txt
      Time (mean ± σ):     119.9 ms ±   6.9 ms    [User: 230.1 ms, System: 63.0 ms]
      Range (min … max):    93.6 ms … 124.4 ms    25 runs
    
    ...
    
    Summary
      'sk --query=hopscotchbubble -e --exit-0 < ../countwords/kjvbible_x10.txt' ran
        1.04 ± 0.06 times faster than 'fzf --query=hopscotchbubble -e --exit-0 < ../countwords/kjvbible_x10.txt'
    

    I've made some improvements to sk so its baseline performance (--exact matching) is now comparable to/better than fzf on the M1 for larger inputs (and less than 5% on Intel). sk still lags way behind in fuzzy searches (10%-20% more wall clock time and 2x CPU time).

    We also now use less memory than fzf.

    I was also able to effectively end the sometimes laggy inputs on searches on over ~200,000 items by moving the matcher to its own thread pool. This is most important to me as now sk is a usable as a daily driver.

    And I'm pretty certain I haven't made any breaking changes to the public API.

    If anyone is interested, I will merge these changes back into skim. But as it is -- it seems interest is waning -- I may consider a hard fork under a new name.

    Crazy respect for how fast fzf is. My guess is two things make fzf still very fast at fuzzy matching on large inputs: 1) as much as it pains me to say, golang is better at/easier for at this type of concurrency than rayon/crossbeam, and 2) the fzf fuzzy algo is amazing (but also may be "cheating"/bailing out somehow on large inputs?).

    My question is -- does anyone want to continue, or should I try a fork?

    opened by kimono-koans 0
  • support : in filenames

    support : in filenames

    Hi,

    Is there any chance to support : in filenames? Having a bunch of files like form:blabla.ini . Field matching chokes on that, because of the : in the filename. execute-silent also chokes (for me) with

    --bind 'ctrl-l:execute-silent(/opt/sublime_text/sublime_text {..2}),f3:execute-silent(/opt/sublime_text/sublime_text {..2}),f4:execute(komodo {1}#{2})'
    

    Do I miss something?

    opened by agroszer 0
Releases(v0.10.2)
Owner
Jinzhou Zhang
A Program is a Process, Not a Thing
Jinzhou Zhang
Fzf - A command-line fuzzy finder

fzf is a general-purpose command-line fuzzy finder. It's an interactive Unix filter for command-line that can be used with any list; files, command hi

Junegunn Choi 49.1k Jan 8, 2023
A simple, modern fuzzy finder tool to run examples in a Cargo project.

cargo-rx cargo-rx is a simple, modern Runner for Examples in a Cargo project. This crate provides a single executable: rx. Basically anywhere you woul

Ritvik Nag 14 Dec 2, 2022
Deadliner helps you keep track of the time left for your deadline by dynamically updating the wallpaper of your desktop with the time left.

Deadliner Watch the YouTube video What's Deadliner? Deadliner is a cross-platform desktop application for setting deadline for a project and keeping t

Deadliner 34 Dec 16, 2022
Helps you keep track of time for team members across different time zones & DST changes

Teamdate Helps you keep track of time for team members across different timezones and other daylight saving changes based off their location. Because

Alex Snaps 7 Jan 9, 2023
General Rust Actix Applications and AWS Programming Utilities

RUST Actix-Web Microservice Our Rust Beginners Kit for Application Development A collection of sample code using the actix rust framework to A) Develo

IntelliConnect Technologies 58 Nov 21, 2022
General purpose memory allocator written in Rust.

Memalloc Memory allocator written in Rust. It implements std::alloc::Allocator and std::alloc::GlobalAlloc traits. All memory is requested from the ke

Antonio Sarosi 35 Dec 25, 2022
A simplified general-purpose queueing system for Rust apps.

A simplified general-purpose queueing system for Rust apps. Example // Create a new Redeez object, and define your queues let mut queues = Redeez::new

Miguel Piedrafita 11 Jan 16, 2023
Umpteen is a general-purpose programming language currently in active development being bootstrapped from Rust

The Umpteen Programming Language This repository provides the reference implementation for the Umpteen Programming Language, bootstrapped from Rust. U

Katie Janzen 4 Nov 20, 2023
General purpose cross-platform GIS-rendering library written in Rust

Galileo is a general purpose cross-platform geo-rendering library. Web examples Raster tile layer (OSM) Vector tile layer (Maplibre) Use buttons at th

Maxim 16 Dec 15, 2023
A general-purpose, transactional, relational database that uses Datalog and focuses on graph data and algorithms

cozo A general-purpose, transactional, relational database that uses Datalog for query and focuses on graph data and algorithms. Features Relational d

null 1.9k Jan 9, 2023
A general purpose Lisp🛸 intended for use as Sage's preprocessor language

sage-lisp This crate implements a standalone Lisp implementation, intended for use in the Sage preprocessor. (do (defun fact (n) (if (<=

adam mcdaniel 3 Apr 10, 2024
Fuzzy Index for Python, written in Rust. Works like error-tolerant dict, keyed by a human input.

FuzzDex FuzzDex is a fast Python library, written in Rust. It implements an in-memory fuzzy index that works like an error-tolerant dictionary keyed b

Tomasz bla Fortuna 8 Dec 15, 2022
A multi-page fuzzy launcher for your terminal, written in Rust.

fr33zmenu A multi-page fuzzy launcher for your terminal, written in Rust. Supports theming and multiple keybind schemes, including basic vim keybinds.

null 3 Dec 15, 2022
Fast TLSH-compatible Fuzzy Hashing Library in pure Rust

fast-tlsh: Fast TLSH-compatible Fuzzy Hashing Library in pure Rust TLSH stands for Trendmicro Locality Sensitive Hash. TLSH can be used to detect simi

Tsukasa OI 4 Mar 27, 2024
Save cli commands and fuzzy find them later

crow - cli command memorizer What is crow? | Installation | Usage | FAQ What is crow? crow (command row) is a CLI tool to help you memorize CLI comman

sandstorm 7 Feb 17, 2022
🧠 A command-line utility for switching git branches more easily. Switch branches interactively or use a fuzzy search to find that long-forgotten branch name.

git-smart-checkout A git command extension for switching git branches more efficiently. About Interactively switch branches or fuzzy search for that f

Cezar Craciun 51 Dec 29, 2022
Integrate Mcfly with fzf to combine a solid command history database with a widely-loved fuzzy search UI

McFly fzf integration Integrate McFly with fzf to combine a solid command history database with a widely-loved fuzzy search UI Features: Advanced hist

null 11 Jan 25, 2023
belt is a command line app that can show your time from a list of selected time zones

A CLI app to show your time from a list of selected time zones, and a rust lib to parse dates in string formats that are commonly used.

Rollie Ma 23 Nov 4, 2022
A CLI screentime monitoring tool. Shows how much time are you using certain apps.

A screentime monitoring tool, shows how much time are you really using certain apps. It work nicely with i3status or py3status on I3 window manager fo

Piotr Czajka 6 Dec 8, 2022