Over the years I've used TextExpander, Alfred, Raycast, and then as I tried to be platform agnostic Espanso. All of the options were decent, but even Espanso had issues on some platforms that caused me to stop using it. For a while I've stored my snippets in my Obsidian vault and then manually copied and pasted them into whatever application I needed.

Time to change that. I wanted to store my snippets in a central place where I could control them with version control. I wanted to invoke a keyboard command, have a window popup to search my snippets, then when I press enter the snippet should be copied to my clipboard. I wanted my snippets to be program agnostic because while I use Neovim for coding, I use Emacs for tasks and Obsidian for writing and I have snippets for each one. I didn't want to manage different snippet systems for each application.

You can find the whole snippet-search script and my other development tools in the Github repository.

I moved my library of code snippets to ~/Documents/snippets, organised into subdirectories by category. Then wrote a small bash script that lets me fuzzy-search the library, preview each snippet with syntax highlighting, and copy the code block directly to my clipboard — all from a floating terminal window triggered by a single keybind.

Now I can press Super+Shift+F, a floating window appears, I type a few characters to filter, once the correct file is highlighted, hit enter, and the code is in my clipboard. The window disappears a second later.

What You Need

The script depends on four tools:

  • ripgrep (rg) — lists files in the snippets directory
  • fzf — the fuzzy finder that drives the interactive selection
  • bat — syntax-highlighted file preview inside fzf
  • wl-clipboard (wl-copy) — Wayland clipboard tool

On NixOS, add them to your home-manager packages:

bat
fzf
ripgrep
wl-clipboard

On other distros, install via your package manager:

# Arch
sudo pacman -S ripgrep fzf bat wl-clipboard

# Ubuntu/Debian
sudo apt install ripgrep fzf bat wl-clipboard

The Snippet Format

Each snippet file is either the code surrounded by backticks, or in the case of newer files just the code in the file. Once selected I want either all the code in the backticks if present, and if not give me the whole code in the file. Once the code is copied you get message then the window disappears after 1 second.

The Script

#!/usr/bin/env bash

set -euo pipefail

SNIPPETS_DIR="$HOME/Documents/snippets"

# Check if snippets directory exists
if [[ ! -d "$SNIPPETS_DIR" ]]; then
    echo "Error: Snippets directory not found at $SNIPPETS_DIR" >&2
    exit 1
fi

# Search with ripgrep, pipe to fzf with bat preview (show relative path only)
result=$(rg --files "$SNIPPETS_DIR" | \
         sed "s|$SNIPPETS_DIR/||" | \
         fzf --preview="bat --style=numbers --color=always $SNIPPETS_DIR/{}")

# Check if user selected a file and pressed enter
if [[ -z "$result" ]]; then
    echo "No selection made."
    exit 0
fi

# Extract content inside triple backtick code fences, fall back to whole file
content=$(awk '/^```/{if(p){p=0}else{p=1;next}} p' "$SNIPPETS_DIR/$result")

if [[ -z "$content" ]]; then
    content=$(cat "$SNIPPETS_DIR/$result")
fi

# Copy to clipboard and show success
if ! printf '%s' "$content" | wl-copy; then
    echo "Error: Failed to copy to clipboard" >&2
    exit 1
fi

echo "✓ Copied $result to clipboard!"
sleep 1

Save it to ~/bin/snippet-search and make it executable:

chmod +x ~/bin/snippet-search

How It Works

File listingrg --files "$SNIPPETS_DIR" lists every file under the snippets directory recursively. Using ripgrep here rather than find keeps it fast even with a large library, and it respects .gitignore files if you have one.

Stripping the path — the sed command removes the $SNIPPETS_DIR/ prefix from each path before it reaches fzf. This means the picker shows docker/remove-all-containers.md rather than /home/you/Documents/snippets/docker/remove-all-containers.md. The full path is reconstructed later when needed.

Fuzzy preview — fzf gets the relative paths but the --preview flag passes the full path ($SNIPPETS_DIR/{}) to bat. bat renders the file with line numbers and syntax highlighting in the right-hand panel as you move through results.

Code extraction — once a file is selected, awk walks the file line by line. When it hits a line starting with triple backticks, it toggles a flag. Lines between the opening and closing fences are printed; the fence lines themselves are discarded. This strips the language tag (```bash, ```python, etc.) as well as any prose outside the code block.

Clipboard copyprintf '%s' "$content" pipes the extracted code into wl-copy. Using printf rather than echo avoids appending a trailing newline to the clipboard content.

Window closesleep 1 keeps the terminal open long enough to read the confirmation message before the window closes. On Hyprland with kitty, launch the script with --override close_on_child_death=yes so kitty exits as soon as the script finishes.

Wiring It Up in Hyprland

Add the keybind and a windowrule to your Hyprland config:

bind = $mainMod SHIFT, F, exec, kitty --title snippet-search --override close_on_child_death=yes -e ~/bin/snippet-search

windowrule {
    name = float-snippet-search
    match:initial_title = snippet-search
    float = on
    size = 1200 500
    center = true
}

The --title flag gives the window a predictable name for the windowrule to match. The windowrule floats it at 1200×500 pixels, centred on screen. Adjust the size to taste — wider is better here because fzf splits the view between the file list on the left and the bat preview on the right.

Wiring It Up in KDE

I don't use KDE or GNOME anymore so while these instructions seem like they'll work based on my experience Claude helped me write them. I did check the docs after, but the instructions may not be exact.

In KDE Plasma, go to System Settings → Shortcuts → Custom Shortcuts. Create a new shortcut with the trigger Meta+Shift+F and set the command to:

konsole --title snippet-search -e ~/bin/snippet-search

To make the window float and centre, go to System Settings → Window Management → Window Rules and add a rule. Set the description to snippet-search, match on Window title snippet-search (exact match), then add these properties:

  • Position → Apply initially → centre of screen
  • Size → Apply initially → 1200×500
  • Keep above → Force → Yes

KDE does not have an equivalent to close_on_child_death — Konsole closes automatically when the process running inside it exits, so the window will disappear on its own after the sleep 1.

Wiring It Up in GNOME

GNOME's built-in keyboard shortcuts only support simple commands, so open Settings → Keyboard → View and Customise Shortcuts → Custom Shortcuts and add a new entry. Name it snippet-search, set the shortcut to Super+Shift+F, and use this command:

gnome-terminal --title snippet-search -- ~/bin/snippet-search

GNOME does not have a built-in window rules system. Install the Window Calls Extended GNOME Shell extension if you want to auto-float or size the window. Alternatively, accept that it opens as a regular window — the script still works fine, it just will not automatically float above your current work.

Like Konsole, gnome-terminal closes when its child process exits, so no extra configuration is needed for the window to disappear after the copy.