Files
fish-config/config.fish
T
rootiest 8495cbaa24 feat(config): auto-manage user-dots convenience symlink
Point $__fish_config_dir/user-dots at $__fish_user_dots_path on interactive
startup so the private overlay can be browsed from the fish config dir. The
link is created if missing and repointed if the path variable changes, only
ever managing a symlink (never clobbering a real file/dir). Gated as a C2
startup side-effect (__fish_config_op_autoexec) and git-ignored.

Docs: README overlay section and fish-config.md C2 table updated.
2026-07-04 02:24:37 -04:00

276 lines
17 KiB
Fish

# Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
# ╭──────────────────────────────────────────────────────────╮
# │ Fish Configuration │
# ╰──────────────────────────────────────────────────────────╯
# ───────────────────── Opinionated component guards ─────────────────────
# Opinionated components (AGENTS.md Task #3) are wrapped in
# __fish_config_op_enabled <category> guards throughout this file and conf.d/.
# The helper always evaluates the master switch __fish_config_opinionated
# first (falsy disables everything), then the per-category opt-out variable:
# __fish_config_op_aliases C1 — command shadows / flag injection
# __fish_config_op_autoexec C2 — startup side-effects
# __fish_config_op_overrides C3 — key bindings, env, prompt overrides
# __fish_config_op_integrations C4 — terminal/tool coupling
# __fish_config_op_logging C5 — scrollback capture / AUR log wrappers
# __fish_config_op_greeting C6 — per-session greeting / first-run welcome
# Example: set -U __fish_config_op_aliases off (erase to re-enable)
# ──────────────────────── Source CachyOS configs ────────────────────────
if test -f /usr/share/cachyos-fish-config/cachyos-config.fish
source /usr/share/cachyos-fish-config/cachyos-config.fish
# Surgically overriding the distro config is opinionated (C3 overrides):
# skip it entirely when overrides are disabled, keeping CachyOS defaults.
if __fish_config_op_enabled __fish_config_op_overrides
# Source our tricks over the cachyOS config
test -f "$__fish_config_dir/conf.d/tricks.fish"
and source "$__fish_config_dir/conf.d/tricks.fish"
# Erase CachyOS aliases/functions that shadow our versions, then
# re-source our versions since functions --erase removes autoload entries.
for _fname in ls lt cleanup copy
functions --erase $_fname
source "$__fish_config_dir/functions/$_fname.fish"
end
end
# The distro config ships opinionated pieces of its own (it is the origin
# of tricks.fish); strip them when the matching category is disabled so
# the guards hold on CachyOS systems too.
if not __fish_config_op_enabled __fish_config_op_aliases
for _fname in grep fgrep egrep dir vdir wget
functions -q $_fname; and functions --erase $_fname
end
# Restore fish's stock versions where they exist (erasing alone would
# also block autoloading the stock function).
for _fname in history ls
functions -q $_fname; and functions --erase $_fname
test -f $__fish_data_dir/functions/$_fname.fish
and source $__fish_data_dir/functions/$_fname.fish
end
end
if not __fish_config_op_enabled __fish_config_op_overrides
for _fname in __history_previous_command __history_previous_command_arguments
functions -q $_fname; and functions --erase $_fname
end
bind --erase ! 2>/dev/null
bind --erase '$' 2>/dev/null
bind -M insert --erase ! 2>/dev/null
bind -M insert --erase '$' 2>/dev/null
end
end
set --erase _fname
# ───────────────────────────── XDG variables ────────────────────────────
# XDG Base Directory variables (standard practice)
set -gx XDG_CONFIG_HOME $HOME/.config # Sets default config dir to ~/.config
set -gx XDG_CACHE_HOME $HOME/.cache # Sets default cache dir to ~/.cache
set -gx XDG_DATA_HOME $HOME/.local/share # Sets default data dir to ~/.local/share
set -gx XDG_STATE_HOME $HOME/.local/state # Sets default state dir to ~/.local/state
# Attempt to keep various config/cache files out of the home directory root
set -gx RANDFILE "$XDG_STATE_HOME/rnd"
set -gx WGETRC "$XDG_CONFIG_HOME/wget/wgetrc"
set -gx WGET_HSTS_FILE "$XDG_CACHE_HOME/wget-hsts"
set -gx NPM_CONFIG_PREFIX "$XDG_DATA_HOME/npm-global"
set -gx NPM_CONFIG_USERCONFIG "$XDG_CONFIG_HOME/npm/npmrc"
set -gx ANDROID_USER_HOME "$XDG_DATA_HOME/android"
set -gx CARGO_HOME "$XDG_DATA_HOME/cargo"
set -gx RUSTUP_HOME "$XDG_DATA_HOME/rustup"
set -gx GOPATH "$XDG_DATA_HOME/go"
set -gx BUN_INSTALL "$XDG_DATA_HOME/bun"
set -gx GNUPGHOME "$XDG_CONFIG_HOME/gnupg"
set -gx WAKATIME_HOME "$XDG_CONFIG_HOME/wakatime"
set -gx HISTFILE "$XDG_STATE_HOME/bash_history"
set -gx EXINIT "set viminfofile=$XDG_STATE_HOME/vim/viminfo | source $MYVIMRC"
set -gx NVIDIA_SETTINGS_RW_CONFIG_FILE "$XDG_CONFIG_HOME/nvidia/settings"
set -gx CODEIUM_HOME "$XDG_CONFIG_HOME/codeium"
set -gx WORDLIST "$XDG_CONFIG_HOME/hunspell_en_US"
# ─────────────────────────── Pager variables ────────────────────────────
# Overriding $PAGER is opinionated (C3 overrides)
if __fish_config_op_enabled __fish_config_op_overrides
if type -q ov
set -gx PAGER ov
else if type -q less
set -gx PAGER less
end
end
# ─────────────────────────── Editor variables ───────────────────────────
# Set Editor variables with fallback to vi if nvim isn't available. This ensures that
# tools that rely on these variables (like git commit messages) will work out of the box,
# while still preferring nvim if it's installed.
if type -q nvim
set -gx NVIM_APPNAME nvim
set -gx EDITOR (command -s nvim)
else
set -gx EDITOR (command -s vi)
end
# set -gx VISUAL $EDITOR # <- Use local.fish to set your preferred GUI editor.
set -gx SUDO_EDITOR $EDITOR
# ──────────────────────────── GPG variables ─────────────────────────────
# Helps ensure that GPG can prompt for passphrases correctly when invoked from the terminal.
set -gx GPG_TTY (tty)
# ────────────────────────── Scrollback History ──────────────────────────
# Optional fish-style source of truth (set -U via config-settings); exported
# for the POSIX wrappers (paru/yay/tmux/zellij/_prune_terminal_logs) that read
# them. We export the default unconditionally, then override from the universal
# var only if set — deliberately NOT creating a global, which would shadow the
# universal and stop live edits (config-settings → Paths) from taking effect.
set -gx SCROLLBACK_HISTORY_DIR "$HOME/.terminal_history"
set -q __fish_scrollback_history_dir
and set -gx SCROLLBACK_HISTORY_DIR $__fish_scrollback_history_dir
set -gx SCROLLBACK_HISTORY_MAX_FILES 100
set -q __fish_scrollback_history_max_files
and set -gx SCROLLBACK_HISTORY_MAX_FILES $__fish_scrollback_history_max_files
# Wire up a clean exit function that won't fire on background subshells
# Replacing the exit builtin is opinionated (C3 overrides); smart_exit also
# guards itself so a live toggle takes effect without restarting the shell.
if status is-interactive; and __fish_config_op_enabled __fish_config_op_overrides
function exit --description 'Safe interactive exit'
# If the smart_exit file exists in our function path, invoke it explicitly
if functions -q smart_exit
smart_exit $argv
else
# Absolute fallback to protect shell mechanics
builtin exit $argv
end
end
end
# ──────────────────────────── PATH variables ────────────────────────────
# Adds common user bin directories to the PATH. The -mg --move option for cargo ensures that
# the cargo bin directory is moved to the end of the PATH, which can help avoid conflicts
# with system-installed Rust tools while still allowing user-installed cargo binaries to be found.
fish_add_path $HOME/.local/bin # Standard user-local executables (XDG spec)
fish_add_path $HOME/.local/share/../bin # Alternative/legacy path for local user binaries
fish_add_path $HOME/Applications # User-installed applications and standalone apps
fish_add_path $HOME/scripts # Custom personal shell scripts and automation
fish_add_path -mga $CARGO_HOME/bin # Rust binaries and tools installed via Cargo
fish_add_path $BUN_INSTALL/bin # Bun runtime executables and globally installed packages
fish_add_path $XDG_DATA_HOME/npm-global/bin # Global Node.js/npm packages (XDG compliant location)
fish_add_path $HOME/.lmstudio/bin # LM Studio CLI tools for local LLM management
fish_add_path $HOME/.resend/bin # Resend email service CLI tools
fish_add_path $HOME/.fzf/bin # Fuzzy Finder (fzf) core binary and helper scripts
# ───────────────────────── CDPATH projects dir ──────────────────────────
# Allows cd-ing to directories within $HOME/projects or $HOME without needing to specify the full path.
# For example, if you have a project at $HOME/projects/myproject,
# you can simply run 'cd myproject' from anywhere and it will take you there.
# 'cd' command prioritizes directories in CDPATH, so if you have a directory with
# the same name in both $HOME/projects and $HOME, it will take you to the one in $HOME/projects first.
# Additionally, directories inside the CWD will still take precedence over CDPATH,
# so if you have a directory named 'myproject' in the current directory,
# running 'cd myproject' will take you there instead of $HOME/projects/myproject.
# CDPATH injection is opinionated (C3 overrides)
if __fish_config_op_enabled __fish_config_op_overrides
set -gx CDPATH . $HOME/projects $HOME
end
# ──────────────────────────── Bootstrap Fisher ──────────────────────────
# Fisher is bootstrapped automatically on first run via conf.d/first_run.fish
# ─────────────────────── Visual/Interactive setup ───────────────────────
# Run only if we're in an interactive session (not a script or non-interactive shell)
if status is-interactive
# ────────────────────────────── Key bindings ────────────────────────────
# Helps ensure that key bindings are consistent with the Vi editing mode set below.
# This is optional but can improve the user experience for those who prefer Vi-style key bindings.
# Global Vi mode is opinionated (C3 overrides); without it fish keeps its
# default Emacs-style bindings.
if __fish_config_op_enabled __fish_config_op_overrides
set -g fish_key_bindings fish_vi_key_bindings
end
# ──────────────────────── Source FZF integration ────────────────────────
# Prefer fzf's own fish integration (fzf --fish, available since fzf 0.48)
# which is always version-matched to the installed binary. Fall back to our
# bundled integrations/fzf.fish for older builds.
# Run `fzf-update` to install/upgrade fzf from git HEAD.
if type -q fzf
set -l _fzf_minor (fzf --version | string match -r '^\d+\.(\d+)')[2]
if test -n "$_fzf_minor" -a "$_fzf_minor" -ge 48
fzf --fish | source
else
test -f "$__fish_config_dir/integrations/fzf.fish"
and source "$__fish_config_dir/integrations/fzf.fish"
end
else
# conf.d/fzf.fish is managed by Fisher and may be restored on fisher
# update, so this is the reliable place to strip its bindings when
# fzf is not installed.
functions -q _fzf_uninstall_bindings; and _fzf_uninstall_bindings
end
# ──────────────────────────────── DirENV ────────────────────────────────
# Tool to handle automatic environment loading in directories and their children
# Use when children need to load venv as well.
#
# The Auto-Venv script above will ignore directories with a
# .envrc file (direnv configuration) to prevent conflicts.
type -q direnv; and direnv hook fish | source
# Helps ensure that Claude Code's terminal output is clean and doesn't have flickering issues.
set -gx CLAUDE_CODE_NO_FLICKER 1
# ╭────────────────────────────── OVERRIDES ─────────────────────────────╮
# │ Run these last so they can override any previous settings. │
# │ This is useful for machine-specific behavior or configurations. │
# ╰────────────────────────────── OVERRIDES ─────────────────────────────╯
#
# Resolve user-dots path. Customize via: set -U __fish_user_dots_path /your/path
set -q __fish_user_dots_path
or set -l __fish_user_dots_path "$XDG_CONFIG_HOME/.user-dots/fish"
# ────────────────────── user-dots convenience symlink ───────────────────
# Keep $__fish_config_dir/user-dots pointing at the resolved path so it can
# be browsed from the fish config dir. Git-ignored; a C2 startup side-effect.
# Only ever manages a symlink — never clobbers a real file/dir placed there.
if __fish_config_op_enabled __fish_config_op_autoexec
set -l __udots_link "$__fish_config_dir/user-dots"
if test -d "$__fish_user_dots_path"
if test -L "$__udots_link"
test (readlink "$__udots_link") != "$__fish_user_dots_path"
and ln -sfn "$__fish_user_dots_path" "$__udots_link"
else if not test -e "$__udots_link"
ln -s "$__fish_user_dots_path" "$__udots_link"
end
end
end
# ─────────────────────── Source machine-local config ────────────────────
# Sources local.fish if it exists. That file handles sourcing its own
# secrets.fish companion when needed.
test -f "$__fish_user_dots_path/local.fish"; and source "$__fish_user_dots_path/local.fish"
# ─────────────────── C6: Greeting & First-Run UI override ───────────────
# When the greeting category is disabled, stamp out any fish_greeting
# function that distro configs set (e.g., CachyOS defines it as fastfetch).
# This runs last inside the interactive block so our empty definition wins
# over whatever cachyos-config.fish or vendor conf.d installed.
if not __fish_config_op_enabled __fish_config_op_greeting
function fish_greeting
end
end
#
# ╭──────────────────────────── END OVERRIDES ──────────────────────────╮
# │ End of override section. │
# ╰──────────────────────────── END OVERRIDES ──────────────────────────╯
end
return # <-- Do not remove this line.
# ╭──────────────────────────────── !!!NOTE!!! ───────────────────────────────╮
# │ Tools like starship, zoxide, etc. append init lines below this point │
# │ via their setup commands. We manage these integrations through │
# │ conf.d/ instead, so we return here to prevent duplicate or conflicting │
# │ inits from being executed. │
# │ │
# │ If a tool's shell integration appears to do nothing, │
# │ check whether its setup command appended an init line here, │
# │ then create a conf.d/<tool>.fish instead and place the init in that file. │
# ╰───────────────────────────────────────────────────────────────────────────╯