What changed in the dotfiles since Part 17
A command guard that stuck, a semantic-search layer, a nix cleanup that split up two oversized modules, an agent-version migration that's still just a plan, and a workaround for a Bedrock bug that kills long agent sessions.
The dotfiles repo took a lot of commits this stretch. Most were noise. The ones that mattered added a command guard for agents, split up two oversized nix modules, and worked around a Bedrock bug that kills long subagent sessions.
Parts 14 to 17 already cover the bigger pieces from this period, the meeting overlay, Tailscale and the agent VM, the PR review job, the local model, so I'm skipping those here. I say when something is a plan and not a fact.
A command guard, and a second one I pulled back out
I added a destructive-command guard, a small Rust binary that runs as a pre-execution hook in both agent runtimes I use. It matches exact patterns, which makes it a hard floor under the softer prompt-level guardrails I'd relied on before. The guards post covers what it catches and what it misses.
Exact patterns miss anything destructive that doesn't look like a known-bad shape. I tried closing that gap with a small local model that scores a command's risk instead of matching it against a list. Against four commands the guard had missed, it caught exactly one, at a threshold that would also have flagged ordinary work as suspicious. That ratio wasn't good enough to keep running, so I pulled the whole thing back out a week or two later. The pattern guard is the only one left in the plugin path.
Semantic search over the agent's own tools
The same stretch added a local search server that blends keyword search with embeddings, so agents stop guessing which file holds an answer. It runs a per-workspace index and starts with the shell. Before that I'd added a symbol-lookup server backed by the language server protocol, which made an older code-search tool redundant, so that one came out.
The rule I settled on: exact search first, semantic search only when I can't name the symbol I'm looking for.
Cleaning up two modules that had gotten out of hand
A nix-darwin audit from earlier in the year had left a handful of follow-ups sitting open. One module had grown to nearly a thousand lines and needed splitting into smaller files, a pure move with no logic changes. A separate file was importing nixpkgs four separate times for no good reason, once each for a few different consumers; one memoized function fixed it. A third file split cleanly into its own small directory.
The same pass removed a VM setup for an ops agent that had been sitting disabled for months, tied to a deploy tool that hadn't seen a real commit upstream in well over a year. A different, simpler setup for that same agent, no credentials mounted, was left alone.
I also added a script that checks live Homebrew state against what's declared in nix, since my setup zaps anything undeclared on every rebuild. It only warns, it doesn't block a rebuild, and a later fix removed some false positives it was throwing against build dependencies it shouldn't have cared about.
A migration that's still just a plan
I wrote up a plan for moving to a newer major version of the coding agent I use day to day. The plan says plainly that nothing in it has run yet, and that's still true. The blocker is the same Homebrew zap setting: a manual install outside nix would get removed on the next rebuild, so the tap has to go in by hand first, declared properly after. The harder part is two of my own plugins, both generated by external tools, that use a hook shape the newer version doesn't support yet. Until there's a fix for that, I turned off the agent's self-update so the version stays pinned under nix on purpose.
A turn budget for long subagent runs
There's a known bug where a long subagent session on Bedrock hits a wall around twenty tool calls and the API call fails outright, with no way for the subagent to save state before it dies. I made my implementation agent count its own turns. A few calls before the wall, it writes a checkpoint describing what's done, what's left, and how to resume, then ends its reply with a marker the orchestrating agent recognizes. The orchestrator starts a fresh subagent from that checkpoint instead of losing the work outright. It costs some repeated context on every restart. Still beats losing an hour of work to a crash.
Smaller things worth recording
A couple of shell abbreviations were pointing at the wrong underlying commands and got fixed. The terminal multiplexer I use for agent sessions got its config inlined into the repo, and its prefix key changed after I found it collided with a macOS shortcut. The full story is here. I tried generating images locally with a small model; the text output came out garbled and I dropped the whole function.
I also added a lightweight skill that tracks whether a shipped feature actually moved the metric it was meant to move, checking in at a few points over the following weeks instead of assuming success and moving on.
Still open
The agent-version migration hasn't started. Someone has to do the manual tap-and-install step, and the two generated plugins still need a path forward before the upgrade is safe. A NixOS host config also broke, because a setting it relied on silently stopped doing anything in a newer version. I moved it to the setting that replaced it, but haven't rebuilt that host to confirm it actually works.