rootiest 46be262f92 fix(fzf): erase fzf bindings in config.fish when fzf is absent
conf.d/fzf.fish is owned by Fisher and gets restored to the plugin's
original on fisher update, so any guard placed there is unreliable.
config.fish is never touched by Fisher, making it the right place to
call _fzf_uninstall_bindings after conf.d has already run and set up
the fzf key bindings on machines where fzf is not installed.
2026-05-18 21:06:09 -04:00
2026-04-26 01:37:38 -04:00

Fish Shell Configuration

A feature-rich Fish shell configuration for CachyOS (Arch Linux), built around a Catppuccin Mocha aesthetic with a curated set of modern CLI tool integrations, smart shell functions, and a heavily customized abbreviation system for keyboard-driven workflows.

Table of Contents


Overview

This config layers on top of the CachyOS base Fish configuration and adds:

  • Catppuccin Mocha theming throughout (prompt, FZF, Zellij)
  • Starship prompt with VI key bindings
  • Fisher plugin management with FZF key bindings and Catppuccin syntax colors
  • Smart CLI wrappers that prefer modern tools (eza, bat, btop, dust, prettyping) with graceful fallbacks
  • Auto Python venv activation on directory change (direnv-aware)
  • Kitty terminal deep integration for splits, tabs, and SSH
  • AI workflow helpers for Claude and Gemini session management
  • WakaTime shell activity tracking

Structure

~/.config/fish/
├── config.fish           # Main entry point
├── fish_plugins          # Fisher plugin list
├── fish_variables        # Universal variables
├── conf.d/               # Auto-sourced configuration fragments
│   ├── abbr.fish         # All abbreviations
│   ├── cheat.fish        # cheat.sh completions
│   ├── key_bindings.fish # Custom key bindings
│   ├── fzf.fish          # FZF key binding initialization
│   ├── tailscale.fish    # Tailscale CLI completions
│   ├── theme.fish        # Theme syntax highlighting colors
│   ├── wakatime.fish     # WakaTime shell hook
│   └── zoxide.fish       # Zoxide z/zi aliases
├── functions/            # Custom functions (one per file)
├── completions/          # Custom tab completions
├── integrations/         # Integration scripts
│   └── fzf.fish          # FZF theme and binding config
└── themes/               # Catppuccin theme files
    ├── Catppuccin Mocha.theme
    ├── Catppuccin Macchiato.theme
    ├── Catppuccin Frappe.theme
    └── Catppuccin Latte.theme

Plugins

Managed via Fisher:

Plugin Purpose
jorgebucaran/fisher Plugin manager
patrickf1/fzf.fish FZF key bindings for history, files, processes, git
catppuccin/fish Catppuccin Mocha syntax highlighting
jorgebucaran/autopair.fish Auto-close brackets, quotes, and other pairs
jorgebucaran/replay.fish Run bash commands in fish without losing state
nickeb96/puffer-fish Expand ... to ../.., !! to last command, etc.
mattmc3/magic-enter.fish Smart Enter: runs ls / git status on blank line
jorgebucaran/spark.fish Sparkline bar charts in the terminal

Fisher and all listed plugins are installed automatically by the bootstrap script in config.fish upon launching the shell for the first time.


Theme & Prompt

Starship

The primary prompt is Starship, initialized in config.fish. Configure it via ~/.config/starship.toml.

FZF

FZF is themed to Catppuccin Mocha with the following colors set via FZF_DEFAULT_OPTS:

  • Background: #1E1E2E / #313244
  • Foreground: #CDD6F4
  • Highlights: #F38BA8 (red), #CBA6F7 (mauve), #B4BEFE (lavender)

See FZF Bindings under Key Bindings for the default FZF shortcuts.


Integrations

Note

All integrations listed below are designed to gracefully fallback to basic commands or safely ignore their configuration if their required external dependencies are not installed on the system.

Zoxide

Smart cd replacement powered by frecency scoring. cd, z, and cdi/zi are all mapped to zoxide-backed navigation functions.

Command Description
cd <path> / z <path> Jump to a matching directory by frecency; falls back to exact path
cdi / zi Open an interactive fzf selector across all frecency-ranked directories

Tab completions for cd and z blend standard directory entries (CWD and CDPATH) with zoxide frecency results, so familiar paths and frequently-visited destinations appear together in a single list. Full tab completions for the zoxide CLI itself (subcommands: add, query, remove, import, init) are provided via completions/zoxide.fish.

DirEnv

Automatically loads .envrc files on directory change. Takes priority over the built-in auto-venv logic.

Auto Python Venv

When entering a directory containing a .venv/, the virtualenv is automatically activated.
It is automatically deactivated when you leave the project tree.

Tip

DirEnv-managed directories are skipped by the auto-venv logic to avoid conflicts.

WakaTime

Every shell command is reported to WakaTime for time-tracking. Disable by setting FISH_WAKATIME_DISABLED=1.

Tailscale

Full tab completion for the tailscale CLI is provided via conf.d/tailscale.fish.


Key Bindings

FZF Bindings

These are the default FZF bindings (from fzf.fish):

Binding Action
Ctrl+R Search command history
Ctrl+Alt+F Search git-tracked files
Ctrl+Alt+L Search git log
Ctrl+Alt+S Search git status
Ctrl+V Search shell variables
Ctrl+Alt+P Search running processes

User Bindings

Beyond standard shell and FZF bindings, these custom interactive shortcuts are available:

Binding Action Description
Ctrl+G Previous Path Head Behaves like !$:h in Bash. Inserts the directory part of the previous command's last argument.
Ctrl+F Interactive History Substitution Behaves like !!:s/old/new/ in Bash. Performs substitution on the previous command using old/new syntax. When no text is entered, prepends sudo to the previous command. The old/new/n syntax will perform substitution on the command n lines previous in the history.
Ctrl+Alt+U Replace Command Token Strips the first token (the command) from the current line. If the line is empty, it pulls the previous command and strips its first token, placing the cursor at the start for a quick replacement (e.g., changing mkdir to cd while keeping the paths).
Ctrl+Alt+= Inline Qalculate! Evaluation Passes the current command-line buffer to qalc (Qalculate!) and prints the result, then clears the buffer. Allows rapid-fire math without leaving the shell — type 150 * 1.08, press Ctrl+Alt+=, and see 162 immediately.
Ctrl+Enter Smart Execute Context-aware Enter key. Empty buffer → standard Enter. Buffer ending with = → evaluates it as a math expression via qalc (same as Ctrl+Alt+=). Any other content → executes the command normally.

Functions

Modern CLI Replacements

These functions wrap modern alternatives with graceful fallbacks to standard tools.

Function Replaces Tool
ls ls eza (falls back to lsd, then system ls)
cat cat bat (plain, no pager)
less less most
ping ping prettyping --nolegend
top top btop
rg rg ripgrep with --hyperlink-format=kitty
ssh ssh kitten ssh when inside Kitty
du du duf (disks) / dust (directories) — auto-detected by argument
mkdir mkdir Always passes -p in interactive mode

du — Smart Disk Usage

du              # → duf  (disk overview)
du /some/dir    # → dust (directory breakdown)
du --disk       # → duf  (force disk view)
du --dir        # → dust (force directory view)
du --dua        # → dua  (interactive mode)

rm — Trash-Aware Remove

rm              # List current trash contents
rm file.txt     # Move to trash (recoverable)
rm -r dir/      # Move directory to trash
rm -e           # Empty all trash
rm -e --within 2weeks  # Empty trash older than 2 weeks
rm -S file.txt  # Permanent secure delete + fstrim
rm -f file.txt  # Falls through to standard rm -f

Directory & File Listing

Function Description
ls eza — long listing, all files, icons, color, hyperlinks
lss eza — size-sorted long listing with gradient color scale
lsr eza — reversed time-sorted oneline listing
ltr eza — long listing, reversed modification time, age color scale
lD eza — directories only
lx eza — long listing sorted by extension
lt eza — tree listing, depth 2
lstree eza — full recursive tree

Git

Function Description
branch Switch to or create a git branch
gitup Fetch updates and show git status
git-clean Fetch, prune, update current branch, delete orphaned local branches
git-clean --force Same but force-deletes unmerged orphaned branches
clone clone-in-kitty wrapper
gitui Fast terminal Git UI

Package Management (Arch / paru)

Function Description
pkg <name> Install package: paru -S <name>
search <query> Search/install interactively: paru <query>
upgrade Full system upgrade: paru -Syu --noconfirm
cleanup Log and remove orphaned packages

Docker

Function Description
ld / lzd Launch LazyDocker using the currently active Docker context
dockup [dir] Pull latest images and restart docker compose services
docker ps Intercepted to use dops for a prettier process listing

Network

Function Description
gip Show both public IPv4 and IPv6 addresses
gip4 Show public IPv4 address only
gip6 Show public IPv6 address (or error if unavailable)
ports List all active TCP listeners via lsof
fast-cli Run a bandwidth speed test using fast.com
fast Friendly error shown when fast is typed instead of fast-cli

Clipboard

Function Description
y <text> Copy text to clipboard (Wayland wl-copy or X11 xclip)
cb <text> Copy to clipboard (alias for y)
paste Paste from clipboard to stdout

Terminal

Function Description
split [-h|-v] [cmd] Open a new split pane, optionally running a command
spwin Spawn a new OS window
detach <cmd> Run a command fully detached (nohup), no output
bkg <cmd> Background a command, discarding all output

System

Function Description
lock Lock the session via loginctl lock-session
screensleep Turn off the display via KDE PowerDevil
wake-lock <cmd> Run a command with systemd-inhibit to prevent sleep
swapstat Colorized zRAM compression ratio, swappiness, and swap priority report
tmux-clean Kill all detached tmux sessions
limine-edit Safely edit and re-verify Limine bootloader configuration
sbver Verify bootloader signing status for Secure Boot

Media & Utilities

Function Description
dng2avif Convert DNG raw images to 10-bit HDR AVIF
steam-dl Run Steam while inhibiting system sleep

Editors & Development

Function Description
edit / e Open in Neovim (or $EDITOR)
view Open in Neovim read-only mode
fc Edit and execute the last command (Bash-style fc)
nvimup Update Neovim headlessly
nlazyup Sync Lazy.nvim plugins headlessly

AI Assistants

Function Description
claude-resume Resume Claude Code session from .claude_session in CWD
gemini-resume Resume Gemini CLI session from .gemini_session in CWD
code-resume Smart resume — tries Claude then Gemini, falls back to picker
superpowers [on|off] Enable/disable the Superpowers extension for Claude and Gemini
claude-docs Ask Claude to sync README.md with recent session changes
claude-pr Create a branch, commit, push, and open a PR via Claude

Fetch & Info

Function Description
ffetch Run fastfetch with ~/.fastfetch.jsonc if present
cffetch Clear screen then run fastfetch
hist FZF history search — selected command is placed in the prompt and copied to clipboard
qr <text> Generate a terminal QR code

Miscellaneous

Function Description
upgrade System upgrade via paru
zellij Zellij with --theme catppuccin-mocha
antigravity Wrapper that suppresses a noisy deprecation warning
bash Drop into bash (raw Fish session via rawfish)

Abbreviations

Abbreviations expand in-place as you type, keeping your history clean.

History Expansions (Bash-style)

These abbreviations replicate Bash's bang-style history expansions. They expand anywhere in the command line when a trigger key (like Space or Enter) is pressed.

Abbr Expansion Description
!^ First argument Expands to the first argument of the previous command
!* All arguments Expands to all arguments of the previous command
!-n n-th previous Expands to the n-th previous command in history (e.g., !-2)
!string Prefix search Expands to the most recent command starting with string
!?string? Contains search Expands to the most recent command containing string
^old^new Quick substitution Replaces old with new in the previous command and expands to it

Editors

Abbr Expands To
n, nv nvim
e edit
se sudoedit
v antigravity (VSCode-equivalent)
k kate

Listing

Abbr Expands To
l ls
lS lss (size-sorted)
lsR lsr (reversed time)
lX lx (extension-sorted)
lT lt (tree, depth 2)
lsT lstree (full tree)

Navigation

Abbr Expands To
cdnv cd ~/.config/nvim
:cdf cd ~/.config/fish/
:cdk cd ~/.config/kitty/
:cdh cd ~
:cdp cd ~/projects/ (with cursor placement)
:cdcz cd ~/.local/share/chezmoi/

Git

Abbr Expands To
g git
lg lazygit

Chezmoi

Abbr Expands To
cm / cz chezmoi
cmcd chezmoi cd
cme chezmoi edit
cmad chezmoi add
cmap chezmoi apply
cmf chezmoi forget
cmi chezmoi init

Kitty / WezTerm Window Management

These abbreviations mirror Vim/tmux ergonomics for managing terminal splits, tabs, and windows. They automatically detect whether you are using Kitty or WezTerm and execute the appropriate terminal CLI commands.

Abbr Action
:q Close active pane
:Q Close active tab
:w New OS window
:t New tab
:wv Horizontal split
:wh Vertical split
:tp / :tn Navigate tabs left/right
:tl "Title" Rename current tab
:tgn New tab in ~/.config/nvim
:tgf New tab in ~/.config/fish
:tgp New tab in ~/projects
:tgr New root tab (sudo -i)

SSH

Machine-specific SSH abbreviations (e.g. sshr, sshrt) live in ~/.config/.user-dots/fish/local.fish. (See Personalization for examples)

Docker

Abbr Expands To
dcl docker context use default
dcls docker context ls
lzd ld (LazyDocker)

Named context shortcuts (e.g. dcr, dck) live in ~/.config/.user-dots/fish/local.fish. (See Personalization for examples)

Systemctl

Abbr Expands To
sc systemctl
ssc sudo systemctl
scu systemctl --user
st systemctl status
scs systemctl start
scr systemctl restart
ssct sudo systemctl status
sscs sudo systemctl start
sscr sudo systemctl restart

Speed Test

Abbr Expands To
speedtest-fast fast-cli (speed test via fast.com)

Beads (bd)

Abbr Expands To
bl bd list
bs bd sync
bC bd create --title
bsh bd show
lb lazybeads

Dependencies

Required

Tool Purpose
Fish Shell
Fisher Plugin manager
Starship Prompt
fzf Fuzzy finder
zoxide Smart directory jumper
direnv Per-directory env loading
paru AUR helper
Tool Replaces
eza ls (preferred)
lsd ls (fallback)
bat cat
btop top
dust du (directories)
duf du (disks)
prettyping ping
most less
ripgrep grep
lazygit git TUI
lazydocker Docker TUI
trash-cli Safe rm
Kitty / WezTerm Terminal emulator
WakaTime Activity tracking

Full Requirements

For a complete, categorized list of all non-standard tools required or used by this configuration, see requirements.md.


Installation

This config is managed as a Git repository. To use it on a new machine:

# Back up any existing config
mv ~/.config/fish ~/.config/fish.bak

# Clone this repo
git clone https://git.rootiest.dev/rootiest/fish-config.git ~/.config/fish

Then open a new Fish shell — Fisher and all plugins will be installed automatically on first launch, and the Catppuccin Mocha theme will be applied.

A chezmoi dotfile manager is also configured — secrets are sourced from ~/.config/.user-dots/fish/secrets.fish and excluded from version control.


Personalization

Sensitive credentials and machine-specific paths are kept out of version control via a secondary private directory at ~/.config/.user-dots/fish/. Two files are sourced automatically by config.fish if they exist:

~/.config/.user-dots/fish/
├── secrets.fish   # API keys, tokens, passwords, personal identifiers
└── local.fish     # Machine-specific paths and environment variables

secrets.fish

Use this file for anything you would not commit to a public repo: API keys, auth tokens, passwords, and personal identifiers like usernames or email addresses.

# ~/.config/.user-dots/fish/secrets.fish

### Identity ###
set -gx MY_NAME "Your Name"
set -gx MY_EMAIL "you@example.com"
set -gx GPG_RECIPIENT "you@example.com"

### API Keys & Tokens ###
set -gx GITHUB_TOKEN ghp_yourTokenHere
set -gx OPENAI_API_KEY sk-proj-yourKeyHere
set -gx GITEA_TOKEN yourGiteaTokenHere
set -gx GITEA_CHOSEN_LOGIN your.gitea.instance
set -gx TEA_LOGIN your.gitea.instance

### Backup ###
set -gx KOPIA_PASSWORD yourKopiaPassword

local.fish

Use this file for paths and variables that are specific to one machine — things that would break or be wrong on any other system.

# ~/.config/.user-dots/fish/local.fish

# CDPATH — directories searched by cd
set -gx CDPATH . /home/youruser/projects /home/youruser

### SSH ###
# Quick shortcuts to your own servers
abbr -a sshr 'ssh you@your-server.local'
abbr -a sshw 'ssh you@work-server.example.com'

### Docker contexts ###
# Named shortcuts for your own Docker contexts (docker context ls)
abbr -a dcr 'docker context use my-remote-server'
abbr -a dcw 'docker context use work-server'

How it works

config.fish sources both files with an existence check so the public config works cleanly on any machine that doesn't have the private repo:

if test -f $HOME/.config/.user-dots/fish/secrets.fish
    source $HOME/.config/.user-dots/fish/secrets.fish
end

if test -f $HOME/.config/.user-dots/fish/local.fish
    source $HOME/.config/.user-dots/fish/local.fish
end

fish_variables (which fish auto-manages and may contain universal variable state) is excluded from this repo via .gitignore.


Attribution

The core of the Zoxide integration in this repository was originally adapted from the icezyclon/zoxide.fish plugin (MIT Licensed) and has since been heavily customized for performance and Fish 4.x compatibility.


License

Copyright (C) 2026 Rootiest

This project is licensed under the GNU Affero General Public License v3.0 or later (AGPLv3+). See the LICENSE file for the full license text.

S
Description
My personal fish config, ready to deploy on any machine!
Readme AGPL-3.0 790 KiB
Languages
Shell 100%