feat: CLASSIFICATION function-header field + shadow-classification lint #163
@@ -391,6 +391,7 @@ all optional except where noted:
|
||||
| `CATEGORY` | **Required to appear in the manual at all** — see below. |
|
||||
| `COMPONENT` | Only for functions gated by the [opinionated-component system](#opinionated-components). |
|
||||
| `DEPENDENCIES` | Other functions this one calls that a reader may want to look up. |
|
||||
| `CLASSIFICATION` | Hazard/shadow-interaction tags — see below. |
|
||||
| `SYNOPSIS` | One-line usage form. |
|
||||
| `DESCRIPTION` | Prose description; can span multiple paragraphs. |
|
||||
| `ARGUMENTS` | Flags/positional args, one per line. |
|
||||
@@ -414,6 +415,9 @@ A full example (`functions/claude.fish`):
|
||||
# DEPENDENCIES
|
||||
# agents-init
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(claude)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# claude [ARGS...]
|
||||
#
|
||||
@@ -443,6 +447,14 @@ If your function genuinely doesn't fit any of these, add a new
|
||||
`docs/manual/05-functions/NN-your-category.md` stub (with frontmatter
|
||||
matching its siblings) rather than force-fitting it into an existing one.
|
||||
|
||||
**`CLASSIFICATION` flags hazards and shadow interactions, optional and
|
||||
omitted when nothing applies:** whether the function calls a
|
||||
[C1-shadowed command](docs/manual/08-components-reference/01-c1-command-shadows.md)
|
||||
bare wanting the override (`uses-shadow(ls)`) or bypasses it deliberately
|
||||
via `command`/`builtin` (`bypasses-shadow(cat)`), and general hazards —
|
||||
`destructive`, `network`, `blocking-prompt`. Full tag definitions and
|
||||
placement rule: [`docs/function-classification-schema.md`](docs/function-classification-schema.md).
|
||||
|
||||
### Private/internal helper functions
|
||||
|
||||
Functions named with a leading `_` (e.g. `_agents_init_ensure_gitignore`,
|
||||
|
||||
@@ -24,6 +24,9 @@ __fish_config_op_enabled (status basename); or exit
|
||||
# COMPONENT
|
||||
# autoexec/sync
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(cat)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# __auto_pull_on_pwd (event handler, --on-variable PWD)
|
||||
#
|
||||
|
||||
+6
-4
@@ -97,11 +97,13 @@ if __fish_config_op_enabled (status basename) tricks-bang
|
||||
end
|
||||
end
|
||||
|
||||
# Fish command history override to show timestamps
|
||||
# Shadowing the history command is opinionated (C1 aliasing); when disabled,
|
||||
# the function is never defined and fish's stock history behavior applies.
|
||||
# Timestamped history view. Named pretty-history (not history) so it never
|
||||
# shadows the fish builtin -- every function in this config that expects
|
||||
# stock `history` semantics (search, --max, merge, ...) would otherwise
|
||||
# silently break, which has happened more than once. Opinionated (C1
|
||||
# aliasing); when disabled, the function is never defined.
|
||||
if __fish_config_op_enabled (status basename) aliases-tricks
|
||||
function history
|
||||
function pretty-history --description 'History with timestamps prepended to every entry'
|
||||
builtin history --show-time='%F %T '
|
||||
end
|
||||
end
|
||||
|
||||
@@ -703,6 +703,29 @@ ENTRY_HEADS = {
|
||||
}
|
||||
|
||||
|
||||
def _classification_tags(raw: list[str]) -> list[str]:
|
||||
"""Split a CLASSIFICATION body into its comma-separated tags.
|
||||
|
||||
A plain comma split (as `names()` uses for DEPENDENCIES) would break on
|
||||
the commas inside `uses-shadow(rm, cp)`-style tags, so this only splits
|
||||
on commas at paren depth 0.
|
||||
"""
|
||||
text = " ".join(raw)
|
||||
tags: list[str] = []
|
||||
depth = 0
|
||||
start = 0
|
||||
for i, ch in enumerate(text):
|
||||
if ch == "(":
|
||||
depth += 1
|
||||
elif ch == ")":
|
||||
depth = max(0, depth - 1)
|
||||
elif ch == "," and depth == 0:
|
||||
tags.append(text[start:i].strip())
|
||||
start = i + 1
|
||||
tags.append(text[start:].strip())
|
||||
return [t for t in tags if t]
|
||||
|
||||
|
||||
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.
|
||||
|
||||
@@ -739,6 +762,7 @@ def render_entry(fn: dict[str, list[str]], used_by: list[str], link=None) -> str
|
||||
refs = []
|
||||
for label, values in (
|
||||
("Dependencies", names(fn.get("DEPENDENCIES", []))),
|
||||
("Classification", _classification_tags(fn.get("CLASSIFICATION", []))),
|
||||
("Used by", sorted(used_by)),
|
||||
):
|
||||
if values:
|
||||
@@ -884,6 +908,7 @@ def render_entry_site(fn: dict[str, list[str]], used_by: list[str], link=None) -
|
||||
refs = []
|
||||
for label, values in (
|
||||
("Dependencies", names(fn.get("DEPENDENCIES", []))),
|
||||
("Classification", _classification_tags(fn.get("CLASSIFICATION", []))),
|
||||
("Used by", sorted(used_by)),
|
||||
):
|
||||
if values:
|
||||
|
||||
@@ -291,6 +291,8 @@ network-shadow=### network
|
||||
monitor=### monitor
|
||||
shell-tools=### shell-tools
|
||||
dev-tools=### dev-tools
|
||||
classification=### For function authors
|
||||
shadow-classification=### For function authors
|
||||
c2=## C2 — Startup Side-Effects
|
||||
autoexec=## C2 — Startup Side-Effects
|
||||
startup=## C2 — Startup Side-Effects
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
# Function CLASSIFICATION schema
|
||||
|
||||
This is the canonical definition of the `# CLASSIFICATION` function
|
||||
doc-header label. It's referenced from code comments and commit messages —
|
||||
link here, not to anything under `AGENTS/` (that tree is git-ignored local
|
||||
agent state, not part of the repo).
|
||||
|
||||
See [Public function documentation header](../CONTRIBUTING.md#public-function-documentation-header)
|
||||
in `CONTRIBUTING.md` for where `CLASSIFICATION` fits among the other header
|
||||
labels, and [C1 — Command Shadows](manual/08-components-reference/01-c1-command-shadows.md)
|
||||
for the full list of C1-shadowed commands this schema's shadow tags refer to.
|
||||
|
||||
## Format
|
||||
|
||||
Optional. Comma-separated tags from the closed set below, on the indented
|
||||
body line directly under the label:
|
||||
|
||||
```fish
|
||||
# CLASSIFICATION
|
||||
# uses-shadow(ls), destructive
|
||||
```
|
||||
|
||||
Omit the label entirely when nothing applies — omission means "nothing to
|
||||
flag," not "not yet audited," so don't add it speculatively, and don't add
|
||||
it empty as a placeholder.
|
||||
|
||||
## Tags
|
||||
|
||||
- **`uses-shadow(name[,name...])`** — calls a C1-shadowed command (see the
|
||||
C1 doc linked above) bare, deliberately wanting the overridden behavior
|
||||
(e.g. `ls` wanting eza's icons for a human to read).
|
||||
- **`bypasses-shadow(name[,name...])`** — calls `command <name>`,
|
||||
`builtin <name>`, or (for `help` specifically) `__original_help $argv`,
|
||||
deliberately forcing stock behavior because the shadow's override would
|
||||
break this function's logic: timestamps leaking into a parsed capture,
|
||||
`-i` prompting on a path meant to run unattended, structural output
|
||||
changes breaking a `string`/`sed` parse, etc.
|
||||
- **`self-limiting(name[,name...])`** — calls a shadowed command bare, and
|
||||
it's safe not because the caller did anything but because *the shadow's
|
||||
own logic* already neutralizes the override for this call. Verify the
|
||||
actual condition per shadow, it's not the same check for each one:
|
||||
- `rm` falls back to `command rm` for any flag **except** a bare `-r`,
|
||||
`-R`, or `--recursive` (those still route to `trash put`) — so
|
||||
`rm -f`/`rm -rf` qualify, but `rm -r $dir` alone does not.
|
||||
- `mkdir` falls back to `command mkdir -p` for *any* flag at all, no
|
||||
exception.
|
||||
- `--color=auto`/`bat`'s own tty auto-detection (`grep`, `fgrep`,
|
||||
`egrep`, `dir`, `vdir`, `cat` — verified byte-identical to stock when
|
||||
piped or captured, since none of these force color on a
|
||||
non-terminal).
|
||||
|
||||
Document it explicitly rather than leaving the bare call untagged: if a
|
||||
shadow's bypass condition is ever weakened, narrowed, or removed, every
|
||||
`self-limiting` site is one grep away instead of silently wrong.
|
||||
Don't use this for `ls` — eza's long-format/icon layout is structural,
|
||||
not tty-gated, so it stays different from stock `ls` even piped; a
|
||||
bare `ls` call still needs `uses-shadow(ls)` or a real bypass.
|
||||
- **`destructive`** — can irreversibly delete or overwrite data: `rm -f`,
|
||||
`rm -rf`, truncating or force-overwriting a file, `git push --force`.
|
||||
Routine cleanup of the function's own `$tmpdir`/`$_tmpdir`/`mktemp`
|
||||
output (or other output it just created in this same call) is expected
|
||||
behavior, not a hazard — don't tag it.
|
||||
- **`network`** — makes an outbound network call: `curl`, `wget`, `ssh`,
|
||||
`git fetch`/`pull`/`push`/`clone`, `paru`/`yay` (package-manager network
|
||||
ops), talking to an API, etc.
|
||||
- **`blocking-prompt`** — can block waiting on interactive confirmation
|
||||
with no non-interactive escape hatch: a shadow's forced `-i`, fish's
|
||||
`read` (genuinely waiting on a terminal — not a `string split | read`
|
||||
or `while read` consuming a pipe, which never blocks), a `confirm`-style
|
||||
prompt with no `--yes`/`--force`/`--silent` bypass. Don't tag a function
|
||||
that's only ever meant to be run interactively at a prompt (a keybinding
|
||||
handler, an fzf-driven picker) — the hazard this tag exists for is a
|
||||
script or another function calling it unexpectedly, not a human running
|
||||
it themselves.
|
||||
|
||||
## Placement
|
||||
|
||||
Directly under `# DEPENDENCIES` if the header has one; otherwise directly
|
||||
under `# COMPONENT`; otherwise directly under `# CATEGORY`; otherwise as
|
||||
the first label in the header block (this is the common case for internal
|
||||
`_`-prefixed helpers, which usually carry none of the three).
|
||||
|
||||
## Judgment calls
|
||||
|
||||
`uses-shadow` vs `bypasses-shadow` is the easiest place to get subtly
|
||||
wrong — verify against the actual code, not just whether the name appears
|
||||
in the file. A function that only calls a *helper* which itself interacts
|
||||
with a shadow does not get the tag; the tag belongs on the helper. When
|
||||
generating these tags in bulk (e.g. delegating the sweep to another
|
||||
model), review every result against the source before trusting it — this
|
||||
schema's own rollout caught several false positives this way: a piped
|
||||
`read` misread as an interactive prompt, a documented `--yes` flag missed
|
||||
as an escape hatch, and cleanup of a function's own temp output flagged
|
||||
as `destructive` despite the explicit exclusion above.
|
||||
|
||||
`rm` specifically has its own internal flag check (any flag other than
|
||||
`-r`/`-R`/`--recursive` falls back to `command rm` *inside the shadow
|
||||
itself*, before it ever touches trash) — a caller writing plain `rm -f`
|
||||
or `rm -rf` is not bypassing anything itself, the shadow is. Only tag
|
||||
`bypasses-shadow(rm)` when the caller explicitly writes `command rm` or
|
||||
`builtin rm`; a bare `rm -f`/`rm -rf` call gets no shadow tag at all.
|
||||
@@ -19,7 +19,6 @@ all of these commands.
|
||||
rg rg --hyperlink-format=kitty system rg
|
||||
mkdir verbose path-tree display on creation mkdir -p silently
|
||||
bash XDG bashrc + $SHELL reset on exit system bash
|
||||
history timestamps prepended to every entry fish builtin history
|
||||
cp / mv forced -i confirmation prompt cp / mv unmodified
|
||||
wget forced --continue (resume downloads) system wget
|
||||
grep/fgrep/egrep forced --color=auto system grep variants
|
||||
@@ -31,6 +30,11 @@ all of these commands.
|
||||
When C1 is disabled, `rm` uses bare `command rm` with no wrapper — files
|
||||
are permanently deleted, not trashed. There is no intermediate safety net.
|
||||
|
||||
`history` itself is never shadowed — every function in this config that
|
||||
reads history depends on its stock builtin semantics. `pretty-history`
|
||||
(same `aliases-tricks` toggle) is a separate command that prints history
|
||||
with a timestamp prepended to every entry.
|
||||
|
||||
## Sub-categories
|
||||
|
||||
`__fish_config_op_aliases` sub-divides into six sub-categories, each with
|
||||
@@ -63,3 +67,48 @@ and the `help config` interception.
|
||||
`claude` (AGENTS.md/CLAUDE.md auto-linking) and `edit` (multi-editor
|
||||
launcher), plus `agy`.
|
||||
|
||||
## For function authors
|
||||
|
||||
Calling one of these names bare from inside your own function means the
|
||||
override runs whenever C1 (or its sub-category) is on — which may not be
|
||||
what your function wants: a shadow can change stdout (`cat`'s syntax
|
||||
highlighting, `mkdir`'s tree display), prompt interactively where none is
|
||||
expected (`cp`/`mv`'s forced `-i`), or reshape output structurally (`ls`'s
|
||||
icons/columns, `rg`'s hyperlink markers). If your function's logic depends
|
||||
on stock behavior, bypass the shadow deterministically, regardless of the
|
||||
toggle state:
|
||||
|
||||
Shadow Bypass Why
|
||||
─────────────────────────────────────────────────────────────────────────
|
||||
ls, cat, rm, less, du, command <name> Real external
|
||||
top, ping, ssh, rg, binaries — a
|
||||
mkdir, bash, cp, mv, real system command
|
||||
wget, grep/fgrep/egrep, exists to fall
|
||||
dir/vdir, claude back to.
|
||||
cd builtin cd The one true
|
||||
fish builtin
|
||||
in this table.
|
||||
help config __original_help $argv `help` is neither
|
||||
a builtin nor an
|
||||
external binary
|
||||
(embedded in the
|
||||
fish binary
|
||||
itself) — see
|
||||
conf.d/help.fish
|
||||
for why the
|
||||
wrapper keeps its
|
||||
own backup copy.
|
||||
edit (nothing to bypass to) Purely our own
|
||||
invention, no
|
||||
stock command
|
||||
exists. Call
|
||||
$EDITOR/$VISUAL
|
||||
yourself if you
|
||||
want a plain
|
||||
editor launch.
|
||||
|
||||
A function's own doc header records which of these it depends on: see the
|
||||
`CLASSIFICATION` label (`uses-shadow(...)` / `bypasses-shadow(...)`),
|
||||
documented in full at
|
||||
[`docs/function-classification-schema.md`](../../function-classification-schema.md).
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@ SECTIONS = (
|
||||
"CATEGORY",
|
||||
"COMPONENT",
|
||||
"DEPENDENCIES",
|
||||
"CLASSIFICATION",
|
||||
"SYNOPSIS",
|
||||
"DESCRIPTION",
|
||||
"ARGUMENTS",
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# COMPONENT
|
||||
# logging/terminal-capture
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# self-limiting(rm,mkdir)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# __fish_config_sync_logging
|
||||
#
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# Copyright (C) 2026 Rootiest
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(cat)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# __fish_help_header <name> [args...]
|
||||
#
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# Copyright (C) 2026 Rootiest
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
# CLASSIFICATION
|
||||
# self-limiting(grep)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# __fish_real_command <name>
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# COMPONENT
|
||||
# autoexec/sync
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# self-limiting(rm), destructive
|
||||
#
|
||||
# SYNOPSIS
|
||||
# __fish_user_dots_link
|
||||
#
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# Copyright (C) 2026 Rootiest
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(grep)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# __kitty_logging_has_watcher
|
||||
#
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# Copyright (C) 2026 Rootiest
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
# CLASSIFICATION
|
||||
# self-limiting(grep)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# _agents_init_ensure_gitignore <root> <label> <pattern>...
|
||||
#
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# Copyright (C) 2026 Rootiest
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
# CLASSIFICATION
|
||||
# self-limiting(rm,mkdir)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# _agents_repo_ensure_symlink <link> <target>
|
||||
#
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# Copyright (C) 2026 Rootiest
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
# CLASSIFICATION
|
||||
# uses-shadow(mkdir), bypasses-shadow(cp,grep)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# _agents_repo_install_tools <repo_dir>
|
||||
#
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# Copyright (C) 2026 Rootiest
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
# CLASSIFICATION
|
||||
# self-limiting(rm,mkdir,cat), bypasses-shadow(cp,bash), destructive, network, blocking-prompt
|
||||
#
|
||||
# SYNOPSIS
|
||||
# _fish_deps_install
|
||||
#
|
||||
@@ -281,7 +284,7 @@ function _fish_deps_install
|
||||
end
|
||||
test $_go_status -eq 0
|
||||
case special-lazydocker
|
||||
curl https://raw.githubusercontent.com/jesseduffield/lazydocker/master/scripts/install_update_linux.sh | bash
|
||||
curl https://raw.githubusercontent.com/jesseduffield/lazydocker/master/scripts/install_update_linux.sh | command bash
|
||||
case special-marktext-paru
|
||||
paru -S --noconfirm marktext-bin
|
||||
case special-marktext-yay
|
||||
@@ -309,7 +312,7 @@ function _fish_deps_install
|
||||
-o "$_tmpdir/$_zip"
|
||||
and unzip -o "$_tmpdir/$_zip" -d "$_tmpdir"
|
||||
and mkdir -p "$_wt_dir" "$HOME/.local/bin"
|
||||
and cp "$_tmpdir/$_bin_src" "$_wt_bin"
|
||||
and command cp "$_tmpdir/$_bin_src" "$_wt_bin"
|
||||
and chmod +x "$_wt_bin"
|
||||
and ln -sf "$_wt_bin" "$HOME/.local/bin/wakatime"
|
||||
rm -rf "$_tmpdir"
|
||||
@@ -320,7 +323,7 @@ function _fish_deps_install
|
||||
and curl -fL "https://github.com/equalsraf/win32yank/releases/latest/download/$_zip" \
|
||||
-o "$_tmpdir/$_zip"
|
||||
and unzip -o "$_tmpdir/$_zip" -d "$_tmpdir"
|
||||
and cp "$_tmpdir/win32yank.exe" "$HOME/.local/bin/win32yank.exe"
|
||||
and command cp "$_tmpdir/win32yank.exe" "$HOME/.local/bin/win32yank.exe"
|
||||
and chmod +x "$HOME/.local/bin/win32yank.exe"
|
||||
set -l _dl_status $status
|
||||
rm -rf "$_tmpdir"
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# Copyright (C) 2026 Rootiest
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
# CLASSIFICATION
|
||||
# self-limiting(rm,mkdir), bypasses-shadow(mv), destructive, network
|
||||
#
|
||||
# SYNOPSIS
|
||||
# _fish_deps_marktext_appimage
|
||||
#
|
||||
@@ -54,7 +57,7 @@ function _fish_deps_marktext_appimage
|
||||
and chmod +x "$tmp/marktext"
|
||||
# Replace via mv, not a write into $dest: overwriting a running AppImage
|
||||
# in place corrupts the live mount.
|
||||
and mv -f "$tmp/marktext" "$dest"
|
||||
and command mv -f "$tmp/marktext" "$dest"
|
||||
and set ok 1
|
||||
rm -rf $tmp
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# Copyright (C) 2026 Rootiest
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
# CLASSIFICATION
|
||||
# self-limiting(rm), bypasses-shadow(cp,bash), destructive, network
|
||||
#
|
||||
# SYNOPSIS
|
||||
# _fish_deps_update
|
||||
#
|
||||
@@ -90,7 +93,7 @@ function _fish_deps_update
|
||||
# lazydocker: re-run the official install/update script
|
||||
if test "$special" = curl-lazydocker
|
||||
echo "Updating $bin..."
|
||||
curl https://raw.githubusercontent.com/jesseduffield/lazydocker/master/scripts/install_update_linux.sh | bash
|
||||
curl https://raw.githubusercontent.com/jesseduffield/lazydocker/master/scripts/install_update_linux.sh | command bash
|
||||
set updated_any 1
|
||||
set i (math $i + 1)
|
||||
continue
|
||||
@@ -138,7 +141,7 @@ function _fish_deps_update
|
||||
curl -L "https://github.com/wakatime/wakatime-cli/releases/latest/download/$_zip" \
|
||||
-o "$_tmpdir/$_zip"
|
||||
and unzip -o "$_tmpdir/$_zip" -d "$_tmpdir"
|
||||
and cp "$_tmpdir/$_bin_src" "$_wt_bin"
|
||||
and command cp "$_tmpdir/$_bin_src" "$_wt_bin"
|
||||
and chmod +x "$_wt_bin"
|
||||
rm -rf "$_tmpdir"
|
||||
and set updated_any 1
|
||||
@@ -155,7 +158,7 @@ function _fish_deps_update
|
||||
curl -fL "https://github.com/equalsraf/win32yank/releases/latest/download/$_zip" \
|
||||
-o "$_tmpdir/$_zip"
|
||||
and unzip -o "$_tmpdir/$_zip" -d "$_tmpdir"
|
||||
and cp "$_tmpdir/win32yank.exe" "$HOME/.local/bin/win32yank.exe"
|
||||
and command cp "$_tmpdir/win32yank.exe" "$HOME/.local/bin/win32yank.exe"
|
||||
and chmod +x "$HOME/.local/bin/win32yank.exe"
|
||||
set -l _up_status $status
|
||||
rm -rf "$_tmpdir"
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# Copyright (C) 2026 Rootiest
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
# CLASSIFICATION
|
||||
# uses-shadow(mkdir)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# _fish_mkdir_p [--path|--tree|--silent] <dir>
|
||||
#
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# Copyright (C) 2026 Rootiest
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
# CLASSIFICATION
|
||||
# network
|
||||
#
|
||||
# SYNOPSIS
|
||||
# _mkrep_default_remote_cmd <type>
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# DEPENDENCIES
|
||||
# gh, glab, tea
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# network
|
||||
#
|
||||
# SYNOPSIS
|
||||
# _mkrep_repo_exists <type> <user> <name>
|
||||
#
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# Copyright (C) 2026 Rootiest
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(ls,rm), destructive
|
||||
#
|
||||
# SYNOPSIS
|
||||
# _prune_terminal_logs <prefix>
|
||||
#
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# Copyright (C) 2026 Rootiest
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(cat,rm), self-limiting(grep), destructive
|
||||
#
|
||||
# SYNOPSIS
|
||||
# _scrollback_prune_junk [dir]
|
||||
#
|
||||
@@ -26,7 +29,7 @@ function _scrollback_prune_junk --description 'Remove empty, trivial, and Kitty
|
||||
# Remove any completely empty log file regardless of source
|
||||
for f in $dir/*.log $dir/*.txt
|
||||
test -f $f || continue
|
||||
not test -s $f; and rm $f
|
||||
not test -s $f; and command rm -f $f
|
||||
end
|
||||
|
||||
# Remove any log with only a single meaningful line (e.g. [exited], a lone prompt, or a trivial error)
|
||||
@@ -34,7 +37,7 @@ function _scrollback_prune_junk --description 'Remove empty, trivial, and Kitty
|
||||
test -f $f || continue
|
||||
set -l line_count (command cat $f | sed 's/\x1b\[[0-9;:]*[a-zA-Z]//g' | grep -cv '^\s*$')
|
||||
if test $line_count -le 1
|
||||
rm $f
|
||||
command rm -f $f
|
||||
end
|
||||
end
|
||||
|
||||
@@ -42,7 +45,7 @@ function _scrollback_prune_junk --description 'Remove empty, trivial, and Kitty
|
||||
for f in $dir/scrollback_*.log $dir/scrollback_*.txt
|
||||
test -f $f || continue
|
||||
if command cat $f | sed 's/\x1b\[[0-9;:]*[a-zA-Z]//g' | grep -q 'Enter the new title for this tab below'
|
||||
rm $f
|
||||
command rm -f $f
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
# Copyright (C) 2026 Rootiest
|
||||
# SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
# CLASSIFICATION
|
||||
# uses-shadow(mkdir)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# _tmux_pipe_log
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# COMPONENT
|
||||
# logging/multiplexer-capture
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# uses-shadow(mkdir), bypasses-shadow(rm)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# _zellij_dump_log
|
||||
#
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# DEPENDENCIES
|
||||
# _agents_repo_install_tools, _agents_repo_sync, _agents_init_ensure_gitignore
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# self-limiting(rm,mkdir), bypasses-shadow(mv)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# agents-init [-a | --agents] [-p | --plugins] [-v | --verbose]
|
||||
# [-q | --quiet] [-s | --silent] [-h | --help]
|
||||
@@ -212,7 +215,7 @@ function agents-init --description 'scaffold AGENTS/ sub-repo with agent spec fi
|
||||
if test $has_agents -eq 1; and test $has_claude -eq 1
|
||||
# Both exist: preserve each as its own file in AGENTS/
|
||||
if not test -f "$agents_dir/AGENTS.md"
|
||||
if not mv "$root/AGENTS.md" "$agents_dir/AGENTS.md"
|
||||
if not command mv "$root/AGENTS.md" "$agents_dir/AGENTS.md"
|
||||
echo "$c_err""Error: could not move AGENTS.md → AGENTS/AGENTS.md$c_reset" >&2
|
||||
return 1
|
||||
end
|
||||
@@ -220,7 +223,7 @@ function agents-init --description 'scaffold AGENTS/ sub-repo with agent spec fi
|
||||
test $verbose -eq 1; and echo "$c_ok→ Moved AGENTS.md → AGENTS/AGENTS.md$c_reset"
|
||||
end
|
||||
if not test -f "$agents_dir/CLAUDE.md"; and not test -L "$agents_dir/CLAUDE.md"
|
||||
if not mv "$root/CLAUDE.md" "$agents_dir/CLAUDE.md"
|
||||
if not command mv "$root/CLAUDE.md" "$agents_dir/CLAUDE.md"
|
||||
echo "$c_err""Error: could not move CLAUDE.md → AGENTS/CLAUDE.md$c_reset" >&2
|
||||
return 1
|
||||
end
|
||||
@@ -229,7 +232,7 @@ function agents-init --description 'scaffold AGENTS/ sub-repo with agent spec fi
|
||||
end
|
||||
else if test $has_agents -eq 1
|
||||
if not test -f "$agents_dir/AGENTS.md"
|
||||
if not mv "$root/AGENTS.md" "$agents_dir/AGENTS.md"
|
||||
if not command mv "$root/AGENTS.md" "$agents_dir/AGENTS.md"
|
||||
echo "$c_err""Error: could not move AGENTS.md → AGENTS/AGENTS.md$c_reset" >&2
|
||||
return 1
|
||||
end
|
||||
@@ -239,7 +242,7 @@ function agents-init --description 'scaffold AGENTS/ sub-repo with agent spec fi
|
||||
else if test $has_claude -eq 1
|
||||
# Only CLAUDE.md: treat it as the agent spec
|
||||
if not test -f "$agents_dir/AGENTS.md"
|
||||
if not mv "$root/CLAUDE.md" "$agents_dir/AGENTS.md"
|
||||
if not command mv "$root/CLAUDE.md" "$agents_dir/AGENTS.md"
|
||||
echo "$c_err""Error: could not move CLAUDE.md → AGENTS/AGENTS.md$c_reset" >&2
|
||||
return 1
|
||||
end
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
# _agents_repo_ensure_symlink, _agents_repo_sync,
|
||||
# _agents_repo_install_tools, git, hostname
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# self-limiting(rm,mkdir)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# agents-vault [--link] [--push] [--restore] [--status]
|
||||
# [--adopt=SLUG] [--remote=URL]
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 12-ai-and-developer-tools
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# self-limiting(grep)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# antigravity-ide [args...]
|
||||
#
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# COMPONENT
|
||||
# aliases/shell-tools
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(bash)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# bash [args...]
|
||||
#
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# COMPONENT
|
||||
# aliases/filesystem
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# uses-shadow(ls), bypasses-shadow(cat)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# cat [args...]
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 14-miscellaneous
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# uses-shadow(ls)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# cffetch [args...]
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 12-ai-and-developer-tools
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# uses-shadow(claude)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# claude-docs
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 12-ai-and-developer-tools
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# uses-shadow(claude)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# claude-pr
|
||||
#
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
# DEPENDENCIES
|
||||
# agents-init, agents-vault
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(claude)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# claude [ARGS...]
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 05-package-management
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# self-limiting(grep)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# cleanup
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 14-miscellaneous
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# self-limiting(grep), bypasses-shadow(less)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# config-help [section]
|
||||
# config-help --html
|
||||
@@ -347,7 +350,7 @@ function config-help --description 'Open the offline fish shell configuration ma
|
||||
|
||||
else if type -q less
|
||||
string replace -ra $span_raw $span_bold <"$doc_file" \
|
||||
| less -R +"$start_line"
|
||||
| command less -R +"$start_line"
|
||||
|
||||
else
|
||||
string replace -ra $span_raw $span_bold <"$doc_file"
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
# __fish_palette, __config_settings_state, __config_settings_apply,
|
||||
# __config_settings_set_value, python3
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(rm)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# config-settings [-h | --help]
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 01-file-and-directory
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(cp)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# copy <source> <dest>
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 13-media-and-utilities
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# self-limiting(rm)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# dng2avif [-h] [-i <file>] [-o <file>] [-q <n>] [-s <n>] [input.dng]
|
||||
#
|
||||
@@ -119,7 +122,7 @@ function dng2avif --description 'Convert DNG raw to 10-bit HDR AVIF'
|
||||
end
|
||||
|
||||
# Final Cleanup
|
||||
test -f "$temp_pnm"; and rm "$temp_pnm"
|
||||
test -f "$temp_pnm"; and rm -f "$temp_pnm"
|
||||
|
||||
set -l size (stat -c '%s' "$output" | numfmt --to=iec)
|
||||
echo (set_color yellow)"Complete: $output ($size)"(set_color normal)
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 14-miscellaneous
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# network
|
||||
#
|
||||
# SYNOPSIS
|
||||
# dockup [-h] [directory]
|
||||
#
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# COMPONENT
|
||||
# aliases/filesystem
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(du)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# du [--disk|--dir|--dua] [args...]
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 01-file-and-directory
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# uses-shadow(du)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# dusize [dir]
|
||||
#
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# COMPONENT
|
||||
# aliases/dev-tools
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(rm)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# edit [-V|-t] [-e EDITOR] [-c] [-x TEXT] [-n] [-v|-s] [FILE...]
|
||||
#
|
||||
|
||||
+6
-3
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 03-editors-and-viewers
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(rm), self-limiting(cat)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# fc [command_prefix]
|
||||
#
|
||||
@@ -50,15 +53,15 @@ function fc --description 'Edit and execute the last command (Bash-style fc)'
|
||||
# Final check if user cleared the file in the editor
|
||||
if test -s $tmpfile
|
||||
set -l command (cat $tmpfile)
|
||||
rm $tmpfile
|
||||
command rm -f $tmpfile
|
||||
commandline -r "$command"
|
||||
commandline -f execute
|
||||
else
|
||||
rm $tmpfile
|
||||
command rm -f $tmpfile
|
||||
echo "fc: Aborted (empty file)"
|
||||
end
|
||||
else
|
||||
rm $tmpfile
|
||||
command rm -f $tmpfile
|
||||
echo "fc: Could not retrieve history"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 14-miscellaneous
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# uses-shadow(ls)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# ffetch [args...]
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 06-dependency-management
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# network
|
||||
#
|
||||
# SYNOPSIS
|
||||
# fzf-update
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 04-git-and-version-control
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# self-limiting(grep,cat), network, blocking-prompt
|
||||
#
|
||||
# SYNOPSIS
|
||||
# gi [-h] [-b] [-p] [-s] [-l] [targets...]
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 10-network
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# network
|
||||
#
|
||||
# SYNOPSIS
|
||||
# gip
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 10-network
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# network
|
||||
#
|
||||
# SYNOPSIS
|
||||
# gip4
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 10-network
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# network
|
||||
#
|
||||
# SYNOPSIS
|
||||
# gip6
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 04-git-and-version-control
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# network
|
||||
#
|
||||
# SYNOPSIS
|
||||
# git-clean [-h] [-f]
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 04-git-and-version-control
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# network
|
||||
#
|
||||
# SYNOPSIS
|
||||
# gitup [args...]
|
||||
#
|
||||
|
||||
+1
-1
@@ -34,7 +34,7 @@ function hist --description 'Search fish history and put it in the prompt'
|
||||
return 1
|
||||
end
|
||||
|
||||
set -l selected (history | fzf --reverse --height 40% --with-nth 3..)
|
||||
set -l selected (builtin history --show-time='%F %T ' | fzf --reverse --height 40% --with-nth 3..)
|
||||
|
||||
if test -n "$selected"
|
||||
# Strip the timestamp for the final output
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# DEPENDENCIES
|
||||
# tmux, screen, __jobrunner_sessions
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(cat,rm)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# jobrunner [-t <tool>] [<subcommand>] [<name>] [<command>...]
|
||||
# jr [-t <tool>] [<subcommand>] [<name>] [<command>...]
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# DEPENDENCIES
|
||||
# gpg, tar
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(rm), destructive
|
||||
#
|
||||
# SYNOPSIS
|
||||
# key-crypt [options] <input> [output]
|
||||
# key-crypt -i <input> -o <output> [options]
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# COMPONENT
|
||||
# logging/terminal-capture
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(grep,mkdir,rm)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# kitty-logging [install | uninstall | status | dismiss] [-h]
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 01-file-and-directory
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(ls)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# lD [args...]
|
||||
#
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# COMPONENT
|
||||
# aliases/shell-tools
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(cat,less)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# less [args...]
|
||||
#
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# COMPONENT
|
||||
# integrations/history-logs
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(cat), self-limiting(rm), network
|
||||
#
|
||||
# SYNOPSIS
|
||||
# logs [-h] [-c <category>]
|
||||
#
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# COMPONENT
|
||||
# aliases/filesystem
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(ls)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# ls [args...]
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 01-file-and-directory
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(ls)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# lsr [args...]
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 01-file-and-directory
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(ls)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# lss [args...]
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 01-file-and-directory
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(ls)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# lstree [args...]
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 01-file-and-directory
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(ls)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# lt [args...]
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 01-file-and-directory
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(ls)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# ltr [args...]
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 01-file-and-directory
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(ls)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# lx [args...]
|
||||
#
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# DEPENDENCIES
|
||||
# marktext, firejail, bkg
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# uses-shadow(mkdir)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# md [-r] [--foreground] [marktext-args...] [FILE...]
|
||||
#
|
||||
|
||||
+4
-1
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 01-file-and-directory
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(cd)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# mkcd [-s | --silent] <dir>
|
||||
#
|
||||
@@ -65,7 +68,7 @@ function mkcd --description 'Create a directory (with parents) and cd into it'
|
||||
_fish_mkdir_p --tree $dir; or return $status
|
||||
end
|
||||
|
||||
cd $dir
|
||||
builtin cd $dir
|
||||
or return $status
|
||||
|
||||
if test $is_new -eq 1
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# COMPONENT
|
||||
# aliases/filesystem
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(mkdir)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# mkdir [args...]
|
||||
#
|
||||
|
||||
+12
-9
@@ -9,6 +9,9 @@
|
||||
# _mkrep_add_origin, _mkrep_default_remote_cmd, _mkrep_remote_url,
|
||||
# _mkrep_repo_exists, git
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(cd), self-limiting(rm), destructive, network
|
||||
#
|
||||
# SYNOPSIS
|
||||
# mkrep [--cd | --no-cd] [--mkdir | --no-mkdir] [--git | --no-git]
|
||||
# [-c | --clean | --no-clean] [--strict] [-v | --verbose]
|
||||
@@ -304,7 +307,7 @@ function mkrep --description 'Create a directory, cd into it, and git init it'
|
||||
_mkrep_say $silent "$c_warn""→$c_reset $c_arg$dir$c_reset already exists"
|
||||
end
|
||||
|
||||
cd $dir
|
||||
builtin cd $dir
|
||||
or begin
|
||||
echo "$c_err""✘$c_reset Failed to enter $c_arg$dir$c_reset" >&2
|
||||
return 1
|
||||
@@ -326,7 +329,7 @@ function mkrep --description 'Create a directory, cd into it, and git init it'
|
||||
end
|
||||
or begin
|
||||
echo "$c_err""✘$c_reset git init failed in $c_arg$dir$c_reset" >&2
|
||||
cd $orig_pwd
|
||||
builtin cd $orig_pwd
|
||||
return 1
|
||||
end
|
||||
|
||||
@@ -341,7 +344,7 @@ function mkrep --description 'Create a directory, cd into it, and git init it'
|
||||
_mkrep_verbose $silent $verbose "$c_dim""Running: git remote add origin $_flag_remote$c_reset"
|
||||
_mkrep_add_origin $silent $_flag_remote
|
||||
or begin
|
||||
cd $orig_pwd
|
||||
builtin cd $orig_pwd
|
||||
return 1
|
||||
end
|
||||
end
|
||||
@@ -351,7 +354,7 @@ function mkrep --description 'Create a directory, cd into it, and git init it'
|
||||
test -z "$cmd"; and set cmd $MKREP_REMOTE_CMD
|
||||
if test -z "$cmd"
|
||||
echo "$c_err""✘$c_reset --new-remote given no command and \$MKREP_REMOTE_CMD is unset" >&2
|
||||
cd $orig_pwd
|
||||
builtin cd $orig_pwd
|
||||
return 1
|
||||
end
|
||||
|
||||
@@ -368,7 +371,7 @@ function mkrep --description 'Create a directory, cd into it, and git init it'
|
||||
end
|
||||
or begin
|
||||
echo "$c_err""✘$c_reset Remote-create command failed" >&2
|
||||
cd $orig_pwd
|
||||
builtin cd $orig_pwd
|
||||
return 1
|
||||
end
|
||||
_mkrep_say $silent "$c_ok""✔$c_reset Ran remote-create command"
|
||||
@@ -390,7 +393,7 @@ function mkrep --description 'Create a directory, cd into it, and git init it'
|
||||
_mkrep_say $silent "$c_warn""→$c_reset $c_arg$USER/$name$c_reset already exists on $srv_type; linking instead of creating"
|
||||
_mkrep_add_origin $silent $url
|
||||
or begin
|
||||
cd $orig_pwd
|
||||
builtin cd $orig_pwd
|
||||
return 1
|
||||
end
|
||||
else
|
||||
@@ -421,7 +424,7 @@ function mkrep --description 'Create a directory, cd into it, and git init it'
|
||||
if string match -q '*{server}*' -- $cmd
|
||||
if test -z "$srv_url"
|
||||
echo "$c_err""✘$c_reset No base URL resolved for $srv_type (set \$GITEA_URL/\$GITEA_HOST or \$GITLAB_URL/\$GITLAB_HOST)" >&2
|
||||
cd $orig_pwd
|
||||
builtin cd $orig_pwd
|
||||
return 1
|
||||
end
|
||||
set cmd (string replace -a '{server}' $srv_url -- $cmd)
|
||||
@@ -437,7 +440,7 @@ function mkrep --description 'Create a directory, cd into it, and git init it'
|
||||
end
|
||||
or begin
|
||||
echo "$c_err""✘$c_reset Remote-create command failed" >&2
|
||||
cd $orig_pwd
|
||||
builtin cd $orig_pwd
|
||||
return 1
|
||||
end
|
||||
set -l url (_mkrep_remote_url $srv_type $USER $name $srv_url)
|
||||
@@ -448,7 +451,7 @@ function mkrep --description 'Create a directory, cd into it, and git init it'
|
||||
end
|
||||
|
||||
if test $do_cd -eq 0
|
||||
cd $orig_pwd
|
||||
builtin cd $orig_pwd
|
||||
else
|
||||
_mkrep_say $silent "$c_ok""✔$c_reset Entered $c_arg$dir$c_reset"
|
||||
end
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# COMPONENT
|
||||
# aliases/filesystem
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(mv)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# mv [args...]
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 05-package-management
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# network
|
||||
#
|
||||
# SYNOPSIS
|
||||
# parur
|
||||
#
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# COMPONENT
|
||||
# aliases/network
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(ping)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# ping [args...]
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 05-package-management
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# network
|
||||
#
|
||||
# SYNOPSIS
|
||||
# pkg [-h] [-i|-u] <package> [package...]
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 10-network
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# self-limiting(cat), network
|
||||
#
|
||||
# SYNOPSIS
|
||||
# qr [text...]
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 14-miscellaneous
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(cat)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# rand_string [COMPONENTS/MODIFIERS]...
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 14-miscellaneous
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(bash,cd)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# replay <commands>
|
||||
#
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# COMPONENT
|
||||
# aliases/search
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(rg)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# rg [args...]
|
||||
#
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# COMPONENT
|
||||
# aliases/filesystem
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(rm), destructive
|
||||
#
|
||||
# SYNOPSIS
|
||||
# rm [-e [options] | -S | args...]
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 07-system-and-monitoring
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# self-limiting(grep)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# sbver [--brief]
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 01-file-and-directory
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# uses-shadow(rm), bypasses-shadow(rm), destructive
|
||||
#
|
||||
# SYNOPSIS
|
||||
# scrub [-a] [-d] [-h]
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 05-package-management
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# network
|
||||
#
|
||||
# SYNOPSIS
|
||||
# search [args...]
|
||||
#
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
# site exit-plain: overrides/key-bindings
|
||||
# site logging-guard: logging/terminal-capture
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# self-limiting(rm,mkdir), destructive
|
||||
#
|
||||
# SYNOPSIS
|
||||
# smart_exit [-h] [-n]
|
||||
#
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# COMPONENT
|
||||
# aliases/network
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(ssh), network
|
||||
#
|
||||
# SYNOPSIS
|
||||
# ssh [args...]
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 12-ai-and-developer-tools
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# uses-shadow(claude)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# superpowers [on|off] [-g]
|
||||
#
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# COMPONENT
|
||||
# aliases/monitor
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# bypasses-shadow(top)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# top [args...]
|
||||
#
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# COMPONENT
|
||||
# integrations/pkg-upgrade
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# network
|
||||
#
|
||||
# SYNOPSIS
|
||||
# upgrade
|
||||
#
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
# CATEGORY
|
||||
# 03-editors-and-viewers
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# uses-shadow(less)
|
||||
#
|
||||
# SYNOPSIS
|
||||
# view [args...]
|
||||
#
|
||||
|
||||
@@ -7,6 +7,9 @@
|
||||
# COMPONENT
|
||||
# aliases/network
|
||||
#
|
||||
# CLASSIFICATION
|
||||
# network
|
||||
#
|
||||
# SYNOPSIS
|
||||
# yt-dlp [args...] URL [URL...]
|
||||
#
|
||||
|
||||
@@ -53,6 +53,89 @@ if test $syntax_failed -ne 0 -o $indent_failed -ne 0
|
||||
set overall_failed 1
|
||||
end
|
||||
|
||||
# ---- Phase 1b: shadow-classification lint --------------------------------
|
||||
# Catches a bare C1-shadowed-command call in a function body with no
|
||||
# matching uses-shadow(name) or self-limiting(name) in that function's own
|
||||
# CLASSIFICATION header -- the exact bug class fixed across fc.fish,
|
||||
# dng2avif.fish, _scrollback_prune_junk.fish, mkcd.fish, and mkrep.fish. A
|
||||
# bare call is either declared (uses-shadow: wanted; self-limiting: safe
|
||||
# because the shadow's own logic neutralizes it, e.g. rm/mkdir's flag check
|
||||
# or grep/cat's tty-auto-detected color) or it's undocumented at best, a bug
|
||||
# at worst -- the lint never guesses which on its own; see
|
||||
# docs/function-classification-schema.md for the full tag definitions and
|
||||
# why the reasoning belongs in a tag, not in this script.
|
||||
#
|
||||
# Scoped to functions/*.fish only: the one-function-per-file convention
|
||||
# there makes "everything after the function line is its body" exact, with
|
||||
# no block-depth parser needed. conf.d/*.fish can define several functions
|
||||
# in one file and isn't covered -- see docs/function-classification-schema.md.
|
||||
echo
|
||||
echo "== Shadow-classification lint =="
|
||||
|
||||
# help and edit are deliberately excluded: help's real bypass is
|
||||
# __original_help (not command/builtin), and edit has no backing binary at
|
||||
# all to bypass to -- see docs/manual/08-components-reference/01-c1-command-shadows.md.
|
||||
set -l shadow_names ls cat cd rm less du top ping ssh rg mkdir bash cp mv wget grep fgrep egrep dir vdir claude
|
||||
|
||||
set -l class_checked 0
|
||||
set -l class_files_failed 0
|
||||
set -l class_issues 0
|
||||
|
||||
for f in $repo_root/functions/*.fish
|
||||
set -l lines (cat $f)
|
||||
|
||||
# Find the function line; everything before it is header, everything
|
||||
# from it onward is body (one function per file).
|
||||
set -l func_idx 0
|
||||
for i in (seq (count $lines))
|
||||
if string match -qr '^function ' -- $lines[$i]
|
||||
set func_idx $i
|
||||
break
|
||||
end
|
||||
end
|
||||
test $func_idx -eq 0; and continue
|
||||
set class_checked (math $class_checked + 1)
|
||||
|
||||
# Pull uses-shadow(...) and self-limiting(...) names from the
|
||||
# CLASSIFICATION tag line, if any -- either one accounts for a bare call.
|
||||
set -l declared
|
||||
for i in (seq (math $func_idx - 1))
|
||||
if test "$lines[$i]" = "# CLASSIFICATION"; and test $i -lt $func_idx
|
||||
set -l tagline $lines[(math $i + 1)]
|
||||
for tag in uses-shadow self-limiting
|
||||
set -l m (string match -r "$tag"'\(([^)]*)\)' -- $tagline)
|
||||
test -n "$m[2]"; and set -a declared (string trim -- (string split ',' -- $m[2]))
|
||||
end
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
set -l file_failed 0
|
||||
for i in (seq $func_idx (count $lines))
|
||||
set -l line $lines[$i]
|
||||
# Strip quoted spans and comments so string literals (error
|
||||
# messages, --description text) never masquerade as a call.
|
||||
set -l stripped (string replace -ra '"[^"]*"' '' -- $line)
|
||||
set stripped (string replace -ra "'[^']*'" '' -- $stripped)
|
||||
set stripped (string replace -r '#.*$' '' -- $stripped)
|
||||
|
||||
for name in $shadow_names
|
||||
if string match -qr '(^|[;|(]|\band\b|\bor\b|\bnot\b|\bif\b|\bwhile\b|\bbegin\b)\s*'"$name"'(\s|$)' -- $stripped
|
||||
if not contains -- $name $declared
|
||||
echo " FAIL (shadow) "(string replace $repo_root/ '' $f)": line $i calls bare '$name' with no uses-shadow($name)/self-limiting($name)"
|
||||
set class_issues (math $class_issues + 1)
|
||||
set file_failed 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
test $file_failed -eq 1; and set class_files_failed (math $class_files_failed + 1)
|
||||
end
|
||||
echo (math $class_checked - $class_files_failed)"/$class_checked functions passed shadow-classification check"
|
||||
if test $class_issues -ne 0
|
||||
set overall_failed 1
|
||||
end
|
||||
|
||||
# ---- Phase 2: discover suites --------------------------------------------
|
||||
# Mode is declared by the suite, not by this driver. Detection is
|
||||
# case-insensitive so a near-miss like "# Mode: in-session" is caught rather
|
||||
|
||||
Reference in New Issue
Block a user