Required tier is now fish, fzf, and zoxide only — the tools the config
meaningfully can't function without. Everything else degrades gracefully.
- cargo: only used by fish-deps to install Rust tools or build fish from
source; all paths are already gated on type -q cargo
- starship: type -q guard in conf.d/starship.fish; shell falls back to
fish's built-in prompt without it
- fisher: auto-bootstrapped by first_run.fish; no need for users or
fish-deps to manage it. Remove from catalog and clean up the now-dead
fisher-bootstrap/special-fisher installer cases.
Catalog arrays verified aligned at 26 entries each.
direnv integration is fully guarded with type -q direnv in config.fish.
The auto-venv script checks $DIRENV_DIR (set at runtime), not the binary.
Without direnv installed the hook simply never loads and venv activation
fires normally. No functionality breaks.
uv is only used in the fish-deps fish-from-source build path
(uv run --no-managed-python cargo install --path .) and is not required
by the config at runtime. All consumers degrade gracefully without it.
pipx appeared in the installer's method-building and execution switch
blocks but no catalog entry ever sets special=pipx, making both branches
permanently unreachable dead code. The docs listed pipx as install
priority #6 which was equally misleading.
- _fish_deps_catalog: change uv tier from req → rec
- _fish_deps_install: remove case pipx method-builder and
special-pipx / special-pip execution cases
- docs/fish-config.md: move uv from Required to Recommended catalog
entry with accurate description; drop pipx from install priority
list and tier summary
python3 is used unguarded by the AI session helpers and (guarded) by the
paru/yay log cleaner, but was absent from the dependency catalog and docs.
uv does not provide python3 on PATH, and Arch's base omits it, so it is
tracked separately rather than assumed via uv.
- Add python3 (recommended tier, pm: python) to _fish_deps_catalog.fish
- Guard python3 calls in save_claude_session/save_antigravity_session with
`type -q python3`, emitting valid empty JSON when absent (Convention §6)
- Document python3 in docs/fish-config.md (§5.6 tiers + catalog entry)
The badge now positions each state by where it sits on the scale: OFF
left-aligned, DEFAULT centered, ON right-aligned. This makes the
OFF ← DEFAULT → ON ordering visible at a glance and reinforces the
direction the ←→/h l keys move.
Directional arrows fully cover value changes, so the Space cycle is
removed. Add h/l as vim-style aliases for ←/→ (matching the existing
j/k for up/down), keeping the whole keymap hjkl-consistent. Update the
in-panel hint, help text, docstrings, and offline docs accordingly.
Left/Right now adjust the highlighted value one step along the
OFF ← DEFAULT → ON scale, clamped at the ends (no wrap), complementing
Space which cycles through all states and wraps. Right steps toward ON,
Left toward OFF.
Extract the set/erase side-effect into __config_toggle_apply so Space,
Left, and Right share one implementation of the scope-aware
set -U/-g/-Ue/-eg logic. Update the in-panel keybind hint (now
width-padded via string pad so the border stays aligned) and the help
text and offline docs to cover the new keys.
fish's `read` invokes its interactive line editor on a TTY, which (1)
prints a `read> ` prompt below the panel, (2) intercepts Tab and arrow
keys for its own line editing so they never reach the switch, and (3)
shifts the cursor down a line, throwing off the `\e[14A` redraw so top
borders stacked on every keypress. Plain keys (j/k/q/space) passed
through, masking the problem.
Add __config_toggle_read_key: puts the terminal in raw, no-echo mode
(`stty raw -echo min 1 time 1`), reads one keypress from /dev/tty, and
returns a normalized token (up/down/left/right/tab/space/escape/quit or
the literal char) by decoding the bytes via od. Arrow keys and Tab now
work, there is no stray prompt, and the redraw stays aligned. Ctrl-C in
raw mode arrives as byte 3 and maps to quit; bare Esc exits after the
0.1s inter-byte timer.
Rewrite the event loop to consume these tokens and restore Esc to the
help text.
The event loop used `read -k 1`, but `-k` is not a valid fish read option
(it errors with "unknown option", status 2). read therefore returned
instantly every iteration without consuming a keypress, so the loop
redrew the panel as fast as the terminal could render and ignored all
input. The nchars flag is `-n`, not `-k`.
Switch to `read -s -n 1` (one char, silent so keystrokes don't garble the
panel) and add `or break` so a read failure (EOF / non-tty stdin) exits
cleanly instead of spinning. Applies to the primary read and both escape
sequence continuation reads.
fish's read -k N waits for exactly N bytes; single-char keys ('q', 'j',
Space, Tab) were blocking indefinitely waiting for 2 more bytes, causing
the input loop to appear unresponsive. Random 3-key bundles were then
processed as unrecognised input, triggering infinite redraws.
Switch to read -k 1 (one raw byte per call). Arrow keys still work: the
terminal sends ESC+[+A/B as a burst, so after reading ESC the two
continuation bytes are already in the TTY buffer and the follow-up reads
return immediately. Bare ESC now passes the next keypress through as the
effective key rather than exiting (q/Q remain the exit keys).
Replace two-read-k-1 ESC handling with a single read -k 3 so that a bare
ESC returns immediately instead of blocking the shell indefinitely waiting
for a second byte. Add trap - INT in the cleanup block so the signal
handler does not leak into the global session after config-toggle exits.
When smart_exit skips fish-side capture due to the C5 guard, it now sets
logged_by_shell=true on the Kitty window before calling builtin exit. This
prevents watcher.py's on_close handler from capturing the scrollback even
if the sentinel file is absent, providing a second layer of protection.
Also restructures the capture block to be flat (no wrapper if-true) after
the early-exit guard.
--on-variable handlers in functions/ are only autoloaded on explicit call,
so they never fire when a universal variable changes. Moving the definitions
to conf.d/logging-events.fish ensures they are registered at shell init.
Also adds a startup __fish_config_sync_logging call so pre-set variable
values (e.g. set before this shell was opened) take effect immediately
without requiring a re-set.
C1 shadows (rm, cat, ls, less, du, bash, top, ping, ssh, rg, mkdir,
help) fall back to the bare command when __fish_config_op_aliases is
falsy; rm falls back to exact 'command rm' with no wrapper. C2 gates
the auto-venv PWD hook. C3 gates smart_exit (composing with Task #4
logging), fish_right_prompt, and all six expand_bang_*/expand_typo_sub
functions atomically with the bang-bang system. C4 integration commands
(spwin, tab, split, hist, logs, upgrade) refuse with a colored stderr
error when disabled. config.fish now also strips the CachyOS distro
config's own bang-bang bindings, history override, and alias opinions
per category, restoring fish stock functions where they exist.
- Section keyword is now extracted early and shared across all three
output modes (pager, HTML, man) rather than duplicated per branch
- --html with a section keyword resolves the heading to a pandoc anchor
ID and looks it up in docs/html/sitemap.json; handles both sub-section
fragment paths and top-level sections that are their own page
- --man with a section keyword overrides MANPAGER to `less +/pattern`
so the page opens at the nearest heading match
- --help output updated to show [section] in USAGE and section+flag
examples (help config keybindings --html, help config pkg --man)
- docs/fish-config.md §5.14 synopsis, flags, and examples updated
- docs/fish-config.md §11 "Viewing" sections updated for both HTML and
man page to document the section+flag invocation
- README table updated with section+html and section+man rows
- help.fish: expand SYNOPSIS/DESCRIPTION to document -w/--html, -m/--man,
-h/--help flags; note flags are only intercepted when 'config' is argv[1]
- config-help.fish: add # NOTES section explaining help config as the
preferred invocation; update --help banner to show both names; update
--help USAGE/EXAMPLES output to use `help config` syntax throughout
- docs/fish-config.md: update §5.14 synopsis/examples and "Viewing" sections
to use `help config` as primary form; inline note for direct config-help use
- README.md: update docs table to show `help config --html` / `--man`
conf.d/sponge_privacy.fish registers patterns and filters that prevent
credentials from reaching fish history:
Layer 1 (static regex, universal): auth flags, env assignments,
credential-bearing URLs, Authorization headers, sshpass, docker
login, openssl -passin/-passout
Layer 2 (dynamic values, session globals): on the first prompt, after
secrets.fish has loaded, reads the literal values of all exported
credential-named vars (TOKEN, PASSWORD, SECRET, etc.), escapes them
for regex, and merges them with the static patterns as a session
global — auto-refreshes on login so rotated tokens are never stale
Layer 3 (per-command filter, sponge_filter_secrets): catches
credentials in variables exported mid-session (e.g. project .env)
Also exempts functions/sponge_filter_secrets.fish from the sponge_*
gitignore glob so our custom filter is committed alongside the config.
config-help gains two new flags:
- --html / -w: opens docs/html/index.html in the default browser using
smart browser detection (xdg-mime https scheme handler → known binaries
→ xdg-open fallback) to avoid MIME-type mismatches with non-browser apps
- --man / -m: opens the compiled docs/fish-config.1 man page via man -l
config-update is a new function that pulls the latest fish config from the
hard-coded upstream URL without requiring a configured git remote. Suppresses
git output and reports status with colored messages. Supports --dry-run and
--force flags.
README updated to document all new commands.
Rename config_help → config-help and add a help wrapper that
intercepts 'help config [section]', forwarding sub-topics to
config-help. Update README and docs to use 'help config' as the
preferred interface so offline docs feel like a natural extension
of fish's built-in help system.
Section headers in bold blue, argument/flag names in yellow, command
examples in green, navigation keys in cyan, fallback chain numbers
dimmed. All reset to normal after each colored span.
- config_help --help / -h prints full usage, section keyword examples,
ov navigation key reference, and the pager fallback chain.
- Prepend a dim nav hint line to the ov input stream and pin it with
--header 1 so "Space=next section ^=prev Alt+u=sections /=search
q=quit" is always visible at the top of the screen.
- Add docs/fish-config.index mapping 100+ keyword aliases to exact heading
text; config_help looks up here first, falls back to normalized heading
scan (strips non-alphanumeric, lowercases both sides) for unknown terms.
- Resolve line numbers at runtime with grep -F so the index never goes
stale from doc edits — only heading renames require an update.
- Fix section jump: --section-header pins delimiter lines as sticky headers
removing them from ov pattern-search scope. Replace --pattern with
tail -n +$start_line piped before ov; the target section is the first
line so no search is needed and forward section nav still works.
- Fix empty sections sidebar: ov matches --section-delimiter against
logical (ANSI-stripped) text, so "^#" is correct for bat-colored output;
the previous ANSI escape-sequence regex never matched anything.
- docs/fish-config.md: curated terminal-optimized manual covering all
public functions, keybindings, abbreviations, configuration variables,
dependency catalog, and customization guide. Written for ov/bat/less
readability rather than browser rendering — no callouts, no hyperlinks.
Pandoc-compatible YAML front matter for man page compilation.
- functions/config_help.fish: viewer function with fallback chain
ov -> bat -> man -l -> less -> cat. Accepts an optional section
keyword to jump directly to the first matching heading.
- .gitea/workflows/man-page.yml: compiles docs/fish-config.md to
docs/fish-config.1 via pandoc on every push to main that touches the
source doc, then commits the result automatically.
- .gitea/workflows/docs-drift.yml: opens a reminder issue whenever
README.md changes without a corresponding docs/fish-config.md update
in the same push.
- README.md: documents config_help and the offline manual.
- AGENTS.md: adds Convention 10 requiring offline doc to be updated
alongside any function, keybinding, or config change.
Refactor pkg.fish to auto-detect the system package manager via
_fish_deps_detect_pm instead of hard-requiring paru/yay. Supports
install, uninstall, and auto (toggle) modes across paru, yay, pacman,
apt, dnf, zypper, yum, brew, and pkg. Package installed-checks now use
the correct query tool per PM (pacman -Qi, dpkg -s, rpm -q, etc.).
Also adds zypper to the _fish_deps_detect_pm detection priority list.
Replace all ad-hoc inline comments between license headers and function
declarations with consistent SYNOPSIS / DESCRIPTION / ARGUMENTS / RETURNS /
EXAMPLE blocks across all 99 project-owned functions/ files. No executable
logic, variable names, or exit codes were modified.
Completes Task #6 from AGENTS.md (Retroactive Function Documentation
Standardization).
Adds __fzf_inline_picker function and @@ keybinding (Emacs + all Vi
modes). Opens an fzf session and injects the selected item at the
cursor position in the current command line. Includes SYNOPSIS/
DESCRIPTION doc block per project conventions. Updates README with
new binding in the User Bindings table.
- mkdir: loop over path args calling _fish_mkdir_p --path; falls back
to command mkdir -p when flag args (e.g. -m 755) are present
- mkcd: default to _fish_mkdir_p --tree for new dirs; add -s/--silent
flag to suppress tree output (mkcd's own status message still prints)
- Add _fish_mkdir_p: reusable mkdir -p with three output modes:
--path (default): "Created: ~/full/path/" on one line
--tree: dimmed existing anchor + cyan tree of newly-created dirs
--silent: no output
HOME is substituted with ~ in all output paths
- Refactor poke to delegate to _fish_mkdir_p --tree; removes inline
mkdir/echo logic and gains ~ substitution and per-dir tree output
- Add poke: touch with automatic parent directory creation; prints
colored notice when new dirs are created; handles multiple file args
- Refactor config.fish CachyOS override block: consolidate copy into
the erase+source loop alongside ls/lt/cleanup
- fish-deps: replace most with ov (cargo crate + AUR pkg); add yay as
rec dep with yay-build special (paru -S yay or AUR makepkg); add
update handling for yay-build in _fish_deps_update
- README: document poke in Directory & File Listing table