2026-07-09 fzf Widget Rename and the Nix GC App Management Block

What I set out to do

Read the errors and warnings out of the update -c run sitting in the config:1.0 tmux pane. Turned into a small declarative fix plus a diagnosis that overturned a stored memory I’d been trusting for two weeks.

What I actually did

Read the update run. update -c had completed: flake update, nix flake check, hm switch, uv/marketplace/nvim updates, cleanup. Most of the noise was benign. nix flake check printed ten error: file ... does not exist in binary cache 'https://cache.garnix.io' lines for Python wheels, but the presigned R2 URLs carry X-Amz-Date=20260702 with X-Amz-Expires=7200, so they’d expired a week earlier and nix fell back to source. unknown flake output 'debug'/'allSystems' is already documented as intentional in nix/flake.nix:102-113. uv tool upgrade warned that huggingface-hub==1.22.0 no longer has a cli extra (upstream folded the CLI into the base package); that tool isn’t declared in nix/ at all, so the extra is baked into a hand-run uv tool install receipt.

fzf widget migration (9c3dbe0): the 2026-07-09 HM bump renamed four programs.fzf options to a nested schema. Migrated fileWidgetCommand/fileWidgetOptionsfileWidget.command/.options and the changeDirWidget pair likewise, verified against the locked HM source (modules/programs/fzf.nix:161-183). Confirmed correctness by evaluating home.sessionVariables before and after: the generated FZF_* env vars are byte-identical.

Atuin gets Ctrl-R explicitly. The same bump added a warning that fzf and atuin both bind Ctrl-R for zsh. Atuin was already winning by sourcing later — i.e. the setup depended on load order, not intent. Set programs.fzf.historyWidget.command = "", which makes fzf skip installing the binding entirely: key-bindings.zsh:183 and key-bindings.bash:160 gate the block on ${FZF_CTRL_R_COMMAND-x} != "", so an empty but set variable is the off switch while unset falls through to the default. Needs fzf ≥ 0.66.0; we’re on 0.73.1. Verified on the live system with zsh -i -c 'bindkey "^R"'atuin-search.

Nix GC / App Management, and a wrong memory. The cleanup step ended with error: chmod ".../ghostty-bin-1.3.1/Applications/Ghostty.app": Operation not permitted and 0 store paths deleted, 0.00 MiB freed. Two things turned out to be false:

  • The summary line lies. Nix prints deleting '<path>' before removing each path, deletes them for real, then aborts at the first .app and never writes the counter. Spot-checked three paths from the middle of the log — all genuinely gone. GC reclaims everything it reaches until it trips over one of the 35 .app bundles in the store, then dies. So it’s a partial success reported as a total failure.
  • It isn’t the terminal that lacks the grant. My memory said “grant the terminal App Management + restart it,” from 2026-06-27. But TCC.db shows Ghostty has held kTCCServiceSystemPolicyAppBundles = 2 since 2025-11-15, months before that session. Reproduced the failure in isolation with nix store delete on the single dead path. Since /nix is a multi-user daemon store, an unprivileged client hands deletion to nix-daemon (root, launchd) — and root getting EPERM on a writable APFS volume means TCC, not ownership. nix-daemon has no TCC row at all, and daemons can’t raise a consent prompt, so it’s denied silently. The store even has a path-keyed denial for .../nodejs-slim-24.15.0/bin/node, showing macOS evaluates this per binary.

Corrected project_nix_gc_app_management_block with an explicit retraction rather than a quiet overwrite, and rewrote its MEMORY.md pointer, which had been injecting the wrong fix into every session’s context. The 78G→52G figure from that note traces to [[project_storage_cleanup_2026_06]], which was never actually written, so I dropped it rather than repeat an unsourced number.

Atuin inline up-arrow: still not a thing. Re-checked upstream at atuin 18.16.1. atuinsh/atuin#798 (“Replace native up arrow more seamlessly”) has been open since 2023-03-22, 40 comments, last activity 2026-03-21, no PR. The only thing that landed is inline_height_shell_up_key_binding (PR #2817, merged 2025-08-04), which sets the TUI height for the up-key path only — still the picker, but at height 1-3 it approximates inline cycling. We’re on inline_height = 20 with no up-key override.

What was striking

  • A tool’s own summary line was the wrong thing to trust, again. 0 store paths deleted, 0.00 MiB freed is emitted by an abort path and contradicts what the same command printed thirty lines earlier. I reported “freed nothing” to the user on its authority before checking whether the paths existed. Exactly the feedback_verify_tool_output failure mode, one day after writing it down.
  • A memory can be a confidently-worded wrong hypothesis. The 2026-06-27 note read as settled fact (“user granted it and reran; 78G→52G”), but the grant predated it by eight months and the byte count is explained by GC’s partial success. Post-hoc correlation, frozen into a durable artifact and re-injected every session. Worth treating “I fixed X and then Y worked” memories as hypotheses unless the note says what was falsified.
  • Load-order coincidence read as configuration. Atuin owned Ctrl-R only because its zsh integration sourced after fzf’s. Nothing declared it. HM’s new warning is doing real work by forcing the choice to be written down.