# 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](#overview) - [Structure](#structure) - [Plugins](#plugins) - [Theme & Prompt](#theme--prompt) - [Integrations](#integrations) - [Functions](#functions) - [Abbreviations](#abbreviations) - [Dependencies](#dependencies) - [Installation](#installation) - [Personalization](#personalization) - [Full Requirements](#full-requirements) --- ## 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 │ ├── fzf.fish # FZF key binding initialization │ ├── keybindings.fish # Custom key bindings │ ├── tailscale.fish # Tailscale CLI completions │ ├── 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](https://github.com/jorgebucaran/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 | Install plugins after cloning: ```fish fisher update ``` --- ## Theme & Prompt ### Starship The primary prompt is [Starship](https://starship.rs/), 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) **Key bindings** (from `fzf.fish`): | Binding | Action | |---|---| | `Ctrl+R` | Search command history | | `Ctrl+F` | Search directory files | | `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 | --- ## Integrations ### Zoxide Smart `cd` replacement. `z ` jumps to the best frecency match; `zi` opens an interactive selector. ### 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 deactivated when you leave the project tree. DirEnv-managed directories are skipped 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 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). | --- ## 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 ```fish 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 ```fish 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 | ### Package Management (Arch / paru) | Function | Description | |---|---| | `pkg ` | Install package: `paru -S ` | | `search ` | Search/install interactively: `paru ` | | `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` | ### Clipboard | Function | Description | |---|---| | `y ` | Copy text to clipboard (Wayland `wl-copy` or X11 `xclip`) | | `cb ` | Copy to clipboard (alias for `y`) | | `paste` | Paste from clipboard to stdout | ### Kitty Terminal | Function | Description | |---|---| | `split [-h\|-v] [cmd]` | Open a new Kitty split pane, optionally running a command | | `spwin` | Spawn a new Kitty OS window via `spawn-window.sh` | | `detach ` | Run a command fully detached (`nohup`), no output | | `bkg ` | 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 ` | Run a command with `systemd-inhibit` to prevent sleep | | `swapstat` | Colorized zRAM compression ratio, swappiness, and swap priority report | | `monitors` | Open a 4-pane Kitty layout running `btop` locally and on remote servers | | `tmux-clean` | Kill all detached tmux sessions | ### Editors & Development | Function | Description | |---|---| | `edit` / `e` | Open in Neovim | | `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 | ### 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 ` | 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`) | | `sbver` | Show system/binary versions | --- ## 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 Window Management These abbreviations mirror Vim/tmux ergonomics for managing Kitty splits, tabs, and windows. | 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](#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](#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` | ### 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](https://fishshell.com/) | Shell | | [Fisher](https://github.com/jorgebucaran/fisher) | Plugin manager | | [Starship](https://starship.rs/) | Prompt | | [fzf](https://github.com/junegunn/fzf) | Fuzzy finder | | [zoxide](https://github.com/ajeetdsouza/zoxide) | Smart directory jumper | | [direnv](https://direnv.net/) | Per-directory env loading | | [paru](https://github.com/Morganamilo/paru) | AUR helper | ### Recommended | Tool | Replaces | |---|---| | [eza](https://github.com/eza-community/eza) | `ls` (preferred) | | [lsd](https://github.com/lsd-rs/lsd) | `ls` (fallback) | | [bat](https://github.com/sharkdp/bat) | `cat` | | [btop](https://github.com/aristocratsupply/btop) | `top` | | [dust](https://github.com/bootandy/dust) | `du` (directories) | | [duf](https://github.com/muesli/duf) | `du` (disks) | | [prettyping](https://github.com/denilsonsa/prettyping) | `ping` | | [most](https://www.jedsoft.org/most/) | `less` | | [ripgrep](https://github.com/BurntSushi/ripgrep) | `grep` | | [lazygit](https://github.com/jesseduffield/lazygit) | git TUI | | [lazydocker](https://github.com/jesseduffield/lazydocker) | Docker TUI | | [trash-cli](https://github.com/andreafrancia/trash-cli) | Safe `rm` | | [Kitty](https://sw.kovidgoyal.net/kitty/) | Terminal emulator | | [WakaTime](https://wakatime.com/) | Activity tracking | --- ## Installation This config is managed as a Git repository. To use it on a new machine: ```fish # 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](https://www.chezmoi.io/) 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. ```fish # ~/.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. ```fish # ~/.config/.user-dots/fish/local.fish # Project root for quick cd set -gx cdp /home/youruser/projects # 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: ```fish 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`. --- ## Full Requirements For a complete, categorized list of all non-standard tools required or used by this configuration, see [requirements.md](requirements.md). --- ## License Copyright (C) 2026 Rootiest This project is licensed under the **GNU Affero General Public License v3.0 or later** (AGPLv3+). See the [LICENSE](LICENSE) file for the full license text.