Files
fish-config/docs/fish-config.md
T
rootiest 034ebade0d feat(edit): stop forcing VISUAL to the terminal editor
VISUAL was hardwired to $EDITOR (nvim), so 'edit --visual' would launch a
terminal editor detached with no tty. Comment it out so --visual falls
through to the GUI fallback chain, and let users set a real GUI editor via
local.fish. Update the editor-variable docs to match.
2026-06-19 01:56:58 -04:00

76 KiB
Raw Blame History

title, section, header, date, author
title section header date author
FISH-CONFIG 7 Fish Shell Configuration User Manual June 2026 Rootiest

NAME

fish-config - personal fish shell configuration for Fish 4.x with modern CLI tool integration

SYNOPSIS

help config [SECTION]

Open this manual in the best available pager. Optionally jump to a section by keyword:

help config keybindings
help config pkg
help config abbreviations
help config logs

The help config syntax integrates with fish's built-in help command. The underlying config-help function is also available directly.

DESCRIPTION

A production-grade Fish shell configuration targeting Fish 4.x. It provides:

  • Drop-in replacements for common Unix tools (ls, cat, rm, du, ping, less)
  • Deep Kitty and WezTerm terminal integration: tab/window/pane management from the command line
  • Automatic session logging: terminal scrollback, tmux/zellij panes, and paru/yay output captured to ~/.terminal_history (on by default; see below)
  • Automatic Python virtualenv activation on directory change
  • Cross-platform package management via pkg and fish-deps
  • AI session helpers for Claude Code and Antigravity
  • Catppuccin Mocha color theme throughout

CAUTION - SESSION LOGGING IS ON BY DEFAULT

This configuration silently records terminal output to ~/.terminal_history: Kitty scrollback on window close, live tmux pane streams, zellij pane snapshots on exit, and full paru/yay output. These logs can contain command output, file contents, and secrets printed to the terminal. Nothing leaves your machine, but the files persist locally.

  • Disable all logging with: set -U __fish_config_op_logging off
  • Prefer a menu? Run the interactive picker: config-toggle
  • See Section 7 (C5 - Logging and Capture) for the full breakdown.

The configuration is split across:

config.fish               Main entry point; sets env vars and PATH
conf.d/
  abbr.fish               All abbreviations
  autopair.fish           Auto-pair brackets and quotes (bundled from jorgebucaran/autopair.fish)
  cheat.fish              cheat.sh tab completions
  done.fish               Desktop notifications for long commands
  first_run.fish          One-time init: Fisher bootstrap, theme, welcome
  key_bindings.fish       Custom key bindings and Vi mode
  logging-events.fish     C5 --on-variable event handlers; syncs logging state at startup
  kitty-watcher-reminder.fish  C5 per-session reminder to set up the Kitty watcher
  paru-wrapper.fish       Auto-generates ~/.local/bin/paru logging wrapper
  puffer.fish             !! / !$ / ./ expansion (bundled from nickeb96/puffer-fish)
  tmux-logging.fish       C5 starts tmux pipe-pane capture when fish runs inside tmux
  zellij-logging.fish     C5 fish_exit handler dumping zellij pane scrollback on exit
  sponge_privacy.fish     Sponge privacy patterns; filters credentials from history
  starship.fish           fish_prompt with OSC 133 shell-integration markers
  tailscale.fish          Tailscale CLI tab completions
  theme.fish              Catppuccin syntax highlight colors
  tricks.fish             PATH, bang-bang helpers, bat man pages, aliases
  wakatime.fish           WakaTime shell hook
  yay-wrapper.fish        Auto-generates ~/.local/bin/yay logging wrapper
  zoxide.fish             Zoxide z/zi integration; overrides cd
functions/                Custom functions, one per file, autoloaded
completions/              Tab completion scripts
integrations/
  fzf.fish                FZF Catppuccin theme and key binding config
scripts/
  clean_progress_log.py   Strips paru/yay typescript animations to clean static logs
  agents-tools/           AGENTS.md version-bump script and git hooks (wired via core.hooksPath)
docs/                     Offline documentation and compiled man page
  fish-config.md          Primary source manual (terminal-readable)
  fish-config.1           Compiled man page (auto-generated by CI)
  fish-config.index       Section index for help config navigation
  html/                   Chunked HTML docs (auto-generated by CI)
  wiki/                   Markdown wiki (auto-generated by CI)

TABLE OF CONTENTS

1.  Configuration Variables
2.  PATH Setup
3.  Key Bindings
4.  Abbreviations
    4.1  Editors
    4.2  Navigation and Listing
    4.3  Git
    4.4  Terminal Windows, Tabs, and Panes
    4.5  Chezmoi
    4.6  Docker
    4.7  Systemctl
    4.8  AI Assistants
    4.9  History Expansion
    4.10 Miscellaneous
    4.11 Shell Aliases
5.  Functions Reference
    5.1  File and Directory
    5.2  Navigation
    5.3  Editors and Viewers
    5.4  Git and Version Control
    5.5  Package Management
    5.6  Dependency Management
    5.7  System and Monitoring
    5.8  Terminal Management
    5.9  Clipboard
    5.10 Network
    5.11 Pager and Logging
    5.12 AI and Developer Tools
    5.13 Media and Utilities
    5.14 Miscellaneous
6.  Dependency Catalog
7.  Customization
8.  Fisher Plugins
9.  Installation
10. Personalization
11. Viewing This Manual

1. CONFIGURATION VARIABLES

These variables are exported from config.fish on every interactive session. Override them in ~/.config/.user-dots/fish/local.fish.

Environment Directories (XDG)

XDG_CONFIG_HOME    ~/.config
XDG_CACHE_HOME     ~/.cache
XDG_DATA_HOME      ~/.local/share
XDG_STATE_HOME     ~/.local/state

Tools that respect XDG are directed to these paths rather than polluting $HOME.

Tool Homes (XDG-compliant)

CARGO_HOME         $XDG_DATA_HOME/cargo
RUSTUP_HOME        $XDG_DATA_HOME/rustup
GOPATH             $XDG_DATA_HOME/go
BUN_INSTALL        $XDG_DATA_HOME/bun
NPM_CONFIG_PREFIX  $XDG_DATA_HOME/npm-global
GNUPGHOME          $XDG_CONFIG_HOME/gnupg
WAKATIME_HOME      $XDG_CONFIG_HOME/wakatime

Editor and Pager

EDITOR      nvim (falls back to vi if nvim is absent)
VISUAL      unset by default; set a GUI editor via local.fish (the edit
            function falls back to a GUI chain when VISUAL is empty)
SUDO_EDITOR same as EDITOR
PAGER       ov (falls back to less)

Scrollback History

SCROLLBACK_HISTORY_DIR        ~/.terminal_history
SCROLLBACK_HISTORY_MAX_FILES  100

Scrollback logs accumulate in SCROLLBACK_HISTORY_DIR as timestamped files. When the count exceeds SCROLLBACK_HISTORY_MAX_FILES the oldest are pruned automatically on exit. Use logs to browse them interactively.

Other

GPG_TTY              $(tty)  — ensures GPG passphrase prompts work
CLAUDE_CODE_NO_FLICKER  1    — suppress terminal flicker in Claude Code
CDPATH               . ~/projects ~

Opinionated defaults (CDPATH, PAGER/MANPAGER, Vi mode, command shadows, terminal integrations) can be switched off per category with universal variables — see Section 7, "Opinionated Components (Minimal Mode)".

Pager Hierarchy

$PAGER is set to ov when available, falling back to less. The less wrapper function extends this into a full chain so anything that calls less directly also benefits:

$PAGER → ov → less → more → cat

When bat is installed, man pages are rendered with syntax highlighting:

MANROFFOPT   -c
MANPAGER     sh -c 'col -bx | bat -l man -p'

Integrations

Zoxide

cd, z, and cdi/zi are all mapped to zoxide-backed navigation. Tab completions for cd and z blend standard directory entries (CWD and CDPATH) with frecency results so both familiar and frequently-visited paths appear in one list.

DirEnv

Automatically loads .envrc files on directory change. Takes priority over the auto-venv logic — if a directory is managed by direnv, the auto-venv activation is skipped entirely.

Auto Python Venv

When entering a directory that contains a .venv/, the virtualenv is activated automatically and deactivated when you leave the project tree.

WakaTime

Every shell command is reported to WakaTime for time-tracking. Set FISH_WAKATIME_DISABLED=1 to disable without removing the plugin.

Tailscale

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

Done Notifications

Desktop notifications fire when a command takes longer than 10 seconds and the terminal window is not focused. Configured via fish universal variables:

__done_min_cmd_duration          10000 ms
__done_notification_urgency_level  low

Scrollback History

When running inside Kitty, closing a shell session via exit saves a timestamped scrollback snapshot to SCROLLBACK_HISTORY_DIR. Files are named:

scrollback_YYYY-MM-DD_HH-MM-SS.log

The paru and yay wrappers (auto-generated in ~/.local/bin/) run the command inside a PTY via script(1) so download progress bars are preserved on screen, then render the captured terminal animation down to a clean static log via scripts/clean_progress_log.py (a small terminal-screen emulator that replays cursor movements, collapses repainted progress frames to their final state, and preserves ANSI color). If python3 is unavailable the wrapper falls back to dropping only the script(1) header/footer. Output is saved to:

paru_YYYY-MM-DD_HH-MM-SS.log
yay_YYYY-MM-DD_HH-MM-SS.log

Before pruning, _scrollback_prune_junk silently removes empty files, files with only a single meaningful line (e.g. bare [exited] captures), and Kitty tab-rename prompt captures. Use exit --no-log (or exit -n) to skip capture.


2. PATH SETUP

Directories prepended to PATH in this order (first wins):

~/.local/bin              Standard user-local executables
~/Applications            User-installed standalone apps
~/scripts                 Personal shell scripts
~/bin                     Cargo binaries (appended — lowest priority)
$BUN_INSTALL/bin          Bun runtime and global packages
$NPM_CONFIG_PREFIX/bin    Global npm packages
~/.lmstudio/bin           LM Studio CLI
~/.resend/bin             Resend CLI
~/.fzf/bin                fzf binary (git-installed)

Cargo binaries are intentionally appended (lowest priority) to avoid shadowing system-installed Rust tools.


3. KEY BINDINGS

The shell uses Vi key bindings (fish_vi_key_bindings). All custom bindings are active in Insert, Normal, and Visual modes unless noted.

Binding         Action
─────────────────────────────────────────────────────────────────────
Ctrl+G          Insert the head of the previous command's last path
                argument. Equivalent to !$:h in Bash.
                Example: previous = "cd /usr/local/bin"
                         Ctrl+G inserts "/usr/local"

Ctrl+F          Interactive history substitution. Type old/new then
                press Ctrl+F to apply s/old/new/ to the previous
                command. Equivalent to !!:s/old/new/ in Bash.
                Example: previous = "echo this is a test"
                         type "this is/that was", press Ctrl+F
                         result = "echo that was a test"

Ctrl+Alt+U      Strip the first token of the current command line,
                leaving arguments in place with the cursor at the
                start. Useful for quickly retyping the command.
                Example: "mkdir new_folder" -> " new_folder"

Ctrl+Alt+=      Evaluate the current command line buffer with
                Qalculate! (qalc) and print the result inline.
                Requires qalc to be installed.
                Example: type "150 * 1.08", press Ctrl+Alt+=
                         prints 162

Ctrl+Enter      Smart execute: runs commands instantly without
                pressing Enter a second time for certain fast-path
                commands (speedtest-fast, etc.).

@@              FZF inline picker. Type @@ anywhere on the command
                line to open an fzf picker and insert a selection
                at the cursor position.

FZF Bindings (bundled from PatrickF1/fzf.fish)

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

4. ABBREVIATIONS

Abbreviations expand when you press Space or Enter. They are terminal-aware: some expand differently in Kitty vs WezTerm vs other terminals.

4.1 Editors

n / nv / neovim    nvim
e                  edit
se                 sudoedit
k                  kate
editt              Open new tab with nvim (terminal-aware)
cdnv               cd ~/.config/nvim
cdnvn              cd ~/.config/nvim; nvim

4.2 Navigation and Listing

l                  ls
lS                 lss       (sort by size)
lsR                lsr       (sort by time, oldest first)
lX                 lx        (sort by extension)
lT                 lt        (tree, depth 2)
lsT                lstree    (full recursive tree)
lzd                ld        (lazydocker)
cdi                zi        (interactive zoxide picker)

4.3 Git

g                  git
lg                 lazygit
gitig / git-ignore gi        (generate .gitignore)

4.4 Terminal Windows, Tabs, and Panes

These abbreviations control the terminal emulator. Each has a Kitty variant and a WezTerm variant; the correct one is inserted based on $TERM or $TERM_PROGRAM.

:w          New OS window
:wv         Split pane horizontally (new pane below)
:wh         Split pane vertically (new pane to the right)
:wo         Detach current window to its own OS window
:wot        Move current pane to a new tab
:t          New tab
:tl         Set tab title
:tw         Set window title
:twk        Rename workspace (WezTerm only)
:tp         Focus previous tab
:tn         Focus next tab
:q          Close current pane/window
:Q          Close current tab
:sw         spwin (spawn new OS window)

Quick-navigate shortcuts open windows/tabs/panes with preset working dirs:

:tgk    New tab at ~/.config/kitty
:tgn    New tab at ~/.config/nvim
:tgf    New tab at ~/.config/fish
:tgh    New tab at ~
:tgcz   New tab at chezmoi source dir
:tgcm   New tab at chezmoi source dir
:tgp    New tab at ~/projects
:tgr    New tab at / (root)

Prefixes :wg* and :wvg* / :whg* open OS windows or splits to the same set of dirs, respectively.

Prefixes :cd* open tabs with a quick cd shortcut:

:cdn    cd ~/.config/nvim
:cdf    cd ~/.config/fish
:cdh    cd ~
:cdcz   cd to chezmoi source
:cdp    cd ~/projects

Appending n to any :cd* abbreviation also runs nvim after changing dir.

4.5 Chezmoi

cm / cme / cmi / cmap / cmad / cmrm / cmcd /
cz / cze / czi / czap / czad / czrm / czcd

cm / cz          chezmoi
cmcd / czcd      chezmoi cd
cme / cze        chezmoi edit
cmad / czad      chezmoi add
cmap / czap      chezmoi apply
cmrm / cmf / czrm / czf    chezmoi forget
cmi / czi        chezmoi init

4.6 Docker

dcl         docker context use default
dcls        docker context ls
lzd         ld (lazydocker)

4.7 Systemctl

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

4.8 AI Assistants

ag          agy
ag.         agy .
v           antigravity-ide
s           wezterm ssh (WezTerm only)

4.9 History Expansion

These are implemented as keybinding helpers, but can also be typed:

!^          Expand to first argument of previous command
!*          Expand to all arguments of previous command
typo_sub    Interactive typo substitution (Ctrl+F)
bang_string !string expansion
bang_search !?string search
bang_minus_n  !-n  (nth-previous command)

4.10 Miscellaneous

/exit       exit
:q          Close pane (alias for terminal close)
:Q          Close tab
sudu        sudo -s
kt          kitty (Kitty only)
c           cat
speedtest-fast  fast-cli
bl          bd list
bs          bd sync
bC          bd create --title
bsh         bd show
lb          lazybeads

4.11 Shell Aliases

These aliases are defined in conf.d/tricks.fish via alias (which creates Fish functions). They are active in all interactive sessions.

Navigation

..      cd ..
...     cd ../..
....    cd ../../..
.....   cd ../../../..
......  cd ../../../../..

Color Overrides

Force color output for common tools:

grep    grep --color=auto
fgrep   fgrep --color=auto
egrep   egrep --color=auto
dir     dir --color=auto
vdir    vdir --color=auto

Safety Wrappers

Add -i (interactive confirmation) to destructive commands:

cp      cp -i
mv      mv -i

Archives and Networking

tarnow  tar -acf              Create compressed archive (auto-detects format)
untar   tar -zxvf             Extract a gzip-compressed archive
wget    wget -c               Resume interrupted downloads by default
tb      nc termbin.com 9999   Pipe content to termbin.com for quick sharing

System Logs

jctl    journalctl -p 3 -xb   Show priority-3 (error) journal entries
                                from the current boot

5. FUNCTIONS REFERENCE

5.1 File and Directory

cat

Synopsis:  cat [args...]
Wraps bat for files with syntax highlighting and line numbers.
Passes directories to ls. Falls back to /usr/bin/cat.

cat README.md
cat ~/projects/myapp

copy

Synopsis:  copy <source> <dest>
Wraps cp, stripping trailing slashes from source directories to
prevent unintended nesting inside the destination.

copy ./mydir/ ~/backup    # copies mydir INTO backup, not backup/mydir/

du

Synopsis:  du [--disk|--dir|--dua] [args...]
Smart disk-usage dispatcher:
  --disk  force duf  (disk-level free/used overview)
  --dir   force dust (per-directory tree breakdown)
  --dua   force dua  (fast space analyzer)
Without flags, routes to the most appropriate tool by context.

du ~/Downloads
du --disk

dusize

Synopsis:  dusize [dir]
Human-readable disk usage for a directory via du -sh. Defaults to cwd.

dusize ~/Videos

lD

Synopsis:  lD [args...]
Lists directories only in long format with icons. Uses eza, falls back
to lsd, then system ls.

lD ~/projects

ls

Synopsis:  ls [args...]
Lists files in long format with icons and hyperlinks. Uses eza, falls
back to lsd, then system ls.

ls
ls -a ~/projects

lsr

Synopsis:  lsr [args...]
Lists files sorted by modification time, oldest first. Uses eza.

lss

Synopsis:  lss [args...]
Lists files sorted by size with gradient color scaling. Uses eza.

lstree

Synopsis:  lstree [args...]
Full recursive tree view with icons. Uses eza.

lstree ~/projects/myapp

lt

Synopsis:  lt [args...]
Tree view limited to depth 2 with icons. Uses eza.

lt ~/projects

ltr

Synopsis:  ltr [args...]
Lists files sorted by modification time, oldest first, long format with
age-based gradient scaling. Uses eza.

lx

Synopsis:  lx [args...]
Lists files sorted by extension, long format. Uses eza.

mkdir

Synopsis:  mkdir [args...]
Interactive mkdir that prints a tree of created directories.
Falls back to mkdir -p silently.

mkdir ~/projects/myapp/src

mkcd

Synopsis:  mkcd [-s] <dir>
Creates a directory (including parents) and cd into it. Prints a tree
of created dirs by default; -s/--silent suppresses output.

mkcd ~/projects/newapp/src

poke

Synopsis:  poke <file> [file...]
Creates files via touch, automatically creating any missing parent
directories first.

poke ~/projects/new/src/main.fish

rm

Synopsis:  rm [-e [opts] | -S | args...]
Safe rm wrapper routing to trash:

  (no args)   List current trash contents
  -e/--empty  Empty the trash (pass options to trash-empty)
  -S/--secure Permanently delete via rm -rf + fstrim (irreversible)
  -r/-R/--recursive  Move to trash
  <paths>     Move to trash (safe delete)

Falls back to /usr/bin/rm when trash is unavailable.

rm file.txt           # moves to trash
rm -e                 # empty trash
rm -S sensitive.pem   # permanent delete

rg

Synopsis:  rg [args...]
In Kitty, wraps ripgrep with --hyperlink-format=kitty so search
results are clickable file links in the terminal. Falls back to
system rg in any other terminal. All other arguments pass through
unchanged.

rg "fish_greeting" ~/.config/fish/
rg -l "TODO" ~/projects/myapp

scrub

Synopsis:  scrub [-a] [-d] [-h]
Recursively removes OS metadata, editor artifacts, compiler output,
and dev caches using fd.

  -a/--aggressive  Also removes node_modules, logs, .cache, IDE dirs,
                   AI session artifacts
  -d/--dry-run     Print what would be removed without deleting

scrub
scrub -a
scrub -d

5.2 Navigation

cdi

Synopsis:  cdi [query]
Interactive directory picker combining zoxide frecency with fzf.
Equivalent to zi.

cdi myproject

clone

Synopsis:  clone [args...]
Clone a git repository into a new Kitty window. Kitty-only.

clone https://github.com/user/repo.git

clonet

Synopsis:  clonet [args...]
Clone a git repository into a new Kitty tab. Kitty-only.

clonet https://github.com/user/repo.git

5.3 Editors and Viewers

edit

Synopsis:  edit [-V|-t] [-e EDITOR] [-c] [-x TEXT] [-n] [-v|-s] [FILE...]

Opens files in a text editor, choosing a terminal or GUI editor and
resolving a rich chain of fallbacks. With no --visual/--terminal flag the
mode is auto-detected: interactive terminals use the terminal editor
($EDITOR), while detached invocations (e.g. desktop shortcuts) use the GUI
editor ($VISUAL). Clipboard contents and literal strings can be opened as
throwaway temp files. Editor output is suppressed unless --verbose.

GUI fallback chain:      zed → antigravity-ide → code → kate → kwrite →
                         gnome-text-editor → gedit
Terminal fallback chain: nvim → vim → micro → nano → vi

Options:
  -V, --visual      Force the GUI editor ($VISUAL or fallbacks)
  -t, --terminal    Force the terminal editor ($EDITOR or fallbacks)
  -e, --editor=X    Use a specific editor binary X
  -c, --clipboard   Open the clipboard contents (as a temp file)
  -x, --text=STR    Open STR as the contents of a new temp file
  -n, --new         Force a new window/instance (best-effort)
  -v, --verbose     Print the launch command and editor output
  -s, --silent      Suppress all output, including the editor's
  -h, --help        Show this help message

edit ~/.config/fish/config.fish
edit --visual notes.txt
edit --terminal --new todo.md
edit --editor=code --clipboard
edit --text="hello world"

fc

Synopsis:  fc [command_prefix]
Edit the last shell command (or one matching a prefix) in $EDITOR,
then execute the result. Bash-style fc behaviour.

fc
fc git

less

Synopsis:  less [args...]
Pager wrapper with fallback chain: $PAGER -> ov -> less -> more -> cat.

less /var/log/syslog

rawfish

Synopsis:  rawfish [args...]
Launches Fish with NO_TMUX=1, bypassing any tmux auto-attach logic.
Useful when you need a clean shell without session management.

view

Synopsis:  view [args...]
Opens files in nvim read-only mode (-R). Falls back to less.

view /etc/fstab

5.4 Git and Version Control

branch

Synopsis:  branch <branch_name>
Switches to a local branch, or creates it if it does not exist.

branch feature/new-ui

gi

Synopsis:  gi [-h] [-b] [-p] [-s] [-l] [targets...]
Generates .gitignore content from the gitignore.io API with MD5-based
deduplication (patterns already present are not re-appended).

  -b/--boilerplate  Append generic boilerplate first
  -p/--prompt       Prompt interactively for targets
  -s/--stdout       Print to stdout instead of appending to .gitignore
  -l/--list         List all available targets
  targets           Comma-separated or space-separated target names

gi python,venv
gi -b -p
gi -s node > .gitignore

git-clean

Synopsis:  git-clean [-f]
Fetches and prunes the remote, fast-forwards the current branch, then
deletes local branches whose remote tracking branch has been deleted.
Switches to main/master automatically if the current branch is orphaned.

  -f/--force  Force-delete unmerged branches too

git-clean
git-clean --force

gitup

Synopsis:  gitup [args...]
Fetches updates from the remote and shows git status. Extra args are
forwarded to git fetch.

gitup
gitup --all

gitui

Synopsis:  gitui [args...]
Launches gitui with the Catppuccin Frappe theme pre-applied.

hist

Synopsis:  hist
Searches shell history with fzf, inserts the selection into the command
line, and copies it to the clipboard via wl-copy.

5.5 Package Management

pkg

Synopsis:  pkg [-h] [-i|-u] <package> [package...]
Installs or removes packages using the detected system package manager.
Supports: paru, yay, pacman, apt, dnf, zypper, yum, brew, pkg.

  (no flag)    Auto mode: installs missing packages, removes installed ones
  -i/--install  Force install
  -u/--uninstall  Force uninstall

pkg firefox             # auto: install if missing, remove if present
pkg -i ripgrep fd       # force install
pkg -u cowsay           # force uninstall

The package-installed check uses the correct query for each PM:
  pacman/paru/yay  pacman -Qi
  apt              dpkg -s
  dnf/zypper/yum   rpm -q
  brew             brew list
  pkg              pkg info
Synopsis:  search [args...]
Interactive AUR package search and install via paru or yay.
Arch Linux only.

search neovim

upgrade

Synopsis:  upgrade
Full system upgrade via paru -Syu --noconfirm or yay -Syu --noconfirm.
Arch Linux only.

cleanup

Synopsis:  cleanup
Lists and removes orphan packages via pacman, logging their names to
~/.removed_orphans. Arch Linux only.

parur

Synopsis:  parur
Opens an fzf picker of all installed packages (with pacman -Qi previews),
then removes the selected packages via paru or yay. Arch Linux only.

parur

5.6 Dependency Management

fish-deps

Synopsis:  fish-deps [status|install|update|sync]
Unified command for managing all tools this configuration depends on.

  status   (default) Show installed/missing status grouped by tier
  install  Interactively install each missing dependency
  update   Update all installed dependencies
  sync     Install missing deps, then update all

Install method priority (highest to lowest):
  1. git+cargo source build (fish shell itself)
  2. cargo (Rust tools — gets latest crate version)
  3. system PM (paru/apt/brew/etc.)
  4. git clone (fzf)
  5. curl installer (starship, fisher, uv)

When multiple methods are available you are prompted to choose.

Dependencies are grouped into three tiers:

  Required      fish, fzf, zoxide
  Integrations  wakatime, tailscale
  Recommended   cargo, starship, uv, direnv, paru, yay, eza, lsd, bat,
                btop, dust, duf, prettyping, ov, ripgrep, lazygit,
                lazydocker, trash, kitty, wezterm, python3

fish-deps
fish-deps install
fish-deps update
fish-deps sync

check_fish_deps

Synopsis:  check_fish_deps
Backwards-compatibility alias for `fish-deps status`.

5.7 System and Monitoring

top

Synopsis:  top [args...]
Launches btop as a modern resource monitor. Falls back to system top.

swapstat

Synopsis:  swapstat
Displays a colorized memory report: kernel swappiness, zRAM compression
ratio, zRAM device details, and active swap priorities.

sbver

Synopsis:  sbver [--brief]
Verifies Secure Boot signatures on all EFI binaries tracked by sbctl.
Color-codes results: green checkmark (verified), red X (unsigned).
Prints a pass/fail summary.

  --brief  Suppress per-file output, show only the summary

sbver
sbver --brief

ports

Synopsis:  ports
Lists active TCP listeners with lsof, showing port/address without
hostname resolution.

screensleep

Synopsis:  screensleep
Turns off the display via KDE PowerDevil's "Turn Off Screen" action,
invoked through busctl.

lock

Synopsis:  lock
Locks the current desktop session using loginctl lock-session.

sudo-toggle

Synopsis:  sudo-toggle
Toggles the sudo NOPASSWD rule on/off via /etc/sudoers.d/nofail-toggle.
Useful for automated tasks that would otherwise require password entry.

limine-edit

Synopsis:  limine-edit
Opens /boot/limine.conf in sudoedit, then automatically re-enrolls the
config hash, runs CachyOS boot hooks, and re-signs Secure Boot files.
Combines the edit and sign steps into a single command.

5.8 Terminal Management

tab

Synopsis:  tab [args...]
Opens a new tab in Kitty (kitty @ launch --type=tab), WezTerm
(wezterm cli spawn), or Konsole. Uses current working directory,
or $cdto if set.

tab

split

Synopsis:  split [-h|-v] [command...]
Opens a new pane in Kitty or WezTerm, optionally running a command.

  -h/--horizontal  (default) Split below
  -v/--vertical    Split to the right

split
split -v nvim README.md

spwin

Synopsis:  spwin [args...]
Spawns a new terminal OS window in Kitty (via spawn-window.sh or
kitty @ launch --type=os-window) or WezTerm (wezterm cli spawn --new-window).

detach

Synopsis:  detach [-h] [--version] <command> [args...]
Runs a command fully detached via nohup with stdout/stderr discarded.
The command survives the current session.

detach rsync -a ./data remote:/backup/

bkg

Synopsis:  bkg <command> [args...]
Launches a command in the background via nohup with output discarded.
Simpler than detach; no version flag.

bkg firefox

ssh

Synopsis:  ssh [args...]
In Kitty, wraps ssh with kitten ssh for better terminal integration
(multiplexing, copy/paste support). Falls back to system ssh elsewhere.

ssh user@host

5.9 Clipboard

y

Synopsis:  y [text...]
Copies text to the clipboard via wl-copy (Wayland) or xclip (X11).
Reads from stdin if no arguments given.

y "hello world"
ls | y
cat file.txt | y

p

Synopsis:  p [args...]
Outputs clipboard contents to stdout.

p | grep foo
p > file.txt

paste

Alias for p. Identical behaviour.

5.10 Network

gip

Synopsis:  gip
Fetches and prints both the public IPv4 and IPv6 address via
icanhazip.com.

gip4

Synopsis:  gip4
Fetches and prints the public IPv4 address.

gip6

Synopsis:  gip6
Fetches and prints the public IPv6 address. Returns 1 if IPv6 is
unavailable.

ping

Synopsis:  ping [args...]
Wraps prettyping with --nolegend. Pass --legend to show the legend.
Falls back to system ping.

ping google.com

qr

Synopsis:  qr [text...]
Generates a UTF-8 QR code from text or stdin. Uses qrencode locally;
falls back to the qrenco.de API.

qr "https://example.com"
echo "https://example.com" | qr

5.11 Pager and Logging

logs

Synopsis:  logs [-c <category>]
Interactively browses terminal log files sorted newest-first using fzf.

  -c/--category  Filter to: scrollback, paru, or yay

Keybindings inside the fzf browser:
  Enter    Open in $PAGER
  Ctrl+E   Open in $EDITOR
  Ctrl+D   Delete (with confirmation)
  ?        Toggle keybind help overlay

Paru and yay logs open in ov with syntax highlighting and sticky section
headers. Scrollback logs open in ov with per-command sticky prompt headers
based on OSC 133 markers.

logs
logs -c paru
logs -c scrollback

smart_exit

Synopsis:  smart_exit [-n]
Closes the shell session. In Kitty, captures the terminal scrollback to
a timestamped log file in $SCROLLBACK_HISTORY_DIR before exiting.
Automatically prunes the oldest logs when the count exceeds
$SCROLLBACK_HISTORY_MAX_FILES.

  -n/--no-log  Exit without saving a scrollback log

The exit builtin is wired to smart_exit for interactive sessions.
Typing exit or Ctrl+D behaves identically to smart_exit.

smart_exit
smart_exit --no-log

5.12 AI and Developer Tools

agy

Synopsis:  agy [args...]
Wrapper for the agy Antigravity AI CLI. Before launching, delegates to
agents-init --agents to ensure AGENTS/ is scaffolded and CLAUDE.md is
symlinked to AGENTS/AGENTS.md in the current project, then forwards all
arguments verbatim to the real agy binary. Command shadow (C1): when
__fish_config_op_aliases (or the master) is disabled, the call is
passed through to the real agy binary unchanged.

agy chat
agy resume

antigravity-ide

Synopsis:  antigravity-ide [args...]
Runs the antigravity-ide editor with warnings filtered.

agents-init

Synopsis:  agents-init [--agents | --plugins]
Scaffold an AGENTS/ sub-repository for tracking agent specs, plans, specs,
and dev logs. Creates AGENTS/ as a standalone git repo, moves any existing
AGENTS.md into it, and replaces it with a relative symlink (plus
CLAUDE.md -> AGENTS/AGENTS.md so Claude Code picks up the shared agent
instructions). Consolidates plans/ and specs/ directly under AGENTS/
(merging any legacy docs/plans, docs/superpowers/plans, or old
AGENTS/plugins/ locations into the canonical AGENTS/<tgt>), creates
AGENTS/devlogs/, and wires docs/superpowers/{plans,specs} symlinks back to
them. Adds managed paths to .gitignore and auto-commits every change inside
the AGENTS/ sub-repo; pulls first when the sub-repo has an upstream.
Fully idempotent: a second run produces no output and no new commits.
Flags: --agents re-runs only the AGENTS.md / symlink step; --plugins
re-runs only the plans/specs/devlogs wiring step. Called automatically by
the claude and agy wrappers on every invocation.

Structure versioning: each AGENTS/ repo carries a self-contained version
bumper. AGENTS/.version holds MAJOR.MINOR.PATCH (seeded 1.0.0). Committed
git hooks under AGENTS/.agents-tools/ (wired via core.hooksPath) bump it on
every commit: MINOR (resetting PATCH) when the tracked directory set
changes, PATCH otherwise; MAJOR is manual-only. A prepare-commit-msg hook
appends "(vX.Y.Z)" to the commit subject. Downstream tooling can read
AGENTS/.version - a changed MINOR field signals a structure change. Because
core.hooksPath is a single setting, the local override would otherwise
shadow your global hooks; after bumping the version, each shim chains
(execs) to the global/system core.hooksPath hook of the same name so global
pre-commit / prepare-commit-msg hooks (e.g. ggshield, Git LFS) still run.
The script and hooks are shipped from scripts/agents-tools/ and refreshed
when their version marker is stale.

agents-init
agents-init --agents
agents-init --plugins

claude

Synopsis:  claude [args...]
Wrapper for the claude CLI. Before launching, delegates to agents-init
--agents to ensure AGENTS/ is scaffolded and CLAUDE.md is symlinked to
AGENTS/AGENTS.md in the current project, then forwards all arguments
verbatim to the real claude binary. Command shadow (C1): when
__fish_config_op_aliases (or the master) is disabled, the call is
passed through to the real claude binary unchanged.

claude
claude --resume

claude-docs

Synopsis:  claude-docs
Invokes Claude Code to analyze recent repository changes and update
README.md, ensuring all documented features and examples are accurate.

claude-pr

Synopsis:  claude-pr
Invokes Claude Code to run the full PR workflow: create branch,
conventional commit, verification, push, and open a PR with a manual
verification checklist.

superpowers

Synopsis:  superpowers [on|off] [-g]
Enables or disables the Superpowers plugin for Antigravity and Claude
Code at workspace/project scope (default) or user scope (-g/--global).

superpowers on
superpowers off -g

5.13 Media and Utilities

dng2avif

Synopsis:  dng2avif [-i <file>] [-o <file>] [-q <n>] [-s <n>] [input.dng]
Converts a DNG raw image to a 10-bit HDR AVIF using an ImageMagick,
ffmpeg, avifenc pipeline with metadata sync via exiftool.

  -i/--input    Input file (or positional arg)
  -o/--output   Output file (default: same name, .avif extension)
  -q/--quality  Quality 0-100 (default 92)
  -s/--speed    Encoding speed 0-10 (default 3)

dng2avif photo.dng
dng2avif -q 85 -s 5 -i shot.dng -o out.avif

steam-dl

Synopsis:  steam-dl
Launches Steam under systemd-inhibit, preventing the system from going
idle or sleeping while a download is in progress.

spark

Synopsis:  spark [--min=<n>] [--max=<n>] [numbers...]
Renders a Unicode sparkline bar chart for a sequence of numbers.
Reads from stdin if no numbers are given.

spark 1 1 2 5 14 42
echo "3 7 2 9 1" | spark

5.14 Miscellaneous

config-help

Synopsis:  config-help [SECTION]
           config-help [SECTION] --html
           config-help [SECTION] --man
           config-help -h | --help

Opens the offline fish shell configuration manual. Without flags, opens
the Markdown source in the best available pager (ov > bat > man > less >
cat). If SECTION is given, jumps to the first heading matching that
keyword (case-insensitive; checks fish-config.index aliases first).

Flags:
  --html / -w   Open docs/html/index.html in the default browser.
                If SECTION is given, opens at the matching anchor.
                Detects the browser via xdg-mime x-scheme-handler/https,
                then known binaries, then xdg-open as last resort.
                Respects $fish_help_browser and $BROWSER.
  --man  / -m   Open docs/fish-config.1 via man -l directly.
                If SECTION is given, jumps to the nearest match.
  --help / -h   Print usage and navigation key reference.

config-help keybindings
config-help pkg
config-help --html
config-help pkg --html
config-help --man
config-help pkg --man

Also available as: help config [SECTION] [FLAGS]

config-update

Synopsis:  config-update [-h] [-n] [-f]

Pulls the latest fish configuration from the upstream repository
(https://git.rootiest.dev/rootiest/fish-config.git) into ~/.config/fish.
The remote URL is hard-coded, so this works on fresh clones with no git
remote configured. All git output is suppressed; colored messages report
fetch and merge status. After a successful pull, run `exec fish` to
reload.

Flags:
  --dry-run / -n   Fetch and show available commits without applying them.
  --force  / -f    Stash local changes, pull, then restore the stash.
  --help   / -h    Show usage.

config-update
config-update --dry-run
config-update --force

config-toggle

Synopsis:  config-toggle [-h]

Opens an interactive TUI for toggling the six opinionated component
categories (C1C6) and the master disable variable without having to
type or remember variable names. Two scope tabs allow independent
per-scope configuration:

  Universal — persists across all sessions (set -U)
  Session   — current shell only (set -g)

Changes apply immediately on each value keypress. Always available
regardless of the __fish_config_opinionated master state.

The panel adapts to the terminal width automatically, selecting from
four layout tiers (with a 6-column buffer on each side before stepping
up to the next tier) and horizontally centering the box. The panel
redraws within ~0.3 s of a terminal resize with no keypress required.

  COLUMNS >= 90  →  78-wide panel (most detail)
  COLUMNS >= 86  →  74-wide panel
  COLUMNS >= 82  →  70-wide panel
  COLUMNS  < 82  →  52-wide panel (default)

Navigation:
  ↑ ↓ / k j   Move cursor
  ← → / h l   Set value: OFF ← DEFAULT → ON (clamped)
  Tab          Switch scope (Universal ↔ Session)
  q / Escape   Exit

Left/Right (or vim-style h/l) move the highlighted value one step along
the OFFDEFAULTON scale and stop at the ends. DEFAULT erases the
variable so the master switch / built-in default applies.

Flags:
  --help / -h   Show usage.

config-toggle

bash

Synopsis:  bash [args...]
Switches to bash, with XDG config applied. On exit, $SHELL is reset
back to fish.

bd-pull

Synopsis:  bd-pull <owner/repo>
Fetches unlinked Gitea issues and creates local Beads entries, updating
issue titles with the assigned Beads IDs.
Requires $GITEA_TOKEN and $GITEA_URL to be set.

bd-pull rootiest/fish-config

cheat

Synopsis:  cheat <topic> [args...]
Displays a colorized cheatsheet using cheat -c, falls back to tldr,
then man.

cheat tar
cheat git

cffetch / ffetch

Synopsis:  cffetch [args...]  /  ffetch [args...]
Clears the screen and displays system information via fastfetch with
the custom config at ~/.fastfetch.jsonc. Falls back to neofetch.

dockup

Synopsis:  dockup [-h] [directory]
Pulls latest Docker images, restarts services in the given Docker
Compose project, and prunes dangling images.

dockup ~/myapp

joplin

Synopsis:  joplin [args...]
Runs the Joplin CLI with Node.js deprecation warnings suppressed.

joplin ls

ld

Synopsis:  ld
Launches lazydocker targeting the currently active Docker context,
detected via docker context inspect.

replay

Synopsis:  replay <commands>
Runs Bash commands and replays any resulting changes to environment
variables, aliases, and the working directory back into the current
Fish session. Useful for sourcing Bash scripts.

replay "source ~/.bashrc"
replay "export FOO=bar"

kitty-logging

Synopsis:  kitty-logging [install|uninstall|status|dismiss] [-h]

Manages the Kitty scrollback watcher that powers C5 logging. Ships a
canonical, version-marked watcher and installs it into the Kitty config
directory, wiring it into kitty.conf through a sentinel-marked managed
block. Commenting out any conflicting watcher line avoids double-capture.

Commands:
  install    Copy/refresh the watcher and add the managed block
  uninstall  Remove the managed block and the watcher file
  status     Show wiring, installed watcher version, and C5 state
  dismiss    Stop the per-session setup reminder

Runtime capture stays governed by the C5 .logging_disabled sentinel, so
disabling __fish_config_op_logging makes the watcher inert without
uninstalling. Install affects new Kitty windows only.

Example:
  kitty-logging install
  kitty-logging status

tmux-clean

Synopsis:  tmux-clean
Kills all detached (unattached) tmux sessions, leaving attached ones
running.

wake-lock

Synopsis:  wake-lock <command> [args...]
Runs a command under systemd-inhibit, preventing the system from going
idle or sleeping until the command completes.

wake-lock rsync -avz src/ dest/

6. DEPENDENCY CATALOG

fish-deps manages these tools. Run fish-deps to check status, or fish-deps install to install missing ones.

Required

fish      Fish shell >= 4.0
fzf       Fuzzy finder
zoxide    Smart cd with frecency

Integrations

wakatime   Developer time tracking
tailscale  Mesh VPN client
cargo       Rust toolchain (via rustup); used by fish-deps to install
            Rust-based tools and to build fish from source. All paths
            are gated on type -q cargo and degrade gracefully.
starship    Cross-shell prompt; loaded via type -q starship guard.
            Without it the Catppuccin nim-style fallback prompt activates.
uv          Python package and project manager (Astral); used by the
            fish-from-source build path in fish-deps. All consumers
            degrade gracefully without it.
direnv      Per-directory environment loading; integration is fully
            guarded with type -q direnv. Without it the direnv hook
            is simply not loaded and auto-venv activates normally.
paru        AUR helper (Arch only; preferred); guarded throughout —
            non-Arch systems silently skip AUR-specific paths.
yay         AUR helper (Arch only; fallback to paru); same guards apply.
eza         Modern ls replacement
lsd         ls replacement (fallback to eza)
bat         Syntax-highlighted cat
btop        Modern resource monitor
dust        Disk usage tree (Rust)
duf         Disk usage/free overview
prettyping  Colorized ping wrapper
ov          Modern pager (replaces less)
ripgrep     Fast line search
lazygit     Terminal git UI
lazydocker  Terminal docker UI
trash       Safe delete (trash-cli)
kitty       GPU-accelerated terminal (primary)
wezterm     GPU-accelerated terminal (alternative)
python3     Standalone interpreter — used by the paru/yay log cleaner.
            Note: uv does not provide python3 on PATH, and Arch's base
            does not include it, so it is listed separately. All
            consumers degrade gracefully without it.

Install Methods

The install priority for each tool:

cargo     Rust tools (eza, lsd, bat, dust, ov, ripgrep, trashy, zoxide,
          starship) — always gets the latest crate version
system PM paru / apt / brew / dnf / etc. — for tools without a crate
git clone fzf — installed from GitHub to ~/.fzf/
curl      starship installer, fisher bootstrap, uv installer

7. CUSTOMIZATION

Machine-local Configuration

Place machine-specific settings that should not be committed to git in:

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

Typical uses: additional PATH entries, local aliases, hostname-specific env vars, work-specific tool configs.

Secrets and API Keys

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

Store API tokens, GPG keys, private credentials here. This file is never committed.

Both files are sourced at the end of config.fish on every interactive session, so they can override anything set earlier.

Overriding Configuration Variables

Any variable set in local.fish after the main config loads takes effect. Example: to increase the scrollback history limit:

# in local.fish
set -gx SCROLLBACK_HISTORY_MAX_FILES 200

Fish Universal Variables

Some settings (fzf colors, theme) are stored in fish_variables via set -U. These are machine-local and git-ignored. Do not commit fish_variables.

Opinionated Components (Minimal Mode)

Every opinionated piece of this config is active by default but can be switched off through six category opt-out variables, each evaluated via __fish_variable_check. Set a variable to any falsy value (0, false, no, off, n) to disable its category; erase it or set a truthy value (1, true, yes, on, y) to re-enable. Unset means enabled.

An explicit per-category truthy value takes precedence over the master switch: setting __fish_config_opinionated=0 disables all unset categories, but a category with an explicit truthy value remains enabled regardless.

Variable                        Disables
------------------------------  ------------------------------------
__fish_config_op_aliases        Command shadows and flag injection:
                                ls->eza, cat->bat, cd->zoxide,
                                rm->trash, less->ov, top->btop,
                                ping->prettyping, ssh->kitten,
                                du->duf/dust, mkdir/bash wrappers,
                                history timestamps, grep/cp/mv/wget
                                flag injection, help intercept, claude
                                AGENTS.md auto-link
__fish_config_op_autoexec       Startup side-effects: Fisher
                                bootstrap, theme apply, paru/yay
                                wrapper generation, auto venv
                                activation, WakaTime hook
__fish_config_op_overrides      Key and env overrides: Vi mode,
                                exit->smart_exit, PAGER/MANPAGER,
                                CDPATH, bang-bang system, autopair,
                                puffer, starship prompt, theme
                                colors, FZF_DEFAULT_OPTS, right
                                prompt
__fish_config_op_integrations   Terminal/tool coupling: Kitty/
                                WezTerm window abbreviations, done
                                notifications, spwin/tab/split,
                                hist, logs, upgrade, WakaTime
__fish_config_op_logging        Logging & capture: scrollback
                                capture on exit, paru/yay AUR log
                                wrappers, Kitty watcher capture;
                                sentinel file coordinates
                                cross-process state
__fish_config_op_greeting       Greeting & first-run UI: per-session
                                fish_greeting override (defines empty
                                function late in config.fish to
                                suppress distro greetings such as
                                CachyOS fastfetch); first-run welcome
                                banner in conf.d/first_run.fish

Examples:

# Disable command shadows only (rm becomes plain rm again):
set -U __fish_config_op_aliases off

# Full minimal mode — disable all six categories at once:
set -U __fish_config_opinionated 0

# Re-enable everything:
set -Ue __fish_config_opinionated

# Minimal mode but keep the greeting:
set -U __fish_config_opinionated 0
set -U __fish_config_op_greeting 1
# (erase both to go back to full-flavor defaults)

For an interactive alternative to setting these variables by hand, run config-toggle — a full-screen TUI that flips any category (including C5 logging) on or off, per session or universally. See its entry in Section 5.

Notes:

  • Command shadows (rm, cat, ls, ...) react immediately; conf.d-level components (bindings, prompt, abbreviations, hooks) take effect in new shells.
  • With aliases disabled, rm falls back to bare command rm — files are deleted permanently, not trashed.
  • Disabled integration commands (spwin, tab, split, hist, logs, upgrade) print an error naming the variable that disabled them.
  • On CachyOS, the distro fish config's own aliases, history override, and bang-bang bindings are stripped per category as well.

Component Reference

The following tables detail every component in each category. Use this reference to understand exactly which behaviors change when you toggle a category variable.

C1 — Command Shadows

Disabling __fish_config_op_aliases restores standard system behavior for all of these commands.

Command / Alias    Active behavior                       Disabled fallback
───────────────────────────────────────────────────────────────────────────
ls                 eza -l -a --icons --hyperlink          system ls
cat                bat syntax-highlighted; dirs → ls      /usr/bin/cat
cd                 zoxide frecency-based navigation        fish builtin cd
rm                 moves files to trash (recoverable)     command rm (permanent)
less               $PAGER → ov → less → more → cat       system less
du                 duf (disk overview) or dust (dir tree) system du
top                btop resource monitor                  system top
ping               prettyping --nolegend animation        system ping
ssh                kitten ssh in Kitty terminal           system ssh
rg                 rg --hyperlink-format=kitty            system rg
mkdir              verbose path-tree display on creation  mkdir -p silently
bash               XDG bashrc + $SHELL reset on exit      system bash
history            timestamps prepended to every entry    fish builtin history
cp / mv            forced -i confirmation prompt          cp / mv unmodified
wget               forced --continue (resume downloads)   system wget
grep/fgrep/egrep   forced --color=auto                    system grep variants
dir / vdir         forced --color=auto                    system dir / vdir
help config        intercepts "help config" → config-help fish builtin help
claude             auto-links AGENTS.md as CLAUDE.md before launch command claude
edit               multi-editor launcher (GUI/term + fallbacks)  $EDITOR/nvim/nano/vi

When C1 is disabled, rm uses bare command rm with no wrapper — files are permanently deleted, not trashed. There is no intermediate safety net.

C2 — Startup Side-Effects

These run automatically without any user action. Disabling __fish_config_op_autoexec prevents all of them.

Component                  Trigger              What it does
───────────────────────────────────────────────────────────────────────────
Fisher bootstrap           First shell only     Downloads and installs fisher
Fisher update              After bootstrap      Installs all fish_plugins entries
Catppuccin Mocha theme     First shell only     Applies theme via fish_config
paru wrapper               Every startup        Writes ~/.local/bin/paru wrapper
yay wrapper                Every startup        Writes ~/.local/bin/yay wrapper
Python venv activation     On every cd          Sources .venv/bin/activate.fish
WakaTime command hook      On every command     Reports to WakaTime API

When C2 is disabled: no Fisher install, no theme application, no paru/yay wrapper generation, no automatic venv activation, and no WakaTime reporting. The first-run completion marker (__fish_config_first_run_complete) is still set so the init does not re-run on subsequent shells.

Python venv activation fires on every directory change. If a directory uses direnv (.envrc present), direnv takes priority and auto-venv is skipped for that directory.

C3 — Key and Environment Overrides

These change fundamental shell behavior: how keys work, which pager opens, and what the prompt looks like. Disabling __fish_config_op_overrides removes all of them.

Override                  What it replaces or sets
───────────────────────────────────────────────────────────────────────────
Vi mode                   fish_vi_key_bindings replaces default Emacs mode
exit → smart_exit         exit wrapper that captures scrollback before closing
PAGER=ov                  ov used by git, man, and all $PAGER-aware tools
MANPAGER=bat pipeline     man pages rendered with syntax highlighting
CDPATH=. ~/projects ~     bare dir names resolve against ~/projects and ~
Bang-bang system          ! and $ keys expand history; !^, !*, !-N, !?str?,
                          ^old^new abbreviations; six expand_bang_* helpers
Autopair                  ( [ { " ' auto-close to (), [], {}, "", ''
Puffer key intercepts     . ! $ * keys intercepted for smart expansion
Starship prompt           fish_prompt replaced by Starship + OSC 133 markers
Catppuccin colors         30+ fish_color_* variables set to Mocha palette
FZF_DEFAULT_OPTS          FZF themed to Catppuccin Mocha colors
Right prompt              fish_right_prompt: exit code (on failure) + dim timestamp; always rendered; Docker context added when starship+C3 active

The bang-bang system spans key_bindings.fish, abbr.fish, puffer.fish, and six expand_bang_*.fish functions. All are gated together — disabling C3 removes the entire bang-expansion system at once.

When C3 is disabled, exit falls back to builtin exit with no scrollback capture, no Kitty IPC, and no file I/O on exit. The scrollback capture block is independently controlled by C5 (see below).

C4 — Terminal and Tool Integration

These features couple the shell to specific external tools. Disabling __fish_config_op_integrations disables all of them.

Component                  Requires
───────────────────────────────────────────────────────────────────────────
~60 Kitty/WezTerm abbrs    Active Kitty or WezTerm session
  (:w, :wv, :wh, :t, etc.)
Done desktop notifications Graphical desktop with a notification daemon
spwin                      Kitty or WezTerm
tab                        Kitty, WezTerm, or Konsole
split                      Kitty or WezTerm
hist                       fzf + wl-copy (Wayland clipboard)
logs                       fzf + ov; reads from ~/.terminal_history/
upgrade                    paru or yay (Arch Linux only)
WakaTime hook              wakatime CLI and a configured API key

Disabled integration commands (spwin, tab, split, hist, logs, upgrade) print a colored error to stderr naming the variable that disabled them rather than silently failing.

C5 — Logging and Capture

Five components capture shell output to disk. Disabling __fish_config_op_logging skips all capture and removes the logging wrappers.

Component               What it captures
───────────────────────────────────────────────────────────────────────────
Scrollback capture      Terminal session output saved to:
                        ~/.terminal_history/scrollback_YYYY-MM-DD_HH-MM-SS.log
tmux pane capture       Continuous pane stream via pipe-pane, saved to:
                        ~/.terminal_history/tmux_<session>-w<win>-p<pane>_YYYY-MM-DD_HH-MM-SS.log
zellij pane capture     Pane scrollback snapshot on shell exit, saved to:
                        ~/.terminal_history/zellij_<session>-p<pane>_YYYY-MM-DD_HH-MM-SS.log
paru wrapper            All paru/AUR output captured to:
                        ~/.terminal_history/paru_YYYY-MM-DD_HH-MM-SS.log
yay wrapper             All yay/AUR output captured to:
                        ~/.terminal_history/yay_YYYY-MM-DD_HH-MM-SS.log
Kitty watcher           watcher.py captures scrollback when Kitty closes

The tmux capture starts automatically when fish launches inside any tmux pane ($TMUX is set). It uses tmux's native pipe-pane to stream all pane output directly to disk without an intermediate process. Each fish shell session gets its own log file; a new log is created on each shell start (including exec fish and new splits). Before each new log, the oldest tmux_*.log files are pruned (by modification time) to keep the total within SCROLLBACK_HISTORY_MAX_FILES, matching the paru/yay wrapper behaviour.

The zellij capture works differently: Zellij has no live output-streaming facility like pipe-pane, so the log is taken as a one-shot snapshot when the shell exits, via zellij action dump-screen --full --ansi (the --ansi flag preserves color). The dump is captured on the fish process's stdout and written to the log file by fish itself (not via --path, which would make the zellij server write the file). A fish_exit handler (registered whenever $ZELLIJ is set) writes the pane's full scrollback and then prunes old zellij_*.log files the same way. Because the capture happens at exit, toggling __fish_config_op_logging takes effect on the next exit with no restart or sentinel coordination needed — the C5 guard is re-checked when the handler fires.

LIMITATION — zellij capture only fires on a clean shell exit (typing exit, Ctrl-D, or a logout), because that is when the fish_exit handler runs. It does NOT capture when you close a pane or quit zellij through zellij itself:

  • Closing a pane signals the shell and tears the pane down concurrently, so even if the handler runs, dump-screen may find the pane buffer already gone.
  • Quitting zellij kills the zellij server, and dump-screen needs a live server to read from — there is nothing left to snapshot.

This is a structural difference from tmux, NOT a bug. tmux streams pane output to disk continuously via pipe-pane, so whatever was printed is already saved no matter how the pane dies. Zellij can only snapshot, and the only reliable snapshot point from the shell is a clean exit. To guarantee a zellij pane is logged, end the session with exit or Ctrl-D rather than zellij's close-pane or quit actions.

The Kitty watcher is managed by the kitty-logging command: it installs a version-marked watcher (fish-config-watcher.py) into the Kitty config directory and wires it into kitty.conf via a managed block. Inside Kitty, a non-blocking per-session reminder points first-time users at kitty-logging install until they install or run kitty-logging dismiss. Install affects new Kitty windows only; runtime disable is still handled by the .logging_disabled sentinel.

Logging coordination via sentinel file

C5 uses a sentinel file to synchronize state between the shell and out-of-process components (the Kitty watcher and all running shells):

~/.config/fish/.logging_disabled

Disabling __fish_config_op_logging:

  1. Creates the sentinel immediately in every open shell.
  2. Removes ~/.local/bin/paru and ~/.local/bin/yay logging wrappers; bare /usr/bin/paru and /usr/bin/yay are used instead.
  3. Kitty's watcher.py reads the sentinel on each save attempt and skips capture — no Kitty restart required.
  4. smart_exit stops saving scrollback logs.
  5. Stops tmux pipe-pane capture in every open fish shell inside tmux.

Re-enabling __fish_config_op_logging:

  1. Removes the sentinel in every open shell.
  2. Regenerates paru/yay logging wrappers in ~/.local/bin/.
  3. Kitty watcher resumes capture on the next session exit.
  4. Restarts tmux pipe-pane capture in every open fish shell inside tmux.

Changes propagate to all running shells through an event handler that fires whenever __fish_config_op_logging changes — no shell restart needed.

Note: C3 and C5 compose independently. C3 controls whether the smart_exit wrapper is active at all; C5 controls only the scrollback-capture block inside it. With C3 disabled, exit is plain builtin exit regardless of C5.

C6 — Greeting and First-Run UI

Component                  What it shows
───────────────────────────────────────────────────────────────────────────
First-run welcome banner   One-time message on first interactive session
fish_greeting override     Empty function defined late in config.fish to
                           suppress distro greetings (e.g. CachyOS sets
                           fish_greeting to fastfetch by default)

When C6 is disabled, no greeting is printed by this config. Any greeting set by the distro or other configs runs normally — this config simply does not override it.

Prompt and Theme

Starship

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

conf.d/starship.fish defines a fish_prompt wrapper that only activates when starship is in PATH. It emits OSC 133;A (prompt start) immediately before Starship renders and OSC 133;B (input start) immediately after, placing both markers on the prompt line itself. This allows ov to use them as sticky section headers when browsing scrollback logs. Without Starship, fish's built-in prompt handles these markers automatically.

Catppuccin Fallback Prompt

When Starship is absent or C3 overrides are disabled, a built-in nim-style two-line prompt activates from functions/fish_prompt.fish. No external dependencies — fish builtins only.

Layout:

┬─[user@host:~/path] (main)
╰─>$

Elements:

user        Yellow (Catppuccin Yellow); red if root
@host       Blue (local) or Teal (SSH)
~/path      prompt_pwd abbreviation (Catppuccin Text)
(main)      Current git branch in Catppuccin Pink; omitted outside repos
─[V:name]   Active Python venv basename; omitted when none
─[N/I/R/V]  Vi-mode indicator when vi bindings are active
┬─ / ╰─>    Connector lines: Catppuccin Green on success, Red on failure

The right prompt (fish_right_prompt.fish) always renders, regardless of C3 state. On failure it shows a red ✘ and the exit code; on success it shows only the dim timestamp. When starship is installed and C3 is enabled, the active Docker context is also shown (if non-default):

✘ 1   󰡨 myctx   Fri Jun 12 00:51:21 2026     ← failed, starship+C3 active
✘ 1   Fri Jun 12 00:51:21 2026               ← failed, fallback prompt
Fri Jun 12 00:51:21 2026                     ← success (no ✘)

FZF

FZF is themed to Catppuccin Mocha via FZF_DEFAULT_OPTS set in integrations/fzf.fish. The colors applied:

Background:   #1E1E2E (base)    #313244 (surface0)
Foreground:   #CDD6F4 (text)
Highlights:   #F38BA8 (red)     #CBA6F7 (mauve)    #B4BEFE (lavender)

To customize, override FZF_DEFAULT_OPTS in local.fish.

Catppuccin Mocha Syntax Highlighting

The Catppuccin Mocha theme ships with this config in themes/ and is applied on first run via conf.d/first_run.fish. Colors are stored in fish_variables (universal). To switch variants, install a different theme from themes/:

fish_config theme save "Catppuccin Latte"

8. FISHER PLUGINS

Fisher is bootstrapped automatically on the first interactive session via conf.d/first_run.fish. This also applies the Catppuccin Mocha theme and prints a one-time welcome message (gated by __fish_config_op_greeting; set it to 0 to suppress). Subsequent sessions skip all first-run logic with zero overhead.

To re-trigger first-run initialization (e.g., after a fresh install or for testing), run:

set -Ue __fish_config_first_run_complete

Then open a new shell.

Fisher-Managed Plugins

The following plugins are fully managed by Fisher. Their files are installed into the repo directory by Fisher and are listed in .gitignore — do not commit them. Fisher installs and updates them automatically.

jorgebucaran/fisher           Plugin manager itself
meaningful-ooo/sponge         Remove failed commands from history

Sponge History Filtering

Sponge removes failed commands from history and, via conf.d/sponge_privacy.fish, also filters privacy-sensitive commands through three layers:

Layer 1 — Static patterns (universal, persistent across sessions): Commands matching any of these structural signatures are never recorded:

--password / --token / --passphrase / --api-key flags with values
Inline env assignments: GITHUB_TOKEN=xxx, MY_API_KEY=abc
Fish set with sensitive names: set -gx GITHUB_TOKEN xxx
URLs with embedded credentials: https://user:pass@host
HTTP Authorization headers: curl -H "Authorization: ..."
Basic auth flags: curl -u user:pass
sshpass, docker login -p, openssl -passin/-passout

Layer 2 — Dynamic secret values (session globals, refreshed each login): On the first prompt, after secrets.fish has loaded, the literal values of all exported variables whose names suggest credentials (TOKEN, PASSWORD, SECRET, API_KEY, etc.) are collected, regex-escaped, and added as a session-scoped overlay. Because globals shadow universals in Fish, the combined list is what sponge sees. Rotating a token takes effect on the next login automatically.

Layer 3 — Per-command filter (sponge_filter_secrets): Catches credentials in variables exported after login, such as tokens sourced from a project .env file mid-session.

To add your own persistent patterns:

set -U -a sponge_regex_patterns 'your-regex-here'

Bundled Plugin Functionality

The remaining plugin functionality is bundled directly with this config rather than managed through Fisher. The bundled versions include customizations for Fish 4.x compatibility and improved behavior that differ from their upstream releases. Installing them through Fisher would overwrite these customizations.

Bundled components and their upstream origins:

catppuccin/fish               → themes/ + conf.d/theme.fish
PatrickF1/fzf.fish            → functions/_fzf_*.fish + conf.d/fzf.fish
franciscolourenco/done        → conf.d/done.fish
jorgebucaran/autopair.fish    → functions/_autopair_*.fish + conf.d/autopair.fish
nickeb96/puffer-fish          → functions/_puffer_fish_*.fish + conf.d/puffer.fish

Do not run fisher install for these — it will overwrite the customized versions. To update their behavior, edit the relevant bundled files directly.

fish_plugins Manifest

The fish_plugins file at the config root:

jorgebucaran/fisher           Plugin manager itself
meaningful-ooo/sponge         Remove failed commands from history

To update all Fisher-managed plugins, run fisher update or fish-deps update which calls it as its first step.


9. INSTALLATION

This configuration is managed as a git repository. To deploy on a new machine:

mv ~/.config/fish ~/.config/fish.bak   # back up any existing config
git clone https://git.rootiest.dev/rootiest/fish-config.git ~/.config/fish

Then open a new Fish shell. Fisher installs automatically on first launch and the Catppuccin Mocha theme is applied. All other plugin functionality is bundled directly with this config and requires no additional installation.

Return Sentinel

config.fish ends with a return sentinel guard. Any lines appended after it by a tool's setup command (starship init fish | source, zoxide init fish | source, etc.) will have no effect. All integrations are managed via conf.d/ files.

If a new tool's shell integration appears to do nothing, check whether its setup command appended an init line below the sentinel and create a dedicated conf.d/.fish instead.

Updating

Pull the latest changes from the upstream repository without needing a configured git remote:

config-update              Fetch and apply the latest commits from upstream
config-update --dry-run    Preview available changes without applying them
config-update --force      Stash local changes, pull, then restore the stash

The remote URL (https://git.rootiest.dev/rootiest/fish-config.git) is hard-coded, so this works on a fresh clone with no origin configured. All git output is suppressed. Run exec fish after a successful update to reload.


10. PERSONALIZATION

Sensitive credentials and machine-specific settings are kept out of version control in a 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

fish_variables (auto-managed by fish) is excluded from this repo via .gitignore. Do not commit it.

secrets.fish

Store anything you would not commit to a public repo: API keys, auth tokens, passwords, and personal identifiers.

set -gx MY_NAME "Your Name"
set -gx MY_EMAIL "you@example.com"
set -gx GPG_RECIPIENT "you@example.com"
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 KOPIA_PASSWORD yourKopiaPassword

local.fish

Store paths and variables specific to one machine — things that would be wrong on any other system.

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

# Path to your shared .gitignore boilerplate
set -gx GITIGNORE_BOILERPLATE ~/.config/git/gitignore_boilerplate

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

# Docker context shortcuts
abbr -a dcr 'docker context use my-remote-server'
abbr -a dcw 'docker context use work-server'

Both files are sourced at the end of config.fish with an existence check so the public config works cleanly on any machine without the private repo.


11. VIEWING THIS MANUAL

help config

ov renders the Markdown with syntax highlighting and section-based navigation.

Space       next section
^           previous section
Alt+u       toggle section list sidebar
/           search forward
n / N       next / previous search match
g           go to line number
j           interactive jump target (line, %, or 'section')
q           quit

With bat

bat --language=markdown --paging=always ~/.config/fish/docs/fish-config.md

As a man page

help config --man
help config pkg --man

Opens the compiled docs/fish-config.1 directly via man -l, bypassing the pager fallback chain. If a section keyword is given, the pager opens at the nearest matching heading. The symlink is created once on first run (like an install step) and MANPATH is set each session, enabling the standard invocation:

man fish-config

NOTE: fish-config (hyphen) is this config's man page. fish_config (underscore) is fish's built-in browser-based configuration tool — a completely separate command. Do not mix them up.

In the browser (HTML)

help config --html
help config pkg --html

Opens docs/html/index.html in the default web browser. If a section keyword is given, the browser opens directly at the matching anchor (resolved via docs/html/sitemap.json). Browser detection queries the system's x-scheme-handler/https MIME entry (via xdg-mime) to find the real browser binary, then falls back through known browser binaries (firefox, chromium, vivaldi, etc.), and finally xdg-open as a last resort. Set $fish_help_browser or $BROWSER to override.

As a wiki

The generated Markdown wiki lives in docs/wiki/. index.md provides the project overview and a full table of contents. Each section page has a navigation bar at the top linking to every other section.

The wiki is auto-generated from this file by the CI pipeline on every push to main that changes docs/fish-config.md.

Jumping to a section

help config keybindings
help config abbreviations
help config pkg
help config logs
help config fish-deps

The keyword is matched case-insensitively against section headings.