What changed in the dotfiles since Part 17
Status for 2026-08-15 to 2026-09-30: a command guard, semantic search, a nix audit cleanup, an unexecuted OpenCode v2 plan, and a Bedrock workaround.
Between 2026-08-15 and 2026-09-30 the dotfiles repo took 169 commits. 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 meeting overlay, Tailscale and the agent VM, the PR review job, and the Bonsai 2 model, so I skip those here. Everything below comes from git log and the handoff docs in docs/handoff/, checked again on 2026-09-30. The repo is private, so I give commit hashes only where the table needs them. I say when something is a plan and not a fact.
A command guard, and a semantic one that I removed
On 2026-09-09 I added dcg (v0.14.1), a destructive command guard. It runs as an auto-discovered OpenCode plugin and as a Claude Code PreToolUse hook, and ai-tools installs both on a fresh machine. It matches exact patterns, so it is a hard layer under my older prompt-level guardrails, which only ask the model to behave. The guards post shows what it blocks and what it misses.
Exact patterns miss commands that are destructive without looking it. On 2026-09-23 I added laya-approval-gate.js, which asks a small local model, Laya, whether a bash, edit, or write call looks destructive. I measured it against four commands the denylist allowed. chmod -R 000 scored 0.83 and was caught. A cp -f /dev/null overwrite scored 0.64. A rename and a mass find-and-replace scored 0.24 to 0.29, so the model missed both. I set two bands, deny at 0.8 and warn at 0.55, because one high cutoff would have missed the only real catch.
That result is why I backed it out. On 2026-09-25 I removed the Laya pre-filter steps from three personal skills. On 2026-09-30 I committed the deletion of the plugin file and its nix wiring, so the gate no longer runs. dcg is the only guard left in the OpenCode plugin path.
Semantic search and code intelligence over MCP
The same commit added zvec-grep, a local search server that combines BM25 with embeddings. It builds a per-workspace index, and the fish login shell starts the server. Agents call it when they do not know which file holds an answer. Before that I had added Serena, which gives agents LSP-backed symbol lookup, and fixed its launch command the next day. I removed GitNexus because Serena covered what I used it for.
I use exact search first and semantic search when I cannot name the symbol. The layering is written up in the new "AI Agent Infrastructure" section of TOOLS.md.
The nix audit cleanup
On 2026-09-25 one commit closed the follow-ups from a nix-darwin audit. Four pieces:
home/mac-extras/default.nixwas 965 lines. It is now 51 lines, withgpg-ssh-agents.nix,fish-overrides.nix, andplatform-tools.nixbeside the existinglib.nix,launchd-agents.nix, andnix-gc.nix. It was a pure move with no logic changes.flake.niximported nixpkgs four times, once each forpkgs,pkgsDarwin, the packages, and the devShells. ApkgsForfunction now memoizes one import per system.ai-tools.nixsplit into anai-tools/directory withdefault,lib,opencode, andtools-and-skills.- The Hermes Firecracker VM is gone: the NixOS configuration, the
kropsinput,home/hermes-host.nix, and the TAP and NAT units. The separate Lima-based Hermes agent stays.
The commit also added scripts/brew-drift-check and a ,brewdrift abbreviation. My Homebrew block sets cleanup = "zap", which removes anything not declared in nix on the next darwin-rebuild switch. The script compares live Homebrew state to the declared config and lists what would be zapped. It only warns, and it does not block a switch. On 2026-09-30 I changed it to compare against brew leaves, which removed false positives from dependencies.
The OpenCode v2 migration is still a plan
On 2026-09-25 I wrote 2026-09-25-opencode-v2-brew-migration-plan.md. It says "planning only, nothing executed yet", and I rechecked on 2026-09-30 that this still holds. opencode --version prints 1.18.30, brew tap is empty, and the Homebrew block still has taps = []. I committed the plan itself on 2026-09-30.
The plan exists because of the zap setting. A v2 install done by hand with brew install anomalyco/tap/opencode-v2 would be removed on the next switch, and the comment I had left in nix/hosts/mac/default.nix said to install it manually. The fix is to tap once by hand, since a first tap under sudo has no TTY and can hang, and then declare the tap and the formula through per-person extraTaps and extraBrews. The plan also lists the harder part. My two remaining plugins, dcg-guard.js and herdr-agent-state.js, use the v1 hook shape. Both are generated by external CLIs, so they need an upstream release or a port before v2. Until then I turned off OpenCode's self-update so the model and version stay under nix.
A turn budget for @implement
OpenCode with Bedrock Claude has a known bug (anomalyco/opencode#40455). A subagent session that reaches about 20 tool-call turns gets a malformed continuation, the API call fails, and the subagent cannot save its state. I made @implement count its own tool calls. After the 14th call it writes a checkpoint to ~/.agent-work/status/<task-slug>.md with Done, Remaining, and Resume-with sections, then ends its reply with CONTINUE-NEEDED: <task-slug>. The orchestrator prompt recognizes that line and starts a fresh @implement from the checkpoint. It costs some duplicated context on each restart, and it beats losing an hour of work to a crashed session.
Smaller things worth recording
I fixed my nh abbreviations twice. nh darwin switch is the command that runs brew bundle, so nhd uses it, and nh home switch never touches Homebrew. I inlined the herdr config into the repo and later changed its prefix key. HERDR.md now lists ctrl+b as the herdr prefix, and the herdr post has the full story. I also removed the local image generation function after its output text came out garbled, and kept the evaluation in docs/memory/2026-09-23-mlx-image-generation-qwen-zimage-abandoned.md.
On the skills side, I added impact-analysis. When a ticket ships, it records a baseline and up to three cheap metrics, then sets reminders for days 15, 30, 45, and 60. Each sprint retro sweeps the open records and flags any checkpoint it cannot measure instead of skipping it.
What changed, in one table
| Date | Change | Commit in my private repo |
|---|---|---|
| 2026-09-09 | dcg guard and zvec-grep added | 50e7fdb |
| 2026-09-23 | Laya approval gate plugin added | none |
| 2026-09-24 | @implement turn-budget checkpoint | none |
| 2026-09-24 | impact-analysis skill | none |
| 2026-09-25 | mac-extras split, nixpkgs dedupe, Hermes VM removed, brew-drift-check | 034ada7 |
| 2026-09-25 | OpenCode v2 plan written, not executed | handoff doc only |
| 2026-09-30 | Laya plugin removed, journald fix for the NixOS host | 5edcb95 |
What is still open
- The OpenCode v2 migration has not started. Someone has to run the tap by hand, and the two generated plugins need a v2 story.
- The Homebrew tap-hang risk under
sudo darwin-rebuild switchis untested, since the tap does not exist yet. nixosConfigurations.defaultfailed to evaluate becauseservices.journald.extraConfigno longer had any effect. I moved it tojournald.settings.Journalon 2026-09-30, but I have not rebuilt the NixOS host to confirm.