A pretty fast code search tool

Welcome to ballish documentation! You're going to learn how to search across all of the code living on your machine in a few milliseconds, with some minimal setup. This documentation starts with a mini-tutorial to explain how to use the basic features, then drills down to more serious use cases, and ends with explaining the internals.

Let's get started!

Assuming you got to this page from the download page , you should have done the first step: installing the ballish daemon. It will do the magic for the search to work. Let's have a quick reminder in case you haven't done it:

$ sudo systemctl enable --now ballish-daemon@"$USER"

That should be it. Let's verify it works:

$ bl --status
server status: up
index size on disk: 0M
in-flight files to index: 0
indexed folders:

Looks like so. "indexed folders" is empty though, let's make sure we start indexing something.

$ bl --folder ~/dev

Or whatever your folder is where you store all your source code. If you're interested in the C things, you could also add this folder:

$ bl -f /usr/include

Now let's see if the daemon is busy:

$ bl -s
server status: up
index size on disk: 54.32M
in-flight files to index: more than 1000
indexed folders:
  - /home/user/dev/
  - /usr/include/

That sure looks better. And busy. Time to do our first search!

$ bl --query glob64_t

Nice. Let's see what's in there?

$ bl -q glob64_t --grep # or -g
/usr/include/glob.h:134:  } glob64_t;
/usr/include/glob.h:164:		   glob64_t *__restrict __pglob) __THROW;
/usr/include/glob.h:166:extern void globfree64 (glob64_t *__pglob) __THROW;
Note: if you need to search with a whitespace, use "+" instead.

There we go! That sums it up for the minimal setup of searching with ballish.

Drilling down


Ballish will helpfully tag all the indexed files. Every file is tagged with the type of programming language it belongs to. For example, *.rs files get the "rust" tag, *.js files get the "javascript" tag, etc. The tags have only one purpose: helping you narrow down the results you're getting.

Here are some usage examples:

$ bl --tags C --count # or bl -t c -c

That's how many C files have been indexed. How many of those files have "struct" in them?

$ bl -q struct -t c -c

Well, that's less than I would've expected.

The full list of tags/file extension is defined here .

Folder search

Searching across everywhere is fun, but sometimes you want to search in just a single folder. Ballish offers several options:

Note that those options have no influence on the performance, they only help to narrow down the results you're getting. You can of course combine those with tags and count.


This was mentioned in the kickstart at the beginning, but you can grep for what you're querying, so that you can see the found values, rather than only the files found.

Note: if you get an error saying fatal: too many results to grep , it's because the results were found in more than 100 files, which makes grep uncomfortable to use. If you decide to go above, you can set the limit in the BL_MAX_GREP_RESULTS environment variable.

The primary goal of this option is to make ballish much more usable from within editors, such as Vim or Emacs. Which leads me to...

Editors integrations

Ballish comes installed with a couple of integrations for your favorite editors, namely: Vim and Emacs.


After ballish is installed, you should be able to add this to your init.el or equivalent:

(require 'ballish)
(global-set-key (kbd "C-c j") 'ballish-grep-in-repository)
(global-set-key (kbd "C-c k") 'ballish-grep-everywhere)

And you should be able to use C-c j to start searching in the current git repository you're in, or C-c k to search everywhere.

Reminder: use "+" instead of spaces.

The Emacs package provided by ballish provides 4 functions at the moment:


After ballish is installed, a Vim plugin is provided, and you can use these commands inside Vim:

:BallishGrepInRepository <your search query>
:BallishGrepEverywhere <your search query>
Reminder: use "+" instead of spaces.

The Vim plugin opens the quickfix window by default, which you can disable by adding this to your .vimrc or equivalent:

let g:ballish_open_quickfix = 0

In the quickfix window, the lines are truncated to a given size to avoid polluting too much the window. The default value is 500 characters, but can be changed as such:

let g:ballish_max_grep_line_length = 1000


This section explains a bit how ballish works, which should explain why some of the arguments exist.

Ballish essentially relies on 3 ideas:

Given this, some limitations apply:

The SQLite database(s) live in the $XDG_CACHE_HOME/ballish/ folder, which is typically ~/.cache/ballish/ .

Exit codes

The bl client will exit with a set of known exit codes when a given set of operations occur.

  1. The search returned results without any errors.
  2. An unqualified error occured. Unqualified means it was handled, but not important enough to have its own exit code. This is typically used for bad arguments or sloppy coding.
  3. The program was interrupted by the user.
  4. The ballish daemon is not started.
  5. The database is too busy, the user should try again later.
  6. An unhandled sqlite error occured.
  7. The --repository argument was provided outside of a Git repository.
  8. The --repository or --location arguments were provided without a query.
  9. The index was not found.
  10. Too many results were found to be able to use --grep.
  11. An unhandled error occured.