personal configs and automations
  • Python 82.2%
  • Shell 16.7%
  • JavaScript 1.1%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
mysticalsoap 84185ef72f
Switch shell configs from zsh to bash
Login shell moves to bash for parity with Claude Code's Bash tool —
one dialect everywhere, no zsh-only quirks (read-only $status,
nomatch globs). Ported the SSH agent env and signing-key autoload;
p10k and the cachyos zsh config were cosmetic and are dropped.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-18 15:54:38 -04:00
_helper/docs Rename docs Home.md to README.md, link root README to it 2026-08-01 18:13:05 -04:00
bash Switch shell configs from zsh to bash 2026-08-18 15:54:38 -04:00
bin Switch shell configs from zsh to bash 2026-08-18 15:54:38 -04:00
config added new aqomui repo to workspace 2026-08-17 12:56:05 -04:00
easyeffects/db updated some setup stuff from reinstall experience 2026-04-12 23:31:57 -04:00
fish switch login shell to zsh, track its config 2026-08-17 14:08:51 -04:00
git switch login shell to zsh, track its config 2026-08-17 14:08:51 -04:00
kde backup-configs: updated kde/kwinrc, kde/konsolerc, kde/konsole-keytabs, kde/kxmlgui5-konsole, git/gitconfig, fish/config.fish, packages/pacman.txt, packages/aur.txt, README.md, bin/backup-configs (2026-08-04 02:15) 2026-08-04 02:15:50 -04:00
packages switch login shell to zsh, track its config 2026-08-17 14:08:51 -04:00
system renamed games to support for new backup process 2026-07-23 19:39:22 -04:00
systemd switch login shell to zsh, track its config 2026-08-17 14:08:51 -04:00
.gitignore Remove letterboxd-poster-sync and soapflix-featured-sync, moved to docker repo 2026-08-11 17:17:09 -04:00
README.md switch login shell to zsh, track its config 2026-08-17 14:08:51 -04:00

dotfiles

Personal configuration files for CachyOS + KDE Plasma.

Playbooks and reference notes live in _helper/docs/

Layout

Path Contents Kept current by
kde/ kdeglobals, kwinrc, kwinrulesrc, kwinoutputconfig.json, plasmarc, plasmashellrc, konsolerc backup-configs
kde/konsole-keytabs/ Konsole custom keyboard schemes + modified profiles (from ~/.local/share/konsole/) backup-configs
kde/kxmlgui5-konsole/ Konsole shortcut overrides, e.g. Copy/Paste rebinds (from ~/.local/share/kxmlgui5/konsole/) backup-configs
kde/kwin-scripts/ cava-to-tv KWin script backup-configs
kde/applications/ cava-fullscreen.desktop, Proton desktop launchers manual
kde/icons/ Proton icon assets manual
config/cava/, config/kitty/ cava visualizer + kitty's cava profile backup-configs
config/ssh/config SSH client config (from ~/.ssh/config) backup-configs
git/ gitconfig (from ~/.gitconfig), config-github (per-directory override for ~/dev/github/**) backup-configs
zsh/ zshrc, p10k.zsh — the login shell backup-configs
fish/ config.fish, fish_variables — kept as the fallback shell backup-configs
easyeffects/db/ EasyEffects presets (compressor, equalizer, gate, limiter, stereotools) backup-configs
system/fstab /etc/fstab backup-configs
systemd/ user-level systemd units (~/.config/systemd/user/) — see below backup-configs
packages/ pacman.txt (explicit native installs), aur.txt (explicit foreign/AUR installs) backup-configs
bin/ backup-configs, sync-systemtray, check-claude-denylist manual

check-claude-denylist

Audits Claude Code's two deny lists in ~/.claude/settings.json against what /opt/docker actually holds, so they stay correct by verification rather than by memory. Read-only; prints paths, never file contents. Exit 1 if anything needs attention.

Lives here rather than in /opt/docker because it reads personal harness config, and that repo is headed public.

Four checks, each mapping to a mistake that has actually happened:

  • overbroad — a pattern denying a git-tracked file. Tracked means deliberately not secret, so this is the blanket-.env-wildcard mistake.
  • mirror driftpermissions.deny only binds the Read tool; sandboxed Bash obeys sandbox.filesystem.denyRead instead. A path in one and not the other is a real hole. Compares coverage, not pattern text, since the two lists legitimately use different patterns for the same protection.
  • fragile **denyRead's ** doesn't reliably match targets 01 segments below its anchor. Flags those, skipping ones a per-stack literal already covers.
  • stale — a pattern matching nothing on disk. Harmless, but it means the list has drifted.

Run it after adding a service, moving a secret, or changing what the repo tracks.

backup-configs

bin/backup-configs is the sync automation: it copies each live file/dir in its MANIFEST into the repo, regenerates the package lists, and — if anything changed — commits (--push also pushes). Run it after any config change you want captured, or on a schedule.

Not covered by the manifest (edit these paths in the repo directly, or extend the manifest if they become worth automating):

  • bin/* scripts themselves
  • kde/applications/, kde/icons/ (Proton launchers/icons)

Restoring on a fresh install

Packages

sudo pacman -S --needed - < packages/pacman.txt
# then install an AUR helper if needed, e.g.:
paru -S --needed - < packages/aur.txt

KDE Plasma

Copy from kde/: kdeglobals, kwinoutputconfig.json, plasmarc, plasmashellrc, kwinrulesrc (has the Proton Mail alt-tab rule), kwinrc, konsolerc into ~/.config/.

Copy kde/konsole-keytabs/ into ~/.local/share/konsole/ and kde/kxmlgui5-konsole/ into ~/.local/share/kxmlgui5/konsole/ to restore the custom Konsole keyboard scheme and Copy/Paste shortcut rebinds.

KWin Tiling (DP-2 portrait monitor)

After a fresh install, KWin tiling on the secondary monitor resets on logout if other monitors have non-default tile layouts. Known Plasma 6.4+ regression.

Fix: Leave all other monitors at their default single-tile layout (don't configure tiling on them). Only configure tiling on DP-2. Set the 50/50 horizontal split with Super+T.

KWin Scripts

kde/kwin-scripts/<name> holds KWin scripts (currently cava-to-tv, which sends the cava/kitty TV visualizer window to the HDMI-A-1 output on open — the classic window-rule "Force screen" approach doesn't reliably win against a window that requests fullscreen immediately at launch).

  1. Install: kpackagetool6 --type KWin/Script -i kde/kwin-scripts/<name>
  2. The enabled flag (kwin4_script_<name>Enabled=true under [Plugins]) is already restored as part of kwinrc, but a freshly-installed script still needs loading for the current session: qdbus6 org.kde.KWin /Scripting loadScript ~/.local/share/kwin/scripts/<name>/contents/code/main.js <name> then qdbus6 org.kde.KWin /Scripting start
  3. It auto-loads on future logins without step 2.

Proton App Icons

  1. Copy PNGs to ~/.local/share/icons/hicolor/256x256/apps/
  2. Copy .desktop files to ~/.local/share/applications/
  3. Run gtk-update-icon-cache --force --ignore-theme-index ~/.local/share/icons/hicolor
  4. Run kbuildsycoca6 --noincremental
  5. Window rules are restored automatically via kwinrulesrc

systemd user units

systemd/ holds user-scope units (~/.config/systemd/user/, not /etc/systemd/system/):

Unit Purpose Schedule
docker-goroutine-watch.timer captures a dockerd pprof goroutine dump if the count spikes (see bin/docker-goroutine-watch.py) every 5 min

Install:

cp systemd/*.service systemd/*.timer ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now docker-goroutine-watch.timer

The CrowdSec hub update, Invidious restart, IP2Location renewal, and Docker image prune timers that used to live here moved to /opt/docker/_helper/ (each has its own directory: crowdsec-hub-update/, invidious-restart/, ip2location/, docker-image-prune/) — they operate entirely on the docker stack, so the docker repo is the more natural home. Same for the docker.service TimeoutStopSec override, now at /opt/docker/_helper/docker-service-override.conf. See that repo's Maintenance doc.

btrfs maintenance (/mnt/external, run on fresh install)

Not tracked as repo files — create these by hand:

sudo systemctl enable --now btrfs-scrub@mnt-external.timer  # built-in unit

/etc/systemd/system/btrfs-balance-external.service:

[Unit]
Description=btrfs balance /mnt/external
ConditionPathIsMountPoint=/mnt/external

[Service]
Type=oneshot
ExecStart=/usr/bin/btrfs balance start -dusage=50 -musage=50 /mnt/external
IOSchedulingClass=idle
CPUSchedulingPolicy=idle

/etc/systemd/system/btrfs-balance-external.timer:

[Unit]
Description=Weekly btrfs balance /mnt/external

[Timer]
OnCalendar=weekly
RandomizedDelaySec=1h
Persistent=true

[Install]
WantedBy=timers.target

Then:

sudo systemctl enable --now btrfs-balance-external.timer

system/fstab: /mnt/external uses x-systemd.device-timeout=2,x-systemd.idle-timeout=60 to avoid a 90s hang when unplugged (fixed 2026-07-20).

sync-systemtray

Keeps systray applet layout mirrored across panels on multiple monitors. Has hardcoded containment/applet IDs (SRC_CONT, SRC_APP, TARGETS) at the top of the script — these are install-specific and need updating after a reinstall or if Plasma reassigns them.

Finding the current IDs

Find all systemtray applet headers:

awk '/^\[Containments\]\[[0-9]+\]\[Applets\]\[[0-9]+\]$/{header=$0} /plugin=org\.kde\.plasma\.systemtray/{print header}' ~/.config/plasma-org.kde.plasma.desktop-appletsrc

This gives three lines like [Containments][N][Applets][M] — one per panel. To determine which screen each belongs to, check the lastScreen= value for each containment:

grep -A5 '^\[Containments\]\[N\]$' ~/.config/plasma-org.kde.plasma.desktop-appletsrc | head -6

lastScreen=0 is the primary (source), 1 and 2 are targets.

Updating the script

Edit the constants at the top of sync-systemtray:

SRC_CONT = <panel_id for screen 0>
SRC_APP  = <systemtray applet id for screen 0>

TARGETS = [
    (<panel_id screen 1>, <systemtray applet id screen 1>),
    (<panel_id screen 2>, <systemtray applet id screen 2>),
]

Verify with --dry-run before applying:

sync-systemtray --dry-run