Merge pull request 'feat(logging): add C5 — Logging & Capture opinionated guard' (#39) from feat/logging-toggle-c5 into main
Generate documentation / build-docs (push) Successful in 32s
Offline docs drift reminder / remind (push) Successful in 10s

Reviewed-on: #39
This commit was merged in pull request #39.
This commit is contained in:
2026-06-11 02:05:06 +00:00
8 changed files with 173 additions and 8 deletions
+5
View File
@@ -62,6 +62,11 @@
opinionated_catalog.md
docs/superpowers
# ──────────────────── Runtime State Files ───────────────────
# Sentinel file written/removed at runtime to coordinate logging state
# across the fish config and the Kitty Python watcher. Never committed.
.logging_disabled
# ──────────────── Fisher-Managed Plugin Files ───────────────
# Fisher writes these into the repo directory on install/update.
# They are owned by Fisher — do not commit them.
+3 -2
View File
@@ -166,7 +166,7 @@ end
## Minimal Mode
Everything opinionated in this config — command shadows, startup side-effects, key and environment overrides, and terminal integrations — is active by default but can be switched off with universal variables. Four category toggles and one master switch are available:
Everything opinionated in this config — command shadows, startup side-effects, key and environment overrides, terminal integrations, and logging — is active by default but can be switched off with universal variables. Five category toggles and one master switch are available:
| Variable | Disables |
|---|---|
@@ -174,7 +174,8 @@ Everything opinionated in this config — command shadows, startup side-effects,
| `__fish_config_op_autoexec` | Startup side-effects: Fisher bootstrap, theme apply, `paru`/`yay` wrapper generation, auto venv activation, WakaTime hook |
| `__fish_config_op_overrides` | Vi mode, `exit``smart_exit`, `$PAGER`/`$MANPAGER`/`$CDPATH`, bang-bang history expansion, autopair, puffer, Starship prompt, theme colors |
| `__fish_config_op_integrations` | Kitty/WezTerm window abbreviations, `done` notifications, `spwin`/`tab`/`split`, `hist`, `logs`, `upgrade`, WakaTime |
| `__fish_config_opinionated` | Master switch — all four categories at once |
| `__fish_config_op_logging` | Scrollback capture on exit, `paru`/`yay` AUR log wrappers, Kitty watcher capture (sentinel-file coordinated) |
| `__fish_config_opinionated` | Master switch — all five categories at once |
Set any of them to a falsy value (`0`, `false`, `no`, `off`, `n`) to disable; erase the variable to re-enable:
+27
View File
@@ -0,0 +1,27 @@
# Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
#
# C5 — Logging & Capture: registers --on-variable event handlers at shell
# startup so that changes to __fish_config_op_logging or the master
# __fish_config_opinionated take effect immediately in every running shell.
# Also calls __fish_config_sync_logging once to reconcile sentinel-file and
# wrapper state with any variable values that were pre-set before this shell
# started.
#
# These functions must be defined in conf.d (not functions/) because fish
# only autoloads from functions/ on explicit call — event handlers that live
# solely in functions/ are never registered and their --on-variable triggers
# never fire.
function __fish_config_logging_changed --on-variable __fish_config_op_logging \
--description 'C5 event handler: sync logging state when __fish_config_op_logging changes'
__fish_config_sync_logging
end
function __fish_config_opinionated_changed --on-variable __fish_config_opinionated \
--description 'C5 event handler: sync logging state when master opinionated switch changes'
__fish_config_sync_logging
end
# Sync once at startup so pre-set variable values take effect without a re-set
__fish_config_sync_logging
+10 -1
View File
@@ -6,9 +6,18 @@
# timestamped log file and prunes old logs, mirroring smart_exit behavior.
# Auto-generating a wrapper in ~/.local/bin is opinionated (C2 auto-exec).
# Task #4's __fish_config_enable_logging will additionally gate this wrapper.
# Wrapper generation is also gated by C5 (Logging & Capture).
__fish_config_op_enabled __fish_config_op_autoexec; or return
# C5 — Logging & Capture: remove generated wrapper and skip when logging is off
if not __fish_config_op_enabled __fish_config_op_logging
if test -f "$HOME/.local/bin/paru"
and grep -q "# paru-wrapper-version:" "$HOME/.local/bin/paru" 2>/dev/null
rm -f "$HOME/.local/bin/paru"
end
return
end
set -l _paru_real /usr/bin/paru
set -l _paru_wrapper "$HOME/.local/bin/paru"
set -l _paru_wrapper_version 1
+10 -1
View File
@@ -6,9 +6,18 @@
# timestamped log file and prunes old logs, mirroring smart_exit behavior.
# Auto-generating a wrapper in ~/.local/bin is opinionated (C2 auto-exec).
# Task #4's __fish_config_enable_logging will additionally gate this wrapper.
# Wrapper generation is also gated by C5 (Logging & Capture).
__fish_config_op_enabled __fish_config_op_autoexec; or return
# C5 — Logging & Capture: remove generated wrapper and skip when logging is off
if not __fish_config_op_enabled __fish_config_op_logging
if test -f "$HOME/.local/bin/yay"
and grep -q "# yay-wrapper-version:" "$HOME/.local/bin/yay" 2>/dev/null
rm -f "$HOME/.local/bin/yay"
end
return
end
set -l _yay_real /usr/bin/yay
set -l _yay_wrapper "$HOME/.local/bin/yay"
set -l _yay_wrapper_version 1
+7 -2
View File
@@ -1382,7 +1382,7 @@ fish_variables.
## Opinionated Components (Minimal Mode)
Every opinionated piece of this config is active by default but can be
switched off through four category opt-out variables, each evaluated via
switched off through five category opt-out variables, each evaluated via
__fish_variable_check. Set a variable to any falsy value (0, false, no,
off, n) to disable its category; erase it or set a truthy value (1, true,
yes, on, y) to re-enable. Unset means enabled.
@@ -1410,13 +1410,18 @@ yes, on, y) to re-enable. Unset means enabled.
WezTerm window abbreviations, done
notifications, spwin/tab/split,
hist, logs, upgrade, WakaTime
__fish_config_op_logging Logging & capture: scrollback
capture on exit, paru/yay AUR log
wrappers, Kitty watcher capture;
sentinel file coordinates
cross-process state
Examples:
# Disable command shadows only (rm becomes plain rm again):
set -U __fish_config_op_aliases off
# Full minimal mode — disable all four categories at once:
# Full minimal mode — disable all five categories at once:
set -U __fish_config_opinionated 0
# Re-enable everything:
+99
View File
@@ -0,0 +1,99 @@
# Copyright (C) 2026 Rootiest
# SPDX-License-Identifier: AGPL-3.0-or-later
# SYNOPSIS
# __fish_config_sync_logging
#
# DESCRIPTION
# Synchronises C5 logging state: creates or removes the Kitty sentinel
# file ($XDG_CONFIG_HOME/fish/.logging_disabled) and generates or removes
# the paru/yay AUR-helper log wrappers based on the combined value of
# __fish_config_opinionated (master) and __fish_config_op_logging (C5).
# Called by --on-variable event handlers whenever either variable changes.
# Safe to call at any time; wrapper removal only affects files bearing
# the generated version-marker comment.
#
# RETURNS
# 0 Always
#
# EXAMPLE
# __fish_config_sync_logging
function __fish_config_sync_logging --description 'Sync C5 logging state: sentinel file and paru/yay wrappers'
set -l config_home $XDG_CONFIG_HOME
if test -z "$config_home"
set config_home "$HOME/.config"
end
set -l sentinel "$config_home/fish/.logging_disabled"
set -l paru_wrapper "$HOME/.local/bin/paru"
set -l yay_wrapper "$HOME/.local/bin/yay"
set -l wrapper_version 1
if __fish_config_op_enabled __fish_config_op_logging
# Logging enabled: remove sentinel and regenerate wrappers if binaries exist
rm -f $sentinel
if test -x /usr/bin/paru
mkdir -p (dirname $paru_wrapper)
printf '%s\n' \
'#!/usr/bin/env bash' \
"# paru-wrapper-version: $wrapper_version" \
'# Auto-generated by conf.d/paru-wrapper.fish — do not edit by hand.' \
'# Tees paru output to a timestamped log file and prunes old ones.' \
'set -o pipefail' \
'' \
'log_dir="${SCROLLBACK_HISTORY_DIR:-$HOME/.terminal_history}"' \
'mkdir -p "$log_dir"' \
'log_file="$log_dir/paru_$(date +%Y-%m-%d_%H-%M-%S).log"' \
'' \
'/usr/bin/paru "$@" 2>&1 | tee "$log_file"' \
'' \
'max_files="${SCROLLBACK_HISTORY_MAX_FILES:-100}"' \
'mapfile -t logs < <(ls -1t "$log_dir"/paru_*.log 2>/dev/null)' \
'excess=$(( ${#logs[@]} - max_files ))' \
'for (( i = ${#logs[@]} - 1; i >= ${#logs[@]} - excess && i >= 0; i-- )); do' \
' rm -f "${logs[$i]}"' \
'done' \
>$paru_wrapper
chmod +x $paru_wrapper
end
if test -x /usr/bin/yay
mkdir -p (dirname $yay_wrapper)
printf '%s\n' \
'#!/usr/bin/env bash' \
"# yay-wrapper-version: $wrapper_version" \
'# Auto-generated by conf.d/yay-wrapper.fish — do not edit by hand.' \
'# Tees yay output to a timestamped log file and prunes old ones.' \
'set -o pipefail' \
'' \
'log_dir="${SCROLLBACK_HISTORY_DIR:-$HOME/.terminal_history}"' \
'mkdir -p "$log_dir"' \
'log_file="$log_dir/yay_$(date +%Y-%m-%d_%H-%M-%S).log"' \
'' \
'/usr/bin/yay "$@" 2>&1 | tee "$log_file"' \
'' \
'max_files="${SCROLLBACK_HISTORY_MAX_FILES:-100}"' \
'mapfile -t logs < <(ls -1t "$log_dir"/yay_*.log 2>/dev/null)' \
'excess=$(( ${#logs[@]} - max_files ))' \
'for (( i = ${#logs[@]} - 1; i >= ${#logs[@]} - excess && i >= 0; i-- )); do' \
' rm -f "${logs[$i]}"' \
'done' \
>$yay_wrapper
chmod +x $yay_wrapper
end
else
# Logging disabled: create sentinel and remove any generated wrappers
mkdir -p (dirname $sentinel)
touch $sentinel
if test -f $paru_wrapper
and grep -q "# paru-wrapper-version:" $paru_wrapper 2>/dev/null
rm -f $paru_wrapper
end
if test -f $yay_wrapper
and grep -q "# yay-wrapper-version:" $yay_wrapper 2>/dev/null
rm -f $yay_wrapper
end
end
end
+12 -2
View File
@@ -48,6 +48,16 @@ function smart_exit --description 'Capture colorized scrollback before exiting,
return 0
end
# C5 — Logging & Capture: skip all capture when logging is disabled.
# When disabled, tell Kitty the window is handled so its watcher doesn't
# capture either — belt-and-suspenders alongside the sentinel file.
if not __fish_config_op_enabled __fish_config_op_logging
if test -n "$KITTY_WINDOW_ID"
kitty @ set-user-vars "logged_by_shell=true" 2>/dev/null
end
builtin exit
end
set -l snapshot_dir (set -q SCROLLBACK_HISTORY_DIR; and echo $SCROLLBACK_HISTORY_DIR; or echo "$HOME/.terminal_history")
set -l max_files (set -q SCROLLBACK_HISTORY_MAX_FILES; and echo $SCROLLBACK_HISTORY_MAX_FILES; or echo 100)
@@ -61,8 +71,8 @@ function smart_exit --description 'Capture colorized scrollback before exiting,
set -l active_tui (ps -o comm= --ppid $fish_pid 2>/dev/null)
if test -n "$KITTY_WINDOW_ID"
# LIVE BUFFER CHECK: Check the active token variable $_
# If the user typed exit, $_ will match "exit". If flags were passed,
# LIVE BUFFER CHECK: Check the active token variable $_
# If the user typed exit, $_ will match "exit". If flags were passed,
# we check if it contains the phrase "exit" to match 'exit -n' or 'exit --help'.
if string match -qr exit "$_"
if not string match -qr '^(nvim|vim|vi|nano|emacs|tmux)$' "$active_tui"