feat(logging): add C5 — Logging & Capture opinionated guard #39

Merged
rootiest merged 10 commits from feat/logging-toggle-c5 into main 2026-06-11 02:05:07 +00:00
8 changed files with 173 additions and 8 deletions
+5
View File
@@ -62,6 +62,11 @@
opinionated_catalog.md opinionated_catalog.md
docs/superpowers 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-Managed Plugin Files ───────────────
# Fisher writes these into the repo directory on install/update. # Fisher writes these into the repo directory on install/update.
# They are owned by Fisher — do not commit them. # They are owned by Fisher — do not commit them.
+3 -2
View File
@@ -166,7 +166,7 @@ end
## Minimal Mode ## 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 | | 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_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_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_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: 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. # timestamped log file and prunes old logs, mirroring smart_exit behavior.
# Auto-generating a wrapper in ~/.local/bin is opinionated (C2 auto-exec). # 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 __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_real /usr/bin/paru
set -l _paru_wrapper "$HOME/.local/bin/paru" set -l _paru_wrapper "$HOME/.local/bin/paru"
set -l _paru_wrapper_version 1 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. # timestamped log file and prunes old logs, mirroring smart_exit behavior.
# Auto-generating a wrapper in ~/.local/bin is opinionated (C2 auto-exec). # 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 __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_real /usr/bin/yay
set -l _yay_wrapper "$HOME/.local/bin/yay" set -l _yay_wrapper "$HOME/.local/bin/yay"
set -l _yay_wrapper_version 1 set -l _yay_wrapper_version 1
+7 -2
View File
@@ -1382,7 +1382,7 @@ fish_variables.
## Opinionated Components (Minimal Mode) ## Opinionated Components (Minimal Mode)
Every opinionated piece of this config is active by default but can be 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, __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, off, n) to disable its category; erase it or set a truthy value (1, true,
yes, on, y) to re-enable. Unset means enabled. 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 WezTerm window abbreviations, done
notifications, spwin/tab/split, notifications, spwin/tab/split,
hist, logs, upgrade, WakaTime 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: Examples:
# Disable command shadows only (rm becomes plain rm again): # Disable command shadows only (rm becomes plain rm again):
set -U __fish_config_op_aliases off 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 set -U __fish_config_opinionated 0
# Re-enable everything: # 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 return 0
end 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 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) 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) set -l active_tui (ps -o comm= --ppid $fish_pid 2>/dev/null)
if test -n "$KITTY_WINDOW_ID" if test -n "$KITTY_WINDOW_ID"
# LIVE BUFFER CHECK: Check the active token variable $_ # LIVE BUFFER CHECK: Check the active token variable $_
# If the user typed exit, $_ will match "exit". If flags were passed, # 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'. # we check if it contains the phrase "exit" to match 'exit -n' or 'exit --help'.
if string match -qr exit "$_" if string match -qr exit "$_"
if not string match -qr '^(nvim|vim|vi|nano|emacs|tmux)$' "$active_tui" if not string match -qr '^(nvim|vim|vi|nano|emacs|tmux)$' "$active_tui"