Learnings¶
Each learning is one bug, gotcha, or measured lesson from dotfiles development.
Search by the symptom, not by the tool¶
Reach for these before diagnosing a broken install, a tool that stopped working, or an error that makes no sense. A learning quotes the error text verbatim wherever there is one, so the string on screen is the string to search for:
The site search above covers the same ground from a browser.
General technical notes that name nothing in this repo live on the hub at https://docs.ichrisbirch.com/, so a symptom search covers both.
The record, listed by what it looked like¶
- App Installation Patterns — a new CLI tool and no obvious place for it; the four categories, and what picks between them
- uv Tool Git Pins and Self-Update — the updater reports a tool already at the latest version, and the tool itself announces one eight releases newer
- uv tool install Ignores the Lock — a git tool exits 3 on
every clean run as installed while its CI passes, because the install resolved dependencies
newer than its
uv.lock - Minimal Manifest for Servers — a headless LXC box pointed at the only available manifest installs docker, ffmpeg and every desktop package
- Undeclared Transitive Dependency —
ModuleNotFoundError: No module named 'click'from the installed tool, after ruff, mypy, pytest and four CI jobs passed and the change merged - Symlinks Path Gotchas —
.gitconfigsilently stops being symlinked, and a second path bug beside it that the unit tests did not catch - A Test Writes Through a Deployed Symlink — every tool that resolves the repo registry fails at once, and a deployed config is no longer a symlink
- WSL Credential Helper Exec Format Error —
git-credential-manager.exe: Exec format error, re-authenticating does nothing, and a reboot fixes it - pre-commit Stash Recovery — a killed pre-commit run and the tree comes back without the unstaged changes
- Shared Stash Across Worktrees — edits disappear from one
worktree and surface in another, and
git stash popconflicts on files the branch never touched - Task Shell Printf Compatibility —
invalid format char: *from aprintfthat runs fine in a bash script - Profiling Zsh Startup — new shells intermittently take six seconds while most of them open in under half of one
- Resilient Installation Patterns — one unresolvable name
aborts a whole
brew installbatch, and the loss surfaces phases later as a missing binary - cargo binstall Falls Back to Compiling — an install
pauses for minutes with no output, which cannot be told from a deadlock, or a source-built StyLua
refuses a
gotolabel - A packages.yml Entry Is Not an Install —
fnm not foundon the offline box, with a completepackages.ymlentry sitting right there - A CIFS Mount Hides a Missing Helper —
mount error(113): No route to hoston a fresh distro, with DNS, hosts and routing all correct - Pyright Config File Precedence — a basedpyright warning
survives every LSP setting that should suppress it, including
ignore = { '*' } - Ghostty Shader Reload — an edited GLSL shader keeps rendering the old picture after a config reload, so every round of tuning looks identical
- The ORA by Kanto Volume Drop-in — the lower half of the volume slider is silent on a USB DAC, and waybar's percentage means nothing
- Finding Where a Slow Run Went —
dotfiles checkandapplytake five silent minutes, and nothing in the output or the run record says which part was slow - A Conflicting Package Blocks an Install Forever
—
yay -S exited 1on every run after a four-minute source build, with the reason only in the transcript - Go Was on No PATH, and Nothing Said So — Go tools
report an
unknownversion soapplynever upgrades them, and gopls cannot findgo - A Unix Socket Path Is Shorter Than tmp_path —
tmux.sock (File name too long)at fixture setup, on macOS only - tmux Before 3.6 Can Lose a Pane's Exit Status
— a
remain-on-exitpane reads dead with no status forever, its command<defunct>under the server, on CI only - A Cache Outlives the File You Restored — a test fails on a mutation the file no longer contains, and two identical mypy runs disagree by hundreds of errors
- Hyprland Keeps the Config Format It Started With
— "You are using the .conf config format" survives a deployed
hyprland.luaand a reload, thenkeyword can't work with non-legacy parsers. Use eval.from every script - A /bin/sh Stub Is Bash Here and Dash on CI — a test
passes locally and fails on CI with
FileNotFoundErrorfor a file its stub writes, because dash printedBad substitutioninto a tmux pane