docs: generate the Functions Reference from function comment headers #74

Merged
rootiest merged 10 commits from docs-option-tables into main 2026-07-26 08:41:03 +00:00
116 changed files with 2347 additions and 1672 deletions
+12 -7
View File
@@ -122,14 +122,19 @@ the watcher inert without uninstalling it.
### [📖 Documentation Site](https://fish-config-docs.pages.dev/) ### [📖 Documentation Site](https://fish-config-docs.pages.dev/)
A Starlight-powered site generated from `docs/manual/**` — the single source A Starlight-powered site rebuilt on every push to `main`. It covers
of truth — on every push to `main`. It covers configuration variables, key configuration variables, key bindings, abbreviations, all functions, the
bindings, abbreviations, all functions, the dependency catalog, customization, dependency catalog, customization, and more, with full-text search.
and more, with full-text search.
Contributing to the docs? Edit files under `docs/manual/**`, never the Contributing to the docs? There are two sources, split by content type:
generated `docs/fish-config.md` — it's rebuilt from the manual tree and any
hand-edits are discarded. - **Function documentation** comes from the man-page-style comment header
above each function in `functions/*.fish`. Edit the function; the entry
and its site page are generated from the header.
- **Everything else** lives under `docs/manual/**`.
Never edit the generated `docs/fish-config.md` — it's rebuilt from both
sources and any hand-edits are discarded.
To browse the docs from the terminal: To browse the docs from the terminal:
+206 -13
View File
@@ -18,6 +18,37 @@ import manualtools as mt
DOCS = Path(__file__).parent DOCS = Path(__file__).parent
MANUAL = DOCS / "manual" MANUAL = DOCS / "manual"
FUNCTIONS = DOCS.parent / "functions"
SLUG_DIR = "reference"
def _is_function_page(path: Path, root: Path) -> bool:
"""True for a Section 5 category stub (not its index)."""
rel = path.relative_to(root)
return bool(rel.parts) and rel.parts[0].endswith("-functions") and rel.name != "index.md"
def _entry_slug(title: str) -> str:
"""The site's page slug for an entry heading."""
return re.sub(r"[^\w-]+", "-", title.strip().lower()).strip("-")
def _entry_link(name: str, functions: dict) -> str:
"""Link a dependency name to its entry page; plain code span if unknown."""
fn = functions.get(name)
if not fn:
return f"`{name}`"
category = re.sub(r"^\d+-", "", fn["CATEGORY"][0])
return f"[`{name}`](/{SLUG_DIR}/{category}/{_entry_slug(name)}/)"
def _with_entries(body: str, path: Path, entries: dict) -> str:
"""Append this category's generated `## name` entries to its stub body."""
generated = entries.get(path.stem, [])
if not generated:
return body
blocks = [f"## {name}\n\n{entry}" for name, entry in generated]
return "\n\n".join(([body] if body.strip() else []) + blocks)
def build_concat(root: Path) -> str: def build_concat(root: Path) -> str:
@@ -32,6 +63,7 @@ def build_concat(root: Path) -> str:
present, its contents are re-emitted byte-for-byte as the leading present, its contents are re-emitted byte-for-byte as the leading
`---`-fenced block, ahead of every heading. `---`-fenced block, ahead of every heading.
""" """
entries = build_entries(mt.parse_functions(FUNCTIONS))
chunks: list[str] = [] chunks: list[str] = []
pandoc_path = root / "_pandoc.yml" pandoc_path = root / "_pandoc.yml"
if pandoc_path.exists(): if pandoc_path.exists():
@@ -43,6 +75,8 @@ def build_concat(root: Path) -> str:
continue continue
heading = fm.get("manTitle") or fm.get("title", path.stem) heading = fm.get("manTitle") or fm.get("title", path.stem)
chunks.append("#" * (depth + 1) + " " + heading) chunks.append("#" * (depth + 1) + " " + heading)
if _is_function_page(path, root):
body = _with_entries(body, path, entries)
if body: if body:
chunks.append(mt.shift_headings(body, depth)) chunks.append(mt.shift_headings(body, depth))
return "\n\n".join(chunks) + "\n" return "\n\n".join(chunks) + "\n"
@@ -73,19 +107,46 @@ def _jsx_attr_escape(value: str) -> str:
def _first_sentence(body: str) -> str: def _first_sentence(body: str) -> str:
"""Extract a one-line description from the start of an entry body. """Extract a one-line description from the start of an entry body.
`Synopsis:` lines are skipped: they restate the calling convention, The `Synopsis:` block is skipped whole — label line plus its
deeper-indented continuation lines. It restates the calling convention,
which the card already shows as its title, so using one as the card which the card already shows as its title, so using one as the card
description wastes the line. description wastes the line.
Source prose is hard-wrapped, so the leading paragraph is unwrapped
before the sentence match — otherwise a card truncates at the first
line break, mid-clause.
""" """
for line in body.split("\n"): para: list[str] = []
line = line.strip() in_fence = False
if not line or line.startswith(("#", "```", "|", "-", "*", ">")): syn_indent: int | None = None
for raw in body.split("\n"):
line = raw.strip()
indent = len(raw) - len(raw.lstrip())
if syn_indent is not None:
if line and indent <= syn_indent:
syn_indent = None
else:
continue
if line.startswith("```"):
in_fence = not in_fence
if para:
break
continue
if in_fence:
continue
if not line or line.startswith(("#", "|", "-", "*", ">")):
if para:
break
continue continue
if line.startswith("Synopsis:"): if line.startswith("Synopsis:"):
syn_indent = indent
continue continue
m = SENTENCE_RE.match(line) para.append(line)
return (m.group(1) if m else line)[:160] if not para:
return "" return ""
text = " ".join(para)
m = SENTENCE_RE.match(text)
return (m.group(1) if m else text)[:160]
# Commands common enough in this manual that a block whose every line starts # Commands common enough in this manual that a block whose every line starts
@@ -140,6 +201,58 @@ def _is_shell(para: list[str], entry_name: str | None) -> bool:
return True return True
CELL_SPLIT = re.compile(r"\s{2,}")
def _cell(text: str, code: bool) -> str:
"""Render one table cell. `|` must be escaped even inside a code span."""
text = text.strip().replace("|", r"\|")
return f"`{text}`" if code and text else text
def _as_table(para: list[str]) -> str | None:
"""Render an aligned two-column block as a markdown table, else None.
Option and subcommand tables are the one thing in this manual that is
genuinely tabular, and the indented-code fallback renders them as a grey
slab. Everything else stays in that fallback: returning None is always
safe, so every check here is free to be conservative.
The rows must form one contiguous indented run, optionally introduced by
a label line (`Options:`) and closed by a sentence. Lines indented deeper
than the run are wrapped descriptions and fold into the row above.
"""
starts = [i for i, ln in enumerate(para) if ln.startswith(" ")]
if len(starts) < 2 or starts != list(range(starts[0], starts[-1] + 1)):
return None
head = para[: starts[0]]
body = para[starts[0] : starts[-1] + 1]
tail = para[starts[-1] + 1 :]
if head and not head[-1].rstrip().endswith(":"):
return None # a head that isn't a label means mixed content
indent = min(len(ln) - len(ln.lstrip()) for ln in body)
rows: list[list[str]] = []
for line in body:
if len(line) - len(line.lstrip()) > indent and rows:
rows[-1][1] += " " + line.strip()
continue
parts = CELL_SPLIT.split(line.strip(), 1)
if len(parts) != 2 or not parts[1].strip():
return None # not column-aligned; a numbered list, or prose
rows.append([parts[0], parts[1].strip()])
if len(rows) < 2:
return None
if any("<" in value or "{" in value for _, value in rows):
return None # live markdown in the prose column
out = [line.strip() for line in head]
out += ["| | |", "|---|---|"]
out += [f"| {_cell(k, True)} | {_cell(v, False)} |" for k, v in rows]
out += [line.strip() for line in tail]
return "\n".join(out)
def _render_para(para: list[str], entry_name: str | None, deeper: bool) -> str: def _render_para(para: list[str], entry_name: str | None, deeper: bool) -> str:
"""Render one paragraph of a former indented block. """Render one paragraph of a former indented block.
@@ -152,6 +265,9 @@ def _render_para(para: list[str], entry_name: str | None, deeper: bool) -> str:
if _is_shell(para, entry_name): if _is_shell(para, entry_name):
body = "\n".join(para) body = "\n".join(para)
return f"```fish\n{body}\n```" return f"```fish\n{body}\n```"
table = _as_table(para)
if table is not None:
return table
return "\n".join(INDENT + line for line in para) return "\n".join(INDENT + line for line in para)
@@ -167,8 +283,12 @@ def _prettify_block(block: list[str], entry_name: str | None) -> str:
out: list[str] = [] out: list[str] = []
if lines and lines[0].startswith(SYNOPSIS_PREFIX): if lines and lines[0].startswith(SYNOPSIS_PREFIX):
synopsis = lines.pop(0)[len(SYNOPSIS_PREFIX) :].strip() synopsis = [lines.pop(0)[len(SYNOPSIS_PREFIX) :].strip()]
out.append(f"```fish\n{synopsis}\n```") # A multi-line synopsis is authored aligned under the first line;
# keep the whole thing in one fence rather than orphaning the rest.
while lines and lines[0].startswith(" "):
synopsis.append(lines.pop(0).strip())
out.append("```fish\n" + "\n".join(synopsis) + "\n```")
para: list[str] = [] para: list[str] = []
for line in lines + [""]: for line in lines + [""]:
@@ -213,6 +333,76 @@ def prettify(body: str, entry_name: str | None = None) -> str:
return "\n".join(out) return "\n".join(out)
ENTRY_HEADS = {"ARGUMENTS": "Arguments:", "RETURNS": "Returns:", "NOTES": "Notes:"}
def render_entry(fn: dict[str, list[str]], used_by: list[str], link=None) -> str:
"""Render one parsed function header as a manual entry body.
Emits the same man-page shape Section 5 was authored in — one 4-space
indented block opening with `Synopsis:` — so `prettify` keeps handling it
for the site and pandoc keeps handling it for the man page, with no
special case on either side.
`link` maps a function name to its markdown link, or is None for the man
page, where a URL in the middle of a sentence is noise.
"""
out: list[str] = []
syn = fn.get("SYNOPSIS", [])
if syn:
pad = " " * len(SYNOPSIS_PREFIX + " ")
out.append(f"{SYNOPSIS_PREFIX} {syn[0]}")
out += [pad + line for line in syn[1:]]
out.append("")
for line in fn.get("DESCRIPTION", []):
out.append(line)
for label, head in ENTRY_HEADS.items():
body = fn.get(label)
if not body:
continue
out += ["", head] + [" " + line for line in body]
if fn.get("EXAMPLE"):
out += [""] + fn["EXAMPLE"]
block = "\n".join((INDENT + line).rstrip() for line in out)
def names(raw: list[str]) -> list[str]:
return [n for n in re.split(r"[,\s]+", " ".join(raw)) if n]
refs = []
for label, values in (
("Dependencies", names(fn.get("DEPENDENCIES", []))),
("Used by", sorted(used_by)),
):
if values:
rendered = ", ".join(link(v) if link else f"`{v}`" for v in values)
refs.append(f"**{label}:** {rendered}")
if refs:
block += "\n\n" + "\n\n".join(refs)
return block
def build_entries(functions: dict[str, dict], link=None) -> dict[str, list[tuple[str, str]]]:
"""Group rendered entries by category stem, ordered by function name.
The `Used by` reverse index is computed here in one pass rather than
authored: a bidirectional link maintained by hand drifts the moment one
side is edited.
"""
used_by: dict[str, list[str]] = {}
for name, fn in functions.items():
for dep in re.split(r"[,\s]+", " ".join(fn.get("DEPENDENCIES", []))):
if dep in functions:
used_by.setdefault(dep, []).append(name)
out: dict[str, list[tuple[str, str]]] = {}
for name in sorted(functions):
fn = functions[name]
body = render_entry(fn, used_by.get(name, []), link)
out.setdefault(fn["CATEGORY"][0], []).append((name, body))
return out
def _page_fm(fm: dict) -> dict: def _page_fm(fm: dict) -> dict:
"""Strip pipeline-only keys from frontmatter destined for the site.""" """Strip pipeline-only keys from frontmatter destined for the site."""
return {k: v for k, v in fm.items() if k not in PIPELINE_KEYS} return {k: v for k, v in fm.items() if k not in PIPELINE_KEYS}
@@ -260,6 +450,9 @@ def build_site(root: Path, out: Path) -> list[dict]:
shutil.rmtree(out) shutil.rmtree(out)
out.mkdir(parents=True) out.mkdir(parents=True)
functions = mt.parse_functions(FUNCTIONS)
entries = build_entries(functions, link=lambda n: _entry_link(n, functions))
sidebar: list[dict] = [] sidebar: list[dict] = []
functions_group: dict = {} functions_group: dict = {}
for path, _depth in mt.walk(root): for path, _depth in mt.walk(root):
@@ -286,7 +479,7 @@ def build_site(root: Path, out: Path) -> list[dict]:
# upload. The pages build fine and never arrive — every entry 404s in # upload. The pages build fine and never arrive — every entry 404s in
# production while working locally. test_site_avoids_reserved_dir # production while working locally. test_site_avoids_reserved_dir
# guards this. # guards this.
slug_dir = "reference" slug_dir = SLUG_DIR
if rel.name == "index.md": if rel.name == "index.md":
target = out / slug_dir / "index.md" target = out / slug_dir / "index.md"
target.parent.mkdir(parents=True, exist_ok=True) target.parent.mkdir(parents=True, exist_ok=True)
@@ -305,12 +498,12 @@ def build_site(root: Path, out: Path) -> list[dict]:
category = re.sub(r"^\d+-", "", rel.stem) category = re.sub(r"^\d+-", "", rel.stem)
cat_dir = out / slug_dir / category cat_dir = out / slug_dir / category
cat_dir.mkdir(parents=True, exist_ok=True) cat_dir.mkdir(parents=True, exist_ok=True)
intro, entries = _split_entries(body) intro, page_entries = _split_entries(_with_entries(body, path, entries))
cards = [] cards = []
links = [] links = []
for title, entry_body in entries: for title, entry_body in page_entries:
entry_slug = re.sub(r"[^\w-]+", "-", title.strip().lower()).strip("-") entry_slug = _entry_slug(title)
desc = _first_sentence(entry_body) desc = _first_sentence(entry_body)
entry_fm = {"title": title} entry_fm = {"title": title}
if desc: if desc:
+1264 -550
View File
File diff suppressed because it is too large Load Diff
@@ -7,158 +7,4 @@ helpKeywords:
- files - files
--- ---
## 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
---
-22
View File
@@ -7,26 +7,4 @@ helpKeywords:
- nav-fns - nav-fns
--- ---
## 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
---
@@ -7,65 +7,4 @@ helpKeywords:
- editors - editors
--- ---
## 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
---
@@ -7,84 +7,4 @@ helpKeywords:
- git - git
--- ---
## auto-pull
Synopsis: auto-pull [list]
auto-pull add [PATH]
auto-pull remove <NAME|PATH>
auto-pull status
Manages the registry of repositories that are background fast-forwarded
when you enter them (see "Auto-pull fast-forward" under the C2 component
reference). The fish-config repo is always covered as a baseline. The
registry is machine-local at `$__fish_user_dots_path/auto-pull.list` (defaults
to `~/.config/.user-dots/fish/auto-pull.list`), one absolute path per line,
and is never committed. Registry management works
even when C2 auto-execution is disabled; only the background sync is gated.
list Show registered repos (default)
add [PATH] Register PATH's git root (default: current repo)
remove <NAME|PATH> Unregister by basename or exact path
status Show enabled/disabled state, repo count, list path
cd ~/src/qmk_firmware; and auto-pull add
auto-pull add ~/work/api
auto-pull list
auto-pull remove qmk_firmware
## 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.
---
@@ -8,53 +8,4 @@ helpKeywords:
- packages - packages
--- ---
## 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
## search
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
---
@@ -7,41 +7,4 @@ helpKeywords:
- deps - deps
--- ---
## 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, yt-dlp
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`.
---
@@ -7,57 +7,4 @@ helpKeywords:
- system - system
--- ---
## 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.
---
@@ -7,54 +7,4 @@ helpKeywords:
- terminal-mgmt - terminal-mgmt
--- ---
## 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
---
-22
View File
@@ -7,26 +7,4 @@ helpKeywords:
- clipboard - 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.
---
-34
View File
@@ -7,38 +7,4 @@ helpKeywords:
- network - 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
---
@@ -7,41 +7,4 @@ helpKeywords:
- logging - 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
---
@@ -7,110 +7,4 @@ helpKeywords:
- ai - ai
--- ---
## 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.
## qc
Synopsis: qc [prompt...]
Quick-chat wrapper around the aichat LLM CLI that defaults to the "cli"
role - a system prompt tuned for concise, terminal-friendly output. On
first use it installs the bundled role by symlinking
scripts/cli-agent.md to $XDG_CONFIG_HOME/aichat/roles/cli.md (creating
the directory if needed). Inherits every aichat flag and tab completion
(--wraps aichat); passing --role/-r overrides the default role, so qc
forwards to aichat unchanged. The function is only defined when aichat
is installed. Run qc --help for aichat's full flag reference with the
command name rewritten to qc.
qc "how do I list open ports on linux?"
qc -m ollama:llama3 "explain this error"
qc --role coder "refactor this function"
## 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
---
@@ -7,48 +7,4 @@ helpKeywords:
- media - media
--- ---
## 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
## yt-dlp
Synopsis: yt-dlp [args...] URL [URL...]
Wraps yt-dlp, prepending sane defaults: --sponsorblock-remove all,
--embed-subs, --embed-metadata, and --embed-thumbnail. Each default
is suppressed when you already pass that flag, its alias, or its
negation (e.g. --no-embed-thumbnail drops the thumbnail default;
--no-sponsorblock or your own --sponsorblock-remove drops ours). All
other arguments pass through unchanged, and --help falls through to
real yt-dlp. Opinionated component (C1 aliases); when disabled it
passes straight through to the system yt-dlp.
yt-dlp dQw4w9WgXcQ
yt-dlp --no-embed-thumbnail dQw4w9WgXcQ
---
@@ -7,278 +7,4 @@ helpKeywords:
- miscfns - miscfns
--- ---
## config-help
Synopsis: config-help [SECTION]
config-help --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 the published documentation website
(https://fish-config-docs.pages.dev/) in the default
browser via xdg-open. Deep links to a section aren't
supported; if SECTION is given, a note points you to the
site's search box instead.
--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 --man
config-help pkg --man
Also available as: help config [SECTION] [FLAGS]
## open-url
Synopsis: open-url [-s|--silent] [-v|--verbose] <url>
open-url -h | --help
Opens a URL or file:// URI in the best available graphical web browser,
backgrounded so it never blocks the terminal. Resolves a real browser
binary rather than deferring to xdg-open, whose MIME dispatch can hand
local text/html files to non-browser apps (e.g. ebook readers).
Silent by default: prints nothing on success (errors always go to
stderr). Pass --verbose / -v to report which browser is launched;
--silent / -s is accepted for explicitness.
Resolution order:
1. $fish_help_browser (explicit override)
2. $BROWSER (validated; errors if not a command)
3. xdg-mime default handler for x-scheme-handler/https
4. First known browser binary found in a built-in list
5. xdg-open (last resort)
open-url https://git.rootiest.dev/rootiest/fish-config
open-url -v https://fish-config-docs.pages.dev/
Used internally by config-help --html.
Typo abbreviation: url-open (expands to open-url on space/enter).
## repo-open
Synopsis: repo-open [-p|--print] [-r|--root]
repo-open -h | --help
Opens the web page for the current repository's `origin` remote in a
browser (via open-url). Deep-links to the current branch when it exists
on the remote — falling back to the remote's default branch (main/master)
otherwise — and to the current sub-directory when run below the repo root.
The remote URL is normalized from HTTPS and SSH/scp forms
(git@host:owner/repo.git, ssh://…, https://…). The web path layout is
provider-specific; the provider is resolved in order:
1. git config browse.provider (per-repo or --global override)
2. Hostname heuristic (github / gitlab / gitea / bitbucket;
codeberg → gitea)
3. Default: github-style layout
Self-hosted hosts the heuristic can't classify (a Gitea/GitLab instance
on a custom domain) need a one-time override:
git config browse.provider gitea
Flags:
--print / -p Print the resolved URL instead of opening it.
--root / -r Ignore the current sub-directory; link to the repo root.
--help / -h Show usage.
repo-open
repo-open --print
repo-open --root
Typo abbreviation: open-repo (expands to repo-open on space/enter).
## config-update
Synopsis: config-update [-h] [-n] [-f]
Pulls the latest fish configuration from the upstream repository
into ~/.config/fish.
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-settings
Synopsis: config-settings [-h]
Opens an interactive TUI for managing fish configuration settings across
four pages, without having to type or remember variable names. Tab cycles
forward through the pages; Shift-Tab cycles backward.
Universal — opinionated category toggles (C1C6) + master, persistent (set -U)
Session — the same toggles, current shell only (set -g)
Sponge — sponge history-scrubbing settings: delay, successful exit
codes, purge-only-on-exit, allow-previously-successful, and
extra sensitive variable-name tokens
Paths — scrollback log directory, scrollback max files, the
user-dots path, and the user-dots convenience symlink toggle
(Dots link)
Toggle rows use ← → (or h/l) along an OFF ← DEFAULT → ON scale; DEFAULT
erases the variable so the master switch / built-in default applies. Value
rows (the path/int/list settings on the Sponge and Paths pages) use Enter to
edit inline; ← / h clears the value back to its default. List rows (e.g.
Extra secret, OK codes) accept values separated by commas and/or whitespace
— "A, B", "A,B" and "A B" all yield the same two entries. Changes apply
immediately. Always available regardless of the __fish_config_opinionated
master state.
The Sponge and Paths pages always write universal variables — these are
persistent, set-and-forget settings with no per-session scope. Editing a
scrollback row updates both the __fish_scrollback_history_* source-of-truth
variables and the exported SCROLLBACK_HISTORY_* mirrors, so the AUR/tmux/
zellij log wrappers (which read the exported names) see the change in the
running session.
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 Toggle rows: OFF ← DEFAULT → ON
← / h Value rows: clear to default
Enter Value rows: edit inline (Sponge / Paths pages)
Tab / S-Tab Next / previous page
q / Escape Exit
Flags:
--help / -h Show usage.
config-settings
## config-toggle (deprecated)
Deprecated alias for config-settings. Prints a deprecation notice to
stderr, then delegates all arguments to config-settings.
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 watcher and symlinks it into the Kitty config directory (so it
always tracks the source), wiring it into kitty.conf through a
sentinel-marked managed block. Commenting out any conflicting watcher line
avoids double-capture.
Commands:
install Symlink the watcher and add the managed block
uninstall Remove the managed block and the watcher symlink
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/
---
+11
View File
@@ -83,3 +83,14 @@ editor, or from a shell:
cd ~/.config/fish/docs/manual cd ~/.config/fish/docs/manual
grep -rn "keybindings" . grep -rn "keybindings" .
Section 5 is the exception. Function entries are generated from the
man-page-style comment header above each function in `functions/*.fish`,
so the documentation for a command lives beside the code that implements
it and cannot drift from it. To read the source for a single function, or
to correct its documentation, open the function itself:
functions/git-clean.fish
The files under `docs/manual/05-functions/` carry only the category
titles, ordering, and search keywords.
+84 -1
View File
@@ -3,7 +3,8 @@
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
"""Shared helpers for the docs/manual SSOT pipeline. """Shared helpers for the docs/manual SSOT pipeline.
Frontmatter parsing, deterministic tree ordering, and heading level shifts. Frontmatter parsing, deterministic tree ordering, heading level shifts, and
the `functions/*.fish` comment-header parser that is the SSOT for Section 5.
Used by build-manual.py and verify-manual.py. Used by build-manual.py and verify-manual.py.
""" """
@@ -57,6 +58,88 @@ def shift_headings(body: str, by: int) -> str:
return "\n".join(out) return "\n".join(out)
HEADER_LABEL = re.compile(r"^#\s+([A-Z][A-Z ]*[A-Z])\s*$")
FUNC_DEF = re.compile(r"^\s*function\s+(\S+)")
SECTIONS = (
"CATEGORY",
"DEPENDENCIES",
"SYNOPSIS",
"DESCRIPTION",
"ARGUMENTS",
"RETURNS",
"EXAMPLE",
"NOTES",
)
def _header_blocks(lines: list[str]) -> list[tuple[int, dict[str, list[str]]]]:
"""Find every man-page comment header in a file's lines.
Yields (index of the line that ended the block, {LABEL: body lines}).
Body lines keep any indentation deeper than the standard `# ` prefix,
which is what lets nested option tables survive into the rendered entry.
Comment runs carrying no `# LABEL` line at all (the copyright preamble,
ordinary inline comments) produce nothing.
"""
out: list[tuple[int, dict[str, list[str]]]] = []
cur: dict[str, list[str]] = {}
label: str | None = None
for i, line in enumerate(lines + [""]):
if not line.startswith("#"):
if cur:
out.append((i, cur))
cur, label = {}, None
continue
m = HEADER_LABEL.match(line)
if m:
label = m.group(1)
cur.setdefault(label, [])
elif label is not None:
body = line[1:]
cur[label].append(body[3:] if body.startswith(" ") else body.strip())
return out
def _trailing_blanks(lines: list[str]) -> int:
"""Count the blank `#` separator lines closing a section."""
n = 0
while n < len(lines) and not lines[len(lines) - 1 - n].strip():
n += 1
return n
def parse_functions(root: Path) -> dict[str, dict[str, list[str]]]:
"""Parse the comment header above every documented public function.
`root` is the repository's `functions/` directory. Returns
`{name: {LABEL: [lines]}}`.
`# CATEGORY` is the opt-in: a header without one produces no entry. That
keeps bundled-plugin and prompt internals (`fish_prompt`, `sponge_filter_*`,
`fisher`, ) out of the manual with no exclusion list to maintain.
A file carrying exactly one header is associated with its own stem, so a
`function` nested inside a `type -q` guard still resolves. Only files with
several headers walk forward to the next `function` definition.
"""
out: dict[str, dict[str, list[str]]] = {}
for path in sorted(root.glob("*.fish")):
lines = path.read_text(encoding="utf-8").split("\n")
blocks = _header_blocks(lines)
for end, sections in blocks:
if len(blocks) == 1:
name = path.stem
else:
after = (m.group(1) for ln in lines[end:] if (m := FUNC_DEF.match(ln)))
name = next(after, path.stem)
if name.startswith("_") or "CATEGORY" not in sections:
continue
out[name] = {
k: v[: len(v) - _trailing_blanks(v)] for k, v in sections.items()
}
return out
def _sort_key(entry: Path) -> tuple: def _sort_key(entry: Path) -> tuple:
"""Order by sidebar.order when present, else by filename. Stable.""" """Order by sidebar.order when present, else by filename. Stable."""
target = entry / "index.md" if entry.is_dir() else entry target = entry / "index.md" if entry.is_dir() else entry
+179 -8
View File
@@ -4,6 +4,7 @@
"""Verification checks for the docs/manual SSOT pipeline.""" """Verification checks for the docs/manual SSOT pipeline."""
import importlib.util import importlib.util
import re
import sys import sys
import tempfile import tempfile
from pathlib import Path from pathlib import Path
@@ -109,14 +110,113 @@ def test_manual_tree_exists():
assert len(cats) == 14, f"expected 14 function categories, got {len(cats)}: {cats}" assert len(cats) == 14, f"expected 14 function categories, got {len(cats)}: {cats}"
def test_function_entries_promoted_to_h2(): def test_function_stubs_carry_no_entries():
"""Category files are stubs: entries come from functions/*.fish headers.
An authored `##` entry here would be a second copy of a function's
documentation exactly the duplication the header-SSOT migration
removed and the generator would emit its own entry alongside it.
"""
root = Path(__file__).parent / "manual" / "05-functions" root = Path(__file__).parent / "manual" / "05-functions"
for path in root.glob("*.md"): for path in root.glob("*.md"):
if path.name == "index.md": if path.name == "index.md":
continue continue
_, body = mt.parse(path) _, body = mt.parse(path)
assert "\n### " not in f"\n{body}", f"{path.name} still has H3 entries" stray = [ln for ln in body.split("\n") if ln.startswith(("## ", "### "))]
assert "\n## " in f"\n{body}", f"{path.name} has no H2 function entries" assert not stray, f"{path.name} has authored entries: {stray}"
def _parsed_functions() -> dict[str, dict[str, list[str]]]:
return mt.parse_functions(Path(__file__).parent.parent / "functions")
def test_every_categorised_function_produces_one_entry():
import build_manual
functions = _parsed_functions()
entries = build_manual.build_entries(functions)
got = [name for names in entries.values() for name, _ in names]
assert sorted(got) == sorted(functions), (
f"entry/function mismatch: "
f"{sorted(set(functions) ^ set(got))}"
)
assert len(got) == len(set(got)), "a function produced more than one entry"
def test_entries_carry_the_required_sections():
missing = []
for name, fn in _parsed_functions().items():
absent = [s for s in ("SYNOPSIS", "DESCRIPTION", "EXAMPLE") if not fn.get(s)]
if absent:
missing.append(f"{name}: {', '.join(absent)}")
assert not missing, "headers missing required sections:\n " + "\n ".join(missing)
def test_every_category_resolves_to_a_stub():
root = Path(__file__).parent / "manual" / "05-functions"
stubs = {p.stem for p in root.glob("*.md") if p.name != "index.md"}
used = {}
for name, fn in _parsed_functions().items():
used.setdefault(" ".join(fn.get("CATEGORY", [])).strip(), []).append(name)
unknown = {c: v for c, v in used.items() if c not in stubs}
assert not unknown, f"# CATEGORY values with no stub: {unknown}"
empty = sorted(stubs - set(used))
assert not empty, f"category stubs generating zero entries: {empty}"
def test_dependencies_resolve():
"""Every declared # DEPENDENCIES name must be a real function or binary.
Catches typos, and catches stale entries when a dependency is renamed
or deleted. External binaries are accepted when some file in the tree
guards them with `type -q`, which is this repo's convention.
"""
repo = Path(__file__).parent.parent
functions = _parsed_functions()
known = {p.stem for p in (repo / "functions").glob("*.fish")} | set(functions)
for path in list(repo.glob("conf.d/*.fish")) + list((repo / "functions").glob("*.fish")):
known |= set(re.findall(r"type -q\s+(\S+)", path.read_text(encoding="utf-8")))
dangling = []
for name, fn in functions.items():
for dep in (d for d in re.split(r"[,\s]+", " ".join(fn.get("DEPENDENCIES", []))) if d):
if dep not in known:
dangling.append(f"{name} -> {dep}")
assert not dangling, "unresolvable # DEPENDENCIES:\n " + "\n ".join(dangling)
def warn_public_functions_without_category():
"""Warn — never fail — on a public function carrying no `# CATEGORY`.
Bundled plugin and prompt internals will always lack one, so this
cannot be a hard failure; a genuinely new user-facing function going
undocumented still needs to be visible in CI output.
"""
repo = Path(__file__).parent.parent
documented = set(_parsed_functions())
orphans = sorted(
p.stem
for p in (repo / "functions").glob("*.fish")
if not p.stem.startswith("_")
and p.stem not in documented
and "# SYNOPSIS" in p.read_text(encoding="utf-8")
)
if orphans:
print(f" WARN {len(orphans)} documented function(s) lack # CATEGORY:")
print(" " + ", ".join(orphans))
def _without_section_5(text: str) -> str:
"""Drop `# 5. FUNCTIONS REFERENCE` through the start of section 6.
Section 5 is generated from `functions/*.fish` headers, so it
legitimately differs from the pre-migration snapshot. The round-trip
guard covers the authored sections either side of it.
"""
start = text.find("\n# 5. ")
if start == -1:
return text
end = text.find("\n# 6. ", start)
return text[:start] + (text[end:] if end != -1 else "")
def _normalise(text: str) -> str: def _normalise(text: str) -> str:
@@ -128,6 +228,11 @@ def _normalise(text: str) -> str:
def test_concat_roundtrips_original(): def test_concat_roundtrips_original():
"""The concat of manual/ must reproduce the original fish-config.md exactly. """The concat of manual/ must reproduce the original fish-config.md exactly.
Section 5 is excluded: it is generated from `functions/*.fish` headers
and so legitimately differs from the snapshot. This test guarded the
*format* migration; the header-SSOT change is a *content* migration,
covered instead by the structural checks above.
Prefers docs/fish-config.md.orig (a snapshot of the pre-migration file) Prefers docs/fish-config.md.orig (a snapshot of the pre-migration file)
when present. Once that snapshot is deleted post-migration, when present. Once that snapshot is deleted post-migration,
docs/fish-config.md IS the concat output regenerated in Step 5, so docs/fish-config.md IS the concat output regenerated in Step 5, so
@@ -149,8 +254,8 @@ def test_concat_roundtrips_original():
if not original.exists(): if not original.exists():
original = docs / "fish-config.md" original = docs / "fish-config.md"
label = "fish-config.md" label = "fish-config.md"
got = build_manual.build_concat(docs / "manual") got = _without_section_5(build_manual.build_concat(docs / "manual"))
want = original.read_text() want = _without_section_5(original.read_text())
if got != want: if got != want:
norm_got = _normalise(got) norm_got = _normalise(got)
norm_want = _normalise(want) norm_want = _normalise(want)
@@ -237,14 +342,79 @@ def test_prettify_splits_an_entry_block():
assert "```fish\nrm file.txt" in out, "examples were not fenced as fish" assert "```fish\nrm file.txt" in out, "examples were not fenced as fish"
assert out.count("```") == 4, f"expected exactly two fences, got:\n{out}" assert out.count("```") == 4, f"expected exactly two fences, got:\n{out}"
assert "\nSafe rm wrapper routing to trash:" in out, "description stayed indented" assert "\nSafe rm wrapper routing to trash:" in out, "description stayed indented"
assert ( assert "| `(no args)` | List current trash contents |" in out, (
"\n (no args) List current trash contents" in out "option table was not converted to a markdown table"
), "option table lost its indentation" )
assert ( assert (
"\nFalls back to /usr/bin/rm when trash is unavailable." in out "\nFalls back to /usr/bin/rm when trash is unavailable." in out
), "trailing prose stayed indented" ), "trailing prose stayed indented"
def test_as_table_converts_option_blocks():
"""A labelled, column-aligned block becomes a table; wrapped rows fold in."""
import build_manual
out = build_manual._as_table(
[
"Options:",
" -a/--aggressive Also removes node_modules, logs,",
" and IDE dirs",
" -d/--dry-run Print what would be removed",
"Pass neither to run interactively.",
]
)
assert out is not None, "a plain option table was rejected"
assert out.splitlines()[0] == "Options:", "the label line was dropped"
assert out.splitlines()[-1] == "Pass neither to run interactively.", (
"the trailing sentence was dropped"
)
assert (
"| `-a/--aggressive` | Also removes node_modules, logs, and IDE dirs |" in out
), "a wrapped description did not fold into the row above"
def test_as_table_escapes_pipes():
"""`|` splits table cells even inside a code span, so it must be escaped."""
import build_manual
out = build_manual._as_table(
[" -r/-R Recurse into it", " -e|-E Empty it"]
)
assert out is not None and r"`-e\|-E`" in out, f"pipe was not escaped:\n{out}"
def test_as_table_rejects_non_tables():
"""Returning None is always safe, so every ambiguous shape must return it."""
import build_manual
cases = {
"single row": [" -f/--force Force-delete unmerged branches too"],
"numbered list": [
" 1. git+cargo source build (fish shell itself)",
" 2. cargo (Rust tools — gets latest crate version)",
],
"misaligned rows": [
" -e/--empty Empty the trash",
" -S/--secure Permanently delete (single space, not a column)",
],
"synopsis continuation": [
" auto-pull add [PATH]",
" auto-pull status",
],
"unlabelled head": [
"Routes to the best tool by context.",
" --disk force duf",
" --dir force dust",
],
"live markdown in prose column": [
" add Register <PATH>'s git root",
" remove Unregister by basename",
],
}
for label, para in cases.items():
assert build_manual._as_table(para) is None, f"{label} was wrongly tabled"
def test_prettify_leaves_reference_tables_alone(): def test_prettify_leaves_reference_tables_alone():
"""Column-aligned blocks are data, not shell, and must not be fenced.""" """Column-aligned blocks are data, not shell, and must not be fenced."""
import build_manual import build_manual
@@ -328,6 +498,7 @@ def main() -> int:
except AssertionError as e: except AssertionError as e:
print(f" FAIL {t.__name__}: {e}", file=sys.stderr) print(f" FAIL {t.__name__}: {e}", file=sys.stderr)
failed += 1 failed += 1
warn_public_functions_without_category()
print(f"\n{len(TESTS) - failed}/{len(TESTS)} passed") print(f"\n{len(TESTS) - failed}/{len(TESTS)} passed")
return 1 if failed else 0 return 1 if failed else 0
+15 -3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 12-ai-and-developer-tools
#
# SYNOPSIS # SYNOPSIS
# agents-init [-a | --agents] [-p | --plugins] [-v | --verbose] # agents-init [-a | --agents] [-p | --plugins] [-v | --verbose]
# [-q | --quiet] [-s | --silent] [-h | --help] # [-q | --quiet] [-s | --silent] [-h | --help]
@@ -42,9 +45,18 @@
# version-managed from scripts/agents-tools/ and refreshed when their marker # version-managed from scripts/agents-tools/ and refreshed when their marker
# is stale. # is stale.
# #
# With no flags, runs both --agents and --plugins setup. At the end of # Downstream tooling can read AGENTS/.version directly — a changed MINOR
# every invocation, commits any uncommitted changes in the AGENTS/ sub-repo # field signals a structure change.
# so that agent-made edits are captured automatically. #
# With no flags, runs both --agents and --plugins setup; --agents re-runs
# only the AGENTS.md / symlink step and --plugins only the plans/specs/
# devlogs wiring step. Managed paths are added to .gitignore. The sub-repo
# is pulled first when it has an upstream, and at the end of every
# invocation any uncommitted changes inside it are auto-committed so
# agent-made edits are captured automatically. Fully idempotent: a second
# run produces no output and no new commits.
#
# Called automatically by the claude and agy wrappers on every invocation.
# #
# ARGUMENTS # ARGUMENTS
# -a, --agents Set up AGENTS/ repo + AGENTS.md / CLAUDE.md symlinks only # -a, --agents Set up AGENTS/ repo + AGENTS.md / CLAUDE.md symlinks only
+9 -1
View File
@@ -1,6 +1,12 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 12-ai-and-developer-tools
#
# DEPENDENCIES
# agents-init
#
# SYNOPSIS # SYNOPSIS
# agy [ARGS...] # agy [ARGS...]
# #
@@ -8,7 +14,9 @@
# Wrapper for the agy Antigravity AI CLI that ensures the AGENTS/ # Wrapper for the agy Antigravity AI CLI that ensures the AGENTS/
# sub-repository is initialized and any agent-made changes are committed # sub-repository is initialized and any agent-made changes are committed
# before launch. Delegates all scaffold and commit logic to agents-init # before launch. Delegates all scaffold and commit logic to agents-init
# (full setup). All arguments are forwarded verbatim to the real agy binary. # --quiet (full setup), which ensures AGENTS/ is scaffolded and CLAUDE.md
# is symlinked to AGENTS/AGENTS.md in the current project. All arguments
# are forwarded verbatim to the real agy binary.
# #
# Opinionated component (C1): when disabled via __fish_config_op_aliases # Opinionated component (C1): when disabled via __fish_config_op_aliases
# (or the __fish_config_opinionated master), the command is passed through # (or the __fish_config_opinionated master), the command is passed through
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 12-ai-and-developer-tools
#
# SYNOPSIS # SYNOPSIS
# antigravity-ide [args...] # antigravity-ide [args...]
# #
+7 -3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 04-git-and-version-control
#
# SYNOPSIS # SYNOPSIS
# auto-pull [list] # auto-pull [list]
# auto-pull add [PATH] # auto-pull add [PATH]
@@ -12,8 +15,9 @@
# background fast-forwarded when you enter them (see conf.d/auto-pull.fish # background fast-forwarded when you enter them (see conf.d/auto-pull.fish
# and _auto_pull_sync). The fish-config repo is always covered as a baseline # and _auto_pull_sync). The fish-config repo is always covered as a baseline
# and does not need to be added. The registry is a plain text file, one # and does not need to be added. The registry is a plain text file, one
# absolute git-toplevel path per line, stored machine-locally in # absolute git-toplevel path per line, stored machine-locally at
# ~/.config/.user-dots/fish/auto-pull.list (never committed to the config). # $__fish_user_dots_path/auto-pull.list (defaults to
# ~/.config/.user-dots/fish/auto-pull.list) and never committed.
# #
# Registry management works regardless of the C2 auto-execution guard; only # Registry management works regardless of the C2 auto-execution guard; only
# the background sync itself is gated by __fish_config_op_autoexec. # the background sync itself is gated by __fish_config_op_autoexec.
@@ -22,7 +26,7 @@
# list Show registered repos (default when no subcommand given) # list Show registered repos (default when no subcommand given)
# add [PATH] Register PATH's git root; defaults to the current repo # add [PATH] Register PATH's git root; defaults to the current repo
# remove <NAME|PATH> Unregister by basename or exact path # remove <NAME|PATH> Unregister by basename or exact path
# status Show whether auto-pull is enabled and the registry path # status Show enabled/disabled state, repo count, and registry path
# -h, --help Show this help message # -h, --help Show this help message
# #
# RETURNS # RETURNS
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 14-miscellaneous
#
# SYNOPSIS # SYNOPSIS
# bash [args...] # bash [args...]
# #
+4
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 14-miscellaneous
#
# SYNOPSIS # SYNOPSIS
# bd-pull <owner/repo> # bd-pull <owner/repo>
# #
@@ -18,6 +21,7 @@
# #
# EXAMPLE # EXAMPLE
# bd-pull myuser/myproject # bd-pull myuser/myproject
# bd-pull rootiest/fish-config
function bd-pull --description 'Pull new Gitea issues into local Beads and link them' function bd-pull --description 'Pull new Gitea issues into local Beads and link them'
if not set -q argv[1]; echo "Need repo owner/name"; return 1; end if not set -q argv[1]; echo "Need repo owner/name"; return 1; end
if not set -q GITEA_TOKEN; echo "\$GITEA_TOKEN not set"; return 1; end if not set -q GITEA_TOKEN; echo "\$GITEA_TOKEN not set"; return 1; end
+5 -1
View File
@@ -1,12 +1,16 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 08-terminal-management
#
# SYNOPSIS # SYNOPSIS
# bkg <command> [args...] # bkg <command> [args...]
# #
# DESCRIPTION # DESCRIPTION
# Launches a command in the background, fully detached from the terminal # Launches a command in the background, fully detached from the terminal
# using nohup. All stdout and stderr output is discarded. # using nohup. All stdout and stderr output is discarded. Simpler than
# detach; no --version flag.
# #
# ARGUMENTS # ARGUMENTS
# command The command to run detached # command The command to run detached
+22 -1
View File
@@ -1,4 +1,25 @@
# Switch to or create a git branch # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 04-git-and-version-control
#
# SYNOPSIS
# branch <branch_name>
#
# DESCRIPTION
# Switches to a local git branch, creating it if it does not already
# exist. Extra arguments are forwarded to git checkout.
#
# ARGUMENTS
# branch_name Branch to switch to or create
#
# RETURNS
# 0 Branch checked out or created
# 1 Not inside a git work tree
#
# EXAMPLE
# branch feature/new-ui
function branch --description 'Switch to or create a git branch' function branch --description 'Switch to or create a git branch'
if not git rev-parse --is-inside-work-tree >/dev/null 2>&1 if not git rev-parse --is-inside-work-tree >/dev/null 2>&1
echo "Not a git repo." echo "Not a git repo."
+8 -3
View File
@@ -1,19 +1,24 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 01-file-and-directory
#
# SYNOPSIS # SYNOPSIS
# cat [args...] # cat [args...]
# #
# DESCRIPTION # DESCRIPTION
# Enhanced cat replacement that uses bat for file display, runs ls when given # Enhanced cat replacement. Wraps bat for files, giving syntax highlighting
# a directory, falls back to raw cat for ANSI-colored log files, and finally # and line numbers; passes directories to ls; falls back to raw cat for
# falls back to standard cat if bat is not installed. # ANSI-colored log files, and finally to /usr/bin/cat if bat is not
# installed.
# #
# ARGUMENTS # ARGUMENTS
# args... Files or directories to display # args... Files or directories to display
# #
# EXAMPLE # EXAMPLE
# cat README.md # cat README.md
# cat ~/projects/myapp
function cat --wraps='bat' --description 'Use bat for files, ls for directories, and raw cat for ANSI logs' function cat --wraps='bat' --description 'Use bat for files, ls for directories, and raw cat for ANSI logs'
# Opinionated guard (C1): fall back to bare command cat when disabled. # Opinionated guard (C1): fall back to bare command cat when disabled.
if not __fish_config_op_enabled __fish_config_op_aliases if not __fish_config_op_enabled __fish_config_op_aliases
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 02-navigation
#
# SYNOPSIS # SYNOPSIS
# cdi [query] # cdi [query]
# #
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 14-miscellaneous
#
# SYNOPSIS # SYNOPSIS
# cffetch [args...] # cffetch [args...]
# #
+4
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 14-miscellaneous
#
# SYNOPSIS # SYNOPSIS
# cheat <topic> [args...] # cheat <topic> [args...]
# #
@@ -14,6 +17,7 @@
# #
# EXAMPLE # EXAMPLE
# cheat tar # cheat tar
# cheat git
function cheat --wraps='cheat' --description 'alias cheat=cheat -c' function cheat --wraps='cheat' --description 'alias cheat=cheat -c'
if type -q cheat if type -q cheat
command cheat -c $argv command cheat -c $argv
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 06-dependency-management
#
# SYNOPSIS # SYNOPSIS
# check_fish_deps # check_fish_deps
# #
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 12-ai-and-developer-tools
#
# SYNOPSIS # SYNOPSIS
# claude-docs # claude-docs
# #
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 12-ai-and-developer-tools
#
# SYNOPSIS # SYNOPSIS
# claude-pr # claude-pr
# #
+9 -1
View File
@@ -1,13 +1,21 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 12-ai-and-developer-tools
#
# DEPENDENCIES
# agents-init
#
# SYNOPSIS # SYNOPSIS
# claude [ARGS...] # claude [ARGS...]
# #
# DESCRIPTION # DESCRIPTION
# Wrapper for the claude CLI that ensures the AGENTS/ sub-repository is # Wrapper for the claude CLI that ensures the AGENTS/ sub-repository is
# initialized and any agent-made changes are committed before launch. # initialized and any agent-made changes are committed before launch.
# Delegates all scaffold and commit logic to agents-init (full setup). # Delegates all scaffold and commit logic to agents-init --quiet (full
# setup), which ensures AGENTS/ is scaffolded and CLAUDE.md is symlinked
# to AGENTS/AGENTS.md in the current project.
# All arguments are forwarded verbatim to the real claude binary. # All arguments are forwarded verbatim to the real claude binary.
# #
# Opinionated component (C1): when disabled via __fish_config_op_aliases # Opinionated component (C1): when disabled via __fish_config_op_aliases
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 05-package-management
#
# SYNOPSIS # SYNOPSIS
# cleanup # cleanup
# #
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 02-navigation
#
# SYNOPSIS # SYNOPSIS
# clone [args...] # clone [args...]
# #
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 02-navigation
#
# SYNOPSIS # SYNOPSIS
# clonet [args...] # clonet [args...]
# #
+12 -5
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 14-miscellaneous
#
# SYNOPSIS # SYNOPSIS
# config-help [section] # config-help [section]
# config-help --html # config-help --html
@@ -14,11 +17,14 @@
# that matches the keyword. Lookup order: docs/fish-config.index (exact # that matches the keyword. Lookup order: docs/fish-config.index (exact
# keyword aliases), then a normalized heading scan as fallback. # keyword aliases), then a normalized heading scan as fallback.
# When opened with ov a sticky navigation hint is shown at the top of the # When opened with ov a sticky navigation hint is shown at the top of the
# screen. Pass --html / -w to open the published documentation website in # screen. Section matching is case-insensitive. Pass --html / -w to open
# the default browser (deep links to a section aren't supported there — # the published documentation website (https://fish-config-docs.pages.dev/)
# use the site's search box). Pass --man / -m to open the compiled man # in the default browser via xdg-open — deep links to a section aren't
# page; if a section keyword is given, the pager opens at the nearest # supported there, so if a keyword is given a note points you to the site's
# match. Pass --help or -h for usage. # search box instead. Pass --man / -m to open the compiled man page
# (docs/fish-config.1) via `man -l`; if a section keyword is given, the
# pager opens at the nearest match. Pass --help or -h for usage and the
# navigation key reference.
# #
# ARGUMENTS # ARGUMENTS
# section Optional keyword to jump to a matching section heading # section Optional keyword to jump to a matching section heading
@@ -39,6 +45,7 @@
# config-help --man # config-help --man
# config-help keys --man # config-help keys --man
# config-help --help # config-help --help
# config-help pkg --man
# #
# NOTES # NOTES
# The preferred invocation is `help config [...]` — this function is # The preferred invocation is `help config [...]` — this function is
+41 -7
View File
@@ -1,24 +1,58 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 14-miscellaneous
#
# SYNOPSIS # SYNOPSIS
# config-settings [-h | --help] # config-settings [-h | --help]
# #
# DESCRIPTION # DESCRIPTION
# Opens an interactive full-screen TUI for managing fish config settings # Opens an interactive full-screen TUI for managing fish config settings
# across four pages: # across four pages, without having to type or remember variable names:
# #
# Universal — opinionated-category toggles, persistent (set -U / set -Ue) # Universal — opinionated-category toggles (C1C6) + master, persistent (set -U)
# Session — opinionated-category toggles, this shell only (set -g / set -eg) # Session — the same toggles, current shell only (set -g)
# Sponge — sponge history-scrubbing settings (delay, codes, secrets …) # Sponge — sponge history-scrubbing settings: delay, successful exit
# Paths — scrollback log dir, log max, and user-dots path # codes, purge-only-on-exit, allow-previously-successful, and
# extra sensitive variable-name tokens
# Paths — scrollback log directory, scrollback max files, the user-dots
# path, and the user-dots convenience symlink toggle (Dots link)
# #
# Toggle rows use ← / → (or h / l) to step OFF ← DEFAULT → ON. # Toggle rows use ← / → (or h / l) to step OFF ← DEFAULT → ON; DEFAULT erases
# Value rows (Sponge, Paths) use Enter to edit inline; ← / h clears to default. # the variable so the master switch / built-in default applies. Value rows
# (Sponge, Paths) use Enter to edit inline; ← / h clears to default. List rows
# (e.g. Extra secret, OK codes) accept values separated by commas and/or
# whitespace — "A, B", "A,B" and "A B" all yield the same two entries.
# Tab / Shift-Tab cycle forward / backward through pages. # Tab / Shift-Tab cycle forward / backward through pages.
# Changes apply immediately — no confirm step. Always available regardless of # Changes apply immediately — no confirm step. Always available regardless of
# __fish_config_opinionated state. # __fish_config_opinionated state.
# #
# The Sponge and Paths pages always write universal variables — these are
# persistent, set-and-forget settings with no per-session scope. Editing a
# scrollback row updates both the __fish_scrollback_history_* source-of-truth
# variables and the exported SCROLLBACK_HISTORY_* mirrors, so the AUR/tmux/
# zellij log wrappers (which read the exported names) see the change in the
# running session.
#
# 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 >= 9078-wide panel (most detail)
# COLUMNS >= 8674-wide panel
# COLUMNS >= 8270-wide panel
# COLUMNS < 8252-wide panel (default)
#
# Navigation:
# ↑ ↓ / k j Move cursor
# ← → / h l Toggle rows: OFF ← DEFAULT → ON
# ← / h Value rows: clear to default
# Enter Value rows: edit inline (Sponge / Paths pages)
# Tab / S-Tab Next / previous page
# q / Escape Exit
#
# ARGUMENTS # ARGUMENTS
# -h, --help Print usage and exit # -h, --help Print usage and exit
# #
+6
View File
@@ -1,6 +1,12 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 14-miscellaneous
#
# DEPENDENCIES
# config-settings
#
# SYNOPSIS # SYNOPSIS
# config-toggle [args...] # config-toggle [args...]
# #
+4 -1
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 14-miscellaneous
#
# SYNOPSIS # SYNOPSIS
# config-update [-h | --help] [-f | --force] [-n | --dry-run] # config-update [-h | --help] [-f | --force] [-n | --dry-run]
# #
@@ -8,7 +11,7 @@
# Pulls the latest fish shell configuration from the upstream repository # Pulls the latest fish shell configuration from the upstream repository
# into ~/.config/fish. Git output is suppressed; status is reported # into ~/.config/fish. Git output is suppressed; status is reported
# through colored messages. After a successful pull the function prints a # through colored messages. After a successful pull the function prints a
# short summary of changed files. # short summary of changed files; run `exec fish` to reload the shell.
# #
# ARGUMENTS # ARGUMENTS
# -h, --help Show this help message and exit # -h, --help Show this help message and exit
+4
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 01-file-and-directory
#
# SYNOPSIS # SYNOPSIS
# copy <source> <dest> # copy <source> <dest>
# #
@@ -14,6 +17,7 @@
# #
# EXAMPLE # EXAMPLE
# copy ./mydir/ ~/backup # copy ./mydir/ ~/backup
# copy ./mydir/ ~/backup # copies mydir INTO backup, not backup/mydir/
function copy function copy
set count (count $argv) set count (count $argv)
if test "$count" = 2; and test -d "$argv[1]" if test "$count" = 2; and test -d "$argv[1]"
+5 -1
View File
@@ -1,12 +1,16 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 08-terminal-management
#
# SYNOPSIS # SYNOPSIS
# detach [-h] [--version] <command> [args...] # detach [-h] [--version] <command> [args...]
# #
# DESCRIPTION # DESCRIPTION
# Runs a command in the background using nohup, fully detached from the # Runs a command in the background using nohup, fully detached from the
# terminal with all output discarded. # terminal with stdout/stderr discarded. The command survives the current
# session.
# #
# ARGUMENTS # ARGUMENTS
# -h, --help Show help message # -h, --help Show help message
+4
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 13-media-and-utilities
#
# SYNOPSIS # SYNOPSIS
# dng2avif [-h] [-i <file>] [-o <file>] [-q <n>] [-s <n>] [input.dng] # dng2avif [-h] [-i <file>] [-o <file>] [-q <n>] [-s <n>] [input.dng]
# #
@@ -22,6 +25,7 @@
# #
# EXAMPLE # EXAMPLE
# dng2avif photo.dng # dng2avif photo.dng
# dng2avif -q 85 -s 5 -i shot.dng -o out.avif
function dng2avif --description 'Convert DNG raw to 10-bit HDR AVIF' function dng2avif --description 'Convert DNG raw to 10-bit HDR AVIF'
set -l options (fish_opt -s h -l help) set -l options (fish_opt -s h -l help)
set -a options (fish_opt -s i -l input -r) set -a options (fish_opt -s i -l input -r)
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 14-miscellaneous
#
# SYNOPSIS # SYNOPSIS
# dockup [-h] [directory] # dockup [-h] [directory]
# #
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 12-ai-and-developer-tools
#
# SYNOPSIS # SYNOPSIS
# docker [subcommand] [args...] # docker [subcommand] [args...]
# #
+10 -6
View File
@@ -1,22 +1,26 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 01-file-and-directory
#
# SYNOPSIS # SYNOPSIS
# du [--disk|--dir|--dua] [args...] # du [--disk|--dir|--dua] [args...]
# #
# DESCRIPTION # DESCRIPTION
# Smart disk-usage wrapper that routes to duf (disk overview), dust (directory # Smart disk-usage dispatcher. Without flags, routes to the most appropriate
# tree), or dua based on context or explicit flags. Falls back to system du # tool by context; explicit flags force one. Falls back to system du when the
# when the preferred tool is not installed. # preferred tool is not installed.
# #
# ARGUMENTS # ARGUMENTS
# --disk Force duf for disk-level overview # --disk Force duf (disk-level free/used overview)
# --dir Force dust for directory-level breakdown # --dir Force dust (per-directory tree breakdown)
# --dua Force dua interactive mode # --dua Force dua (fast interactive space analyzer)
# args... Files/directories or flags forwarded to the selected tool # args... Files/directories or flags forwarded to the selected tool
# #
# EXAMPLE # EXAMPLE
# du ~/Downloads # du ~/Downloads
# du --disk
function du --description 'Execute du' function du --description 'Execute du'
# Opinionated guard (C1): fall back to bare command du when disabled. # Opinionated guard (C1): fall back to bare command du when disabled.
if not __fish_config_op_enabled __fish_config_op_aliases if not __fish_config_op_enabled __fish_config_op_aliases
+4
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 01-file-and-directory
#
# SYNOPSIS # SYNOPSIS
# dusize [dir] # dusize [dir]
# #
@@ -13,6 +16,7 @@
# #
# EXAMPLE # EXAMPLE
# dusize ~/Downloads # dusize ~/Downloads
# dusize ~/Videos
function dusize --wraps='du' --description 'alias dusize=du' function dusize --wraps='du' --description 'alias dusize=du'
du -sh (test -n "$argv[1]"; and echo $argv[1]; or echo .) du -sh (test -n "$argv[1]"; and echo $argv[1]; or echo .)
end end
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 03-editors-and-viewers
#
# SYNOPSIS # SYNOPSIS
# edit [-V|-t] [-e EDITOR] [-c] [-x TEXT] [-n] [-v|-s] [FILE...] # edit [-V|-t] [-e EDITOR] [-c] [-x TEXT] [-n] [-v|-s] [FILE...]
# #
+25 -1
View File
@@ -1,4 +1,28 @@
# Edit and execute the last command (Bash-style fc) # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 03-editors-and-viewers
#
# SYNOPSIS
# fc [command_prefix]
#
# DESCRIPTION
# Edits the last shell command -- or the most recent one matching a
# prefix -- in $EDITOR, then executes the result. Bash-style fc
# behaviour. Falls back to vi when $EDITOR is unset, and aborts without
# executing if the buffer is left empty.
#
# ARGUMENTS
# command_prefix Search history for the newest command matching this
#
# RETURNS
# The edited command's exit status, or a message when history lookup
# found nothing.
#
# EXAMPLE
# fc
# fc git
function fc --description 'Edit and execute the last command (Bash-style fc)' function fc --description 'Edit and execute the last command (Bash-style fc)'
set -l tmpfile (mktemp /tmp/fish_fc.XXXXXX).fish set -l tmpfile (mktemp /tmp/fish_fc.XXXXXX).fish
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 14-miscellaneous
#
# SYNOPSIS # SYNOPSIS
# ffetch [args...] # ffetch [args...]
# #
+26 -2
View File
@@ -1,12 +1,33 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 06-dependency-management
#
# SYNOPSIS # SYNOPSIS
# fish-deps [status|install|update|sync] # fish-deps [status|install|update|sync]
# #
# DESCRIPTION # DESCRIPTION
# Manages fish shell dependencies by dispatching to subcommand handlers. # Unified command for managing all tools this configuration depends on,
# Defaults to status when no subcommand is given. # dispatching to subcommand handlers. Defaults to status when no subcommand
# is given.
#
# 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, yt-dlp
# #
# ARGUMENTS # ARGUMENTS
# status Report installed/missing deps (default) # status Report installed/missing deps (default)
@@ -20,6 +41,9 @@
# #
# EXAMPLE # EXAMPLE
# fish-deps sync # fish-deps sync
# fish-deps
# fish-deps install
# fish-deps update
function fish-deps --description 'Manage fish shell dependencies' function fish-deps --description 'Manage fish shell dependencies'
set -l subcmd $argv[1] set -l subcmd $argv[1]
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 06-dependency-management
#
# SYNOPSIS # SYNOPSIS
# fzf-update # fzf-update
# #
+10 -4
View File
@@ -1,13 +1,17 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 04-git-and-version-control
#
# SYNOPSIS # SYNOPSIS
# gi [-h] [-b] [-p] [-s] [targets...] # gi [-h] [-b] [-p] [-s] [-l] [targets...]
# #
# DESCRIPTION # DESCRIPTION
# Generates .gitignore content by querying the gitignore.io API. Appends # Generates .gitignore content by querying the gitignore.io API. Appends
# results to the repository's .gitignore with MD5-based deduplication, or # results to the repository's .gitignore with MD5-based deduplication
# prints to stdout with -s. Supports boilerplate and interactive prompt modes. # patterns already present are not re-appended — or prints to stdout with
# -s. Supports generic boilerplate and interactive prompt modes.
# #
# ARGUMENTS # ARGUMENTS
# -h, --help Show help message # -h, --help Show help message
@@ -16,7 +20,7 @@
# -b, --boilerplate Append boilerplate from $GITIGNORE_BOILERPLATE # -b, --boilerplate Append boilerplate from $GITIGNORE_BOILERPLATE
# -p, --prompt Prompt for patterns to append # -p, --prompt Prompt for patterns to append
# -s, --stdout Print API output to stdout instead of .gitignore # -s, --stdout Print API output to stdout instead of .gitignore
# targets Comma-separated list of language/tool names # targets Comma- or space-separated list of language/tool names
# #
# RETURNS # RETURNS
# 0 Patterns appended or printed # 0 Patterns appended or printed
@@ -24,6 +28,8 @@
# #
# EXAMPLE # EXAMPLE
# gi python,venv # gi python,venv
# gi -b -p
# gi -s node > .gitignore
function gi --description 'Generate .gitignore files using the gitignore.io API' function gi --description 'Generate .gitignore files using the gitignore.io API'
argparse h/help d/description l/list b/boilerplate p/prompt s/stdout -- $argv argparse h/help d/description l/list b/boilerplate p/prompt s/stdout -- $argv
or return 1 or return 1
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 10-network
#
# SYNOPSIS # SYNOPSIS
# gip # gip
# #
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 10-network
#
# SYNOPSIS # SYNOPSIS
# gip4 # gip4
# #
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 10-network
#
# SYNOPSIS # SYNOPSIS
# gip6 # gip6
# #
+7 -3
View File
@@ -1,13 +1,16 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 04-git-and-version-control
#
# SYNOPSIS # SYNOPSIS
# git-clean [-h] [-f] # git-clean [-h] [-f]
# #
# DESCRIPTION # DESCRIPTION
# Fetches and prunes the remote, updates the current branch, and deletes # Fetches and prunes the remote, fast-forwards the current branch, and
# local branches whose tracking remote has been deleted. Automatically moves # deletes local branches whose tracking remote has been deleted. Switches to
# to main if currently on an orphaned branch. # main/master automatically if the current branch is orphaned.
# #
# ARGUMENTS # ARGUMENTS
# -h, --help Show help message # -h, --help Show help message
@@ -19,6 +22,7 @@
# #
# EXAMPLE # EXAMPLE
# git-clean --force # git-clean --force
# git-clean
function git-clean --description 'Sync main, prune remotes, and delete orphaned branches' function git-clean --description 'Sync main, prune remotes, and delete orphaned branches'
set -l options h/help f/force set -l options h/help f/force
argparse $options -- $argv argparse $options -- $argv
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 04-git-and-version-control
#
# SYNOPSIS # SYNOPSIS
# gitui [args...] # gitui [args...]
# #
+23 -1
View File
@@ -1,4 +1,26 @@
# Fetch updates and show git status # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 04-git-and-version-control
#
# SYNOPSIS
# gitup [args...]
#
# DESCRIPTION
# Fetches updates from the remote and shows git status. Extra arguments
# are forwarded to git fetch.
#
# ARGUMENTS
# args... Forwarded verbatim to git fetch
#
# RETURNS
# 0 Fetch and status succeeded
# 1 Not inside a git work tree
#
# EXAMPLE
# gitup
# gitup --all
function gitup --description 'Fetch updates and show git status' function gitup --description 'Fetch updates and show git status'
# Check if we are even in a git repository # Check if we are even in a git repository
if not git rev-parse --is-inside-work-tree >/dev/null 2>&1 if not git rev-parse --is-inside-work-tree >/dev/null 2>&1
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 04-git-and-version-control
#
# SYNOPSIS # SYNOPSIS
# hist # hist
# #
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 14-miscellaneous
#
# SYNOPSIS # SYNOPSIS
# joplin [args...] # joplin [args...]
# #
+16 -9
View File
@@ -1,21 +1,28 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 14-miscellaneous
#
# SYNOPSIS # SYNOPSIS
# kitty-logging [install | uninstall | status | dismiss] [-h] # kitty-logging [install | uninstall | status | dismiss] [-h]
# #
# DESCRIPTION # DESCRIPTION
# Manages the fish-config Kitty scrollback watcher. `install` copies the # Manages the fish-config Kitty scrollback watcher that powers C5 logging.
# canonical watcher into the Kitty config dir and wires it into kitty.conf via # `install` symlinks the canonical watcher into the Kitty config dir (so it
# a sentinel-marked managed block (commenting out any conflicting active # always tracks the source) and wires it into kitty.conf via a
# watcher line to avoid double-capture). `uninstall` reverses it. `status` # sentinel-marked managed block, commenting out any conflicting active
# reports wiring, watcher version, and C5 logging state. `dismiss` silences the # watcher line to avoid double-capture. `uninstall` reverses it. `status`
# per-session setup reminder. Runtime capture remains gated by the C5 # reports wiring, installed watcher version, and C5 logging state. `dismiss`
# .logging_disabled sentinel; install affects future Kitty instances only. # silences 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.
# #
# ARGUMENTS # ARGUMENTS
# install Copy the watcher and add the managed block to kitty.conf # install Symlink the watcher and add the managed block to kitty.conf
# uninstall Remove the managed block and the installed watcher # uninstall Remove the managed block and the watcher symlink
# status Report wiring, watcher version, and C5 logging state # status Report wiring, watcher version, and C5 logging state
# dismiss Stop the per-session reminder # dismiss Stop the per-session reminder
# -h, --help Show this help # -h, --help Show this help
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 01-file-and-directory
#
# SYNOPSIS # SYNOPSIS
# lD [args...] # lD [args...]
# #
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 14-miscellaneous
#
# SYNOPSIS # SYNOPSIS
# ld # ld
# #
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 03-editors-and-viewers
#
# SYNOPSIS # SYNOPSIS
# less [args...] # less [args...]
# #
+5 -1
View File
@@ -1,13 +1,17 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 07-system-and-monitoring
#
# SYNOPSIS # SYNOPSIS
# limine-edit # limine-edit
# #
# DESCRIPTION # DESCRIPTION
# Opens /boot/limine.conf in sudoedit, then re-enrolls the config hash, # Opens /boot/limine.conf in sudoedit, then re-enrolls the config hash,
# runs CachyOS boot hooks (limine-mkinitcpio), and re-signs all Secure Boot # runs CachyOS boot hooks (limine-mkinitcpio), and re-signs all Secure Boot
# files tracked by sbctl. # files tracked by sbctl. Combines the edit and sign steps into a single
# command.
# #
# EXAMPLE # EXAMPLE
# limine-edit # limine-edit
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 07-system-and-monitoring
#
# SYNOPSIS # SYNOPSIS
# lock # lock
# #
+15
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 11-pager-and-logging
#
# SYNOPSIS # SYNOPSIS
# logs [-h] [-c <category>] # logs [-h] [-c <category>]
# #
@@ -8,6 +11,16 @@
# Interactively browses terminal log files (scrollback, paru, yay) sorted # Interactively browses terminal log files (scrollback, paru, yay) sorted
# newest-first using fzf. Supports viewing in $PAGER, editing, and deletion. # newest-first using fzf. Supports viewing in $PAGER, editing, and deletion.
# #
# 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.
#
# ARGUMENTS # ARGUMENTS
# -h, --help Show help message # -h, --help Show help message
# -c, --category cat Filter to one category: scrollback, paru, or yay # -c, --category cat Filter to one category: scrollback, paru, or yay
@@ -18,6 +31,8 @@
# #
# EXAMPLE # EXAMPLE
# logs -c paru # logs -c paru
# logs
# logs -c scrollback
function logs --description 'Browse terminal log files interactively with fzf' function logs --description 'Browse terminal log files interactively with fzf'
# Opinionated guard (C4): integrations disabled # Opinionated guard (C4): integrations disabled
if not __fish_config_op_enabled __fish_config_op_integrations if not __fish_config_op_enabled __fish_config_op_integrations
+5
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 01-file-and-directory
#
# SYNOPSIS # SYNOPSIS
# ls [args...] # ls [args...]
# #
@@ -13,6 +16,8 @@
# #
# EXAMPLE # EXAMPLE
# ls ~/projects # ls ~/projects
# ls
# ls -a ~/projects
function ls --description 'List all files' function ls --description 'List all files'
# Opinionated guard (C1): fall back to bare command ls when disabled. # Opinionated guard (C1): fall back to bare command ls when disabled.
if not __fish_config_op_enabled __fish_config_op_aliases if not __fish_config_op_enabled __fish_config_op_aliases
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 01-file-and-directory
#
# SYNOPSIS # SYNOPSIS
# lsr [args...] # lsr [args...]
# #
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 01-file-and-directory
#
# SYNOPSIS # SYNOPSIS
# lss [args...] # lss [args...]
# #
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 01-file-and-directory
#
# SYNOPSIS # SYNOPSIS
# lstree [args...] # lstree [args...]
# #
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 01-file-and-directory
#
# SYNOPSIS # SYNOPSIS
# lt [args...] # lt [args...]
# #
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 01-file-and-directory
#
# SYNOPSIS # SYNOPSIS
# ltr [args...] # ltr [args...]
# #
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 01-file-and-directory
#
# SYNOPSIS # SYNOPSIS
# lx [args...] # lx [args...]
# #
+4
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 01-file-and-directory
#
# SYNOPSIS # SYNOPSIS
# mkcd [-s | --silent] <dir> # mkcd [-s | --silent] <dir>
# #
@@ -21,6 +24,7 @@
# #
# EXAMPLE # EXAMPLE
# mkcd ~/projects/myapp # mkcd ~/projects/myapp
# mkcd ~/projects/newapp/src
function mkcd --description 'Create a directory (with parents) and cd into it' function mkcd --description 'Create a directory (with parents) and cd into it'
set -l c_head (set_color --bold cyan) set -l c_head (set_color --bold cyan)
set -l c_cmd (set_color --bold white) set -l c_cmd (set_color --bold white)
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 01-file-and-directory
#
# SYNOPSIS # SYNOPSIS
# mkdir [args...] # mkdir [args...]
# #
+8 -1
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 14-miscellaneous
#
# SYNOPSIS # SYNOPSIS
# open-url [-s|--silent] [-v|--verbose] <url> # open-url [-s|--silent] [-v|--verbose] <url>
# open-url --help # open-url --help
@@ -11,7 +14,8 @@
# binary rather than deferring to xdg-open, whose MIME dispatch can hand # binary rather than deferring to xdg-open, whose MIME dispatch can hand
# local text/html files to non-browser apps (e.g. ebook readers). # local text/html files to non-browser apps (e.g. ebook readers).
# #
# Silent by default: prints nothing on success (errors always go to stderr). # Silent by default: prints nothing on success (errors always go to stderr);
# --silent / -s is accepted for explicitness.
# #
# Resolution order: # Resolution order:
# 1. $fish_help_browser (explicit override) # 1. $fish_help_browser (explicit override)
@@ -33,6 +37,9 @@
# EXAMPLE # EXAMPLE
# open-url https://git.rootiest.dev/rootiest/fish-config # open-url https://git.rootiest.dev/rootiest/fish-config
# open-url -v https://fish-config-docs.pages.dev/ # open-url -v https://fish-config-docs.pages.dev/
#
# NOTES
# Typo abbreviation: url-open (expands to open-url on space/enter).
function open-url --description 'Open a URL in the best available web browser' function open-url --description 'Open a URL in the best available web browser'
argparse h/help s/silent v/verbose -- $argv argparse h/help s/silent v/verbose -- $argv
or return 1 or return 1
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 09-clipboard
#
# SYNOPSIS # SYNOPSIS
# p [args...] # p [args...]
# #
+4
View File
@@ -1,12 +1,16 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 05-package-management
#
# SYNOPSIS # SYNOPSIS
# parur # parur
# #
# DESCRIPTION # DESCRIPTION
# Presents an fzf picker of all installed packages (via pacman -Qqs) with # Presents an fzf picker of all installed packages (via pacman -Qqs) with
# pacman -Qi previews, then removes the selected packages using paru or yay. # pacman -Qi previews, then removes the selected packages using paru or yay.
# Arch Linux only.
# #
# RETURNS # RETURNS
# 0 Packages removed or none selected # 0 Packages removed or none selected
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 09-clipboard
#
# SYNOPSIS # SYNOPSIS
# paste [args...] # paste [args...]
# #
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 10-network
#
# SYNOPSIS # SYNOPSIS
# ping [args...] # ping [args...]
# #
+11
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 05-package-management
#
# SYNOPSIS # SYNOPSIS
# pkg [-h] [-i|-u] <package> [package...] # pkg [-h] [-i|-u] <package> [package...]
# #
@@ -10,6 +13,14 @@
# In auto mode (no flag), detects whether each package is installed and # In auto mode (no flag), detects whether each package is installed and
# toggles it — installing if absent, removing if present. # toggles it — installing if absent, removing if present.
# #
# The package-installed check uses the correct query for each manager:
#
# pacman/paru/yay pacman -Qi
# apt dpkg -s
# dnf/zypper/yum rpm -q
# brew brew list
# pkg pkg info
#
# ARGUMENTS # ARGUMENTS
# -h, --help Show help message # -h, --help Show help message
# -i, --install Force install mode # -i, --install Force install mode
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 01-file-and-directory
#
# SYNOPSIS # SYNOPSIS
# poke <file> [file...] # poke <file> [file...]
# #
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 07-system-and-monitoring
#
# SYNOPSIS # SYNOPSIS
# ports # ports
# #
+14 -6
View File
@@ -1,16 +1,22 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 12-ai-and-developer-tools
#
# SYNOPSIS # SYNOPSIS
# qc [prompt...] # qc [prompt...]
# #
# DESCRIPTION # DESCRIPTION
# Quick-chat wrapper around aichat using the "cli" role. Resolves the # Quick-chat wrapper around the aichat LLM CLI that defaults to the "cli"
# aichat config directory (honoring $XDG_CONFIG_HOME), creates it if # role — a system prompt tuned for concise, terminal-friendly output.
# missing, and installs the bundled cli-agent role as a symlink at # Resolves the aichat config directory (honoring $XDG_CONFIG_HOME), creates
# roles/cli.md on first use. Inherits aichat's own flags and tab # it if missing, and on first use installs the bundled role by symlinking
# completions (--wraps). The function is only defined when aichat is # scripts/cli-agent.md to $XDG_CONFIG_HOME/aichat/roles/cli.md. Inherits
# installed. # every aichat flag and tab completion (--wraps aichat); passing --role/-r
# overrides the default role, so qc forwards to aichat unchanged. The
# function is only defined when aichat is installed. Run `qc --help` for
# aichat's full flag reference with the command name rewritten to qc.
# #
# ARGUMENTS # ARGUMENTS
# prompt... Prompt forwarded to aichat # prompt... Prompt forwarded to aichat
@@ -21,6 +27,8 @@
# #
# EXAMPLE # EXAMPLE
# qc "how do I list open ports on linux?" # qc "how do I list open ports on linux?"
# qc -m ollama:llama3 "explain this error"
# qc --role coder "refactor this function"
if type -q aichat if type -q aichat
function qc --wraps aichat --description 'Quick-chat wrapper around aichat (cli role)' function qc --wraps aichat --description 'Quick-chat wrapper around aichat (cli role)'
if contains -- -h $argv; or contains -- --help $argv if contains -- -h $argv; or contains -- --help $argv
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 10-network
#
# SYNOPSIS # SYNOPSIS
# qr [text...] # qr [text...]
# #
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 03-editors-and-viewers
#
# SYNOPSIS # SYNOPSIS
# rawfish [args...] # rawfish [args...]
# #
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 14-miscellaneous
#
# SYNOPSIS # SYNOPSIS
# replay <commands> # replay <commands>
# #
+9
View File
@@ -1,6 +1,12 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 14-miscellaneous
#
# DEPENDENCIES
# open-url
#
# SYNOPSIS # SYNOPSIS
# repo-open [-p|--print] [-r|--root] # repo-open [-p|--print] [-r|--root]
# repo-open --help # repo-open --help
@@ -39,6 +45,9 @@
# repo-open # open current branch (+ subdir) in browser # repo-open # open current branch (+ subdir) in browser
# repo-open --print # just print the URL # repo-open --print # just print the URL
# repo-open --root # repo home page for the current branch # repo-open --root # repo home page for the current branch
#
# NOTES
# Typo abbreviation: open-repo (expands to repo-open on space/enter).
function repo-open --description 'Open the origin remote of the current repo in a browser' function repo-open --description 'Open the origin remote of the current repo in a browser'
argparse -X 0 h/help p/print r/root -- $argv argparse -X 0 h/help p/print r/root -- $argv
or return 1 or return 1
+5
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 01-file-and-directory
#
# SYNOPSIS # SYNOPSIS
# rg [args...] # rg [args...]
# #
@@ -14,6 +17,8 @@
# #
# EXAMPLE # EXAMPLE
# rg "TODO" src/ # rg "TODO" src/
# rg "fish_greeting" ~/.config/fish/
# rg -l "TODO" ~/projects/myapp
function rg --description 'alias rg=rg --hyperlink-format=kitty' function rg --description 'alias rg=rg --hyperlink-format=kitty'
# Opinionated guard (C1): fall back to bare command rg when disabled. # Opinionated guard (C1): fall back to bare command rg when disabled.
if not __fish_config_op_enabled __fish_config_op_aliases if not __fish_config_op_enabled __fish_config_op_aliases
+7 -1
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 01-file-and-directory
#
# SYNOPSIS # SYNOPSIS
# rm [-e [options] | -S | args...] # rm [-e [options] | -S | args...]
# #
@@ -18,7 +21,7 @@
# ARGUMENTS # ARGUMENTS
# (none) List current trash contents # (none) List current trash contents
# -e, --empty [opts] Empty the trash; opts forwarded to trash empty # -e, --empty [opts] Empty the trash; opts forwarded to trash empty
# -S, --secure Permanently delete targets and run fstrim # -S, --secure Permanently delete targets and run fstrim (irreversible)
# -r, -R, --recursive Forwarded to trash put alongside path arguments # -r, -R, --recursive Forwarded to trash put alongside path arguments
# args... Files or paths to trash or remove # args... Files or paths to trash or remove
# #
@@ -30,6 +33,9 @@
# rm file.txt # rm file.txt
# rm -e # rm -e
# rm -S sensitive_key.pem # rm -S sensitive_key.pem
#
# NOTES
# Falls back to /usr/bin/rm when trash is unavailable.
function rm --description 'Ultimate rm: trash, list, empty, and secure-erase' function rm --description 'Ultimate rm: trash, list, empty, and secure-erase'
# Opinionated guard (C1): fall back to bare command rm when disabled. # Opinionated guard (C1): fall back to bare command rm when disabled.
if not __fish_config_op_enabled __fish_config_op_aliases if not __fish_config_op_enabled __fish_config_op_aliases
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 07-system-and-monitoring
#
# SYNOPSIS # SYNOPSIS
# sbver [--brief] # sbver [--brief]
# #
+3
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 07-system-and-monitoring
#
# SYNOPSIS # SYNOPSIS
# screensleep # screensleep
# #
+4 -1
View File
@@ -1,6 +1,9 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 01-file-and-directory
#
# SYNOPSIS # SYNOPSIS
# scrub [-a] [-d] [-h] # scrub [-a] [-d] [-h]
# #
@@ -12,7 +15,7 @@
# IDE directories, and AI tool artifacts. # IDE directories, and AI tool artifacts.
# #
# ARGUMENTS # ARGUMENTS
# -a, --aggressive Also purge node_modules, *.log, .idea, AI artifacts # -a, --aggressive Also purge node_modules, *.log, .cache, .idea, AI artifacts
# -d, --dry-run Show targets without deleting # -d, --dry-run Show targets without deleting
# -h, --help Show usage help # -h, --help Show usage help
# #
+4 -1
View File
@@ -1,12 +1,15 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 05-package-management
#
# SYNOPSIS # SYNOPSIS
# search [args...] # search [args...]
# #
# DESCRIPTION # DESCRIPTION
# Delegates to paru or yay for interactive AUR package search and # Delegates to paru or yay for interactive AUR package search and
# installation. Falls back to yay if paru is not installed. # installation. Falls back to yay if paru is not installed. Arch Linux only.
# #
# ARGUMENTS # ARGUMENTS
# args... Arguments forwarded to paru or yay # args... Arguments forwarded to paru or yay
+12 -3
View File
@@ -1,13 +1,17 @@
# Copyright (C) 2026 Rootiest # Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later # SPDX-License-Identifier: AGPL-3.0-or-later
# CATEGORY
# 11-pager-and-logging
#
# SYNOPSIS # SYNOPSIS
# smart_exit [-h] [-n] # smart_exit [-h] [-n]
# #
# DESCRIPTION # DESCRIPTION
# Closes the shell session, capturing and archiving the terminal scrollback # Closes the shell session. In Kitty, captures the terminal scrollback to a
# log before exit (Kitty only). Automatically prunes junk and excess log # timestamped log file in $SCROLLBACK_HISTORY_DIR before exiting.
# files according to $SCROLLBACK_HISTORY_MAX_FILES. # Automatically prunes junk and the oldest logs when the count exceeds
# $SCROLLBACK_HISTORY_MAX_FILES.
# #
# ARGUMENTS # ARGUMENTS
# -h, --help Show help message # -h, --help Show help message
@@ -18,7 +22,12 @@
# 1 Argument parsing failed # 1 Argument parsing failed
# #
# EXAMPLE # EXAMPLE
# smart_exit
# smart_exit --no-log # smart_exit --no-log
#
# NOTES
# The exit builtin is wired to smart_exit for interactive sessions. Typing
# `exit` or Ctrl+D behaves identically to calling smart_exit directly.
function smart_exit --description 'Capture colorized scrollback before exiting, with pruning and safe overrides' function smart_exit --description 'Capture colorized scrollback before exiting, with pruning and safe overrides'
# Opinionated guard (C3): exit plainly when overrides are disabled. # Opinionated guard (C3): exit plainly when overrides are disabled.
# This composes with Task #4's __fish_config_enable_logging, which will # This composes with Task #4's __fish_config_enable_logging, which will

Some files were not shown because too many files have changed in this diff Show More