March 2026
Quick reminder of a comment to set vim file type (but this catch 22 - vim needs to know the file type to know to parse a comment to know to apply the file type comment)
Apparently vim 'modelines' helps with the chicken and egg by scanning first few lines for vim style comments
Command-line window (q:)
q: opens an editable buffer of command history — not just for searching, you can actually edit commands in it like a normal buffer (yank, paste, modify), then hit Enter on a line to execute. Also accessible via <C-f> from the : prompt.
Completion broken again (autopairs referencing nvim-cmp)
Completion stopped working again. Previous investigation (see "Nvim glitching after zellij layout change" above) found lspsaga was the cause - disabled it, fixed it.
This time: autopairs.lua was never updated when migrating from nvim-cmp to blink.cmp (Oct 2025). It still had dependencies = { 'hrsh7th/nvim-cmp' } and called require 'cmp' on InsertEnter. Since nvim-cmp is no longer installed, this errors every time you enter insert mode, potentially breaking blink.cmp completion.
Fix: removed the nvim-cmp dependency and require 'cmp' integration from autopairs.lua. Autopairs still works standalone, just no longer auto-adds () after selecting a function from completion (blink.cmp handles this differently anyway).
Zellij edge detection + hyprland flash (TODO)
Requirement: when moving focus hits an edge (no pane in that direction), flash the hyprland border red (like move-focus.sh does for hyprland windows).
Pain points:
- zellij
bindonly supports a single action — can't chain "get pane id → move focus → check pane id → flash" vim-zellij-navwasm plugin handles nvim detection internally, can't wrap it with a scriptsmart-splits.nvimat_edge = 'stop'is broken — the zellij mux hardcodesDirection.leftregardless of direction arg- zellij plugin
Keyevents only fire when the plugin's own pane is focused, not globally
Proposed solution: custom zellij wasm plugin move-focus-jol:
- Receives
MessagePluginwith direction (like vim-zellij-nav) - Gets pane id → calls
move_focus→ checks pane id again - If unchanged →
run_command("hyprctl", ...)to flash border - Fork
vim-zellij-navto callmove-focus-jolinstead ofmove_focusdirectly - Update nvim
zellij-nav.nvimto messagemove-focus-jolinstead ofzellij action move-focus - Everything funnels through one plugin that owns edge detection
Bash parameter expansion (suffix removal)
The single % is the shortest match from end of string operator, whereas %% is large suffix removal operator.
In this mode
.is a literal dot, not a regexp dot for any char
- Notice how nothing matched on the
file%%g: must match to end of string file%%g*is greedy so goes up to thegzad the endfile%a*so goes for the firstainbackup
Vim Dadbod UI
Ok wow i found something today i cannot believe it took me this long to find?
whilst in vim dadbod mode will only execute selected text as a query - kind of like filip does in DBeaver - which is awesome!
Opening a blank buffer
:enew— opens a new blank buffer in the current window (mnemonic: edit new):new— opens a new blank buffer in a horizontal split:vnew— opens a new blank buffer in a vertical split
Vim: Redirect command output to register
:new | put =execute('SomeCommand') — this opens a new scratch buffer and pastes the output of any ex command into it. Breakdown:
:new— opens a new empty splitput =— puts the result of an expression into the bufferexecute('...')— runs an ex command and captures its output as a string
So execute('Fidget history') runs :Fidget history and returns the output text, then put = pastes it into the buffer where you can search with /.
Works with any command, e.g. :new | put =execute('messages'), :new | put =execute('map')
Ok so (ME not claude as of now...)
| is not actually what i thought like a pipe in bash, it is actually just like ; in bash (see :h :bar in vim)
So in this case we are just saying :new to open a new buffer and THEN :put to dump the output of the register
Gotcha: | doesn't work with all commands. Some commands treat | as part of their own arguments instead of as a command separator. User-defined commands (from plugins) do this by default unless the plugin author explicitly opted in to | separation with -bar (see :h command-bar). So:
Fix: use <cmd>...<cr> chaining in a keymap, or just use separate commands. In ex mode, there's no clean workaround — run them separately:
Or in a keymap:
e.g.
dumps 'pls' into current buffer
i did try this
BUT echo doesn't return to a buffer so it wouldn't work. WAIT IGNORE. just needed to escape the " with
....or...
Vim registers and the " prefix
Registers in vim are accessed with " (double quote) in normal mode.
Special registers:
to see help can use vims special 'quote' like
:h quote=is equivalent to:h "=
Accessing registers — " vs @:
Why quote= in vim help?
Vim help spells " as quote in its help tags, so :h quote= means "help for the "= register", :h quotea for "a, etc.
GH issues
I should really learn this.... so search for issues
have to specify --repo then just gh search issues...
Ok so it turned out the relevant issue i was looking for is a discussion (here) and gh api doesnt support discussions....
Disk space cheat sheet
To list all block devices (the /dev/xxx names for cfdisk/parted):
Why nix-tree shows 30GB but /nix/store is 122GB:
nix-tree only shows the closure of the current system profile — the set of packages reachable from this generation. /nix/store also contains old generations, cached build deps, devenv shells, and anything not yet garbage collected. Run sudo nix-collect-garbage -d to prune old generations (careful: removes rollback ability).
Does the math add up? (March 2026)
Neovim display corruption on terminal resize
Ghost lines, black spots, misaligned rendering when resizing (fullscreen toggle, zellij pane resize).
Only happens inside zellij — confirmed no issue in bare kitty terminal.
Cause: Neovim's CSI 2026 (termsync / synchronized output) misimplementation conflicts with zellij's terminal emulation layer. Zellij acts as terminal-within-a-terminal and must relay escape sequences — mismatch causes artifacts. Zellij creator confirmed: "99% a misimplementation of CSI 2026 by nvim." (neovim#29427, zellij#426, zellij#3415)
Fix — disable termsync in nvim config:
Other things that help:
- Set
TERM=xterm-256colorinside zellij (avoidxterm-kittyetc) Ctrl-Lto manually force redraw- If using noice.nvim, set notify stages to
"static"(zellij#3208)
Yazi image/video previews black in zellij
Yazi mediainfo plugin shows black screen for both image and video previews.
Only happens inside zellij — confirmed previews work fine in bare kitty terminal.
Cause: Likely zellij doesn't support passthrough for the kitty graphics protocol, which yazi uses to render inline images. Zellij's terminal emulation layer can't relay the graphics escape sequences properly. (zellij#1796)
Helix — vim equivalent workflows
Helix is selection-first (select then act) vs vim's verb-first (act then motion). Here's the mapping for common vim workflows:
Key mental shift: in helix you select first, then act. So "delete 3 lines" is xxd not 3dd. Takes getting used to but means you always see what you're about to affect before doing it.
lazydev.nvim — what it actually does
Without lazydev, lua_ls only knows Lua syntax — it has no idea vim exists as a global, so you get Undefined global 'vim' warnings and zero completions for vim.*.
What lazydev does: tells lua_ls to index Neovim's bundled type definitions ($VIMRUNTIME/lua/vim/) so it learns about vim.api.*, vim.keymap.*, vim.lsp.*, etc. Also loads types for installed plugins.
The luv/luvit thing: Neovim's event loop is built on libuv (same C library that powers Node.js — async I/O, timers, filesystem). Neovim exposes it to Lua as vim.uv. The { path = '${3rd}/luv/library', words = { 'vim%.uv' } } in the config just conditionally loads the type defs for vim.uv.* only when you actually use it.
March 2026
Zellij + Image Preview (Yazi) — Why It's Broken
The problem: yazi image preview works in zellij but large or wide images corrupt the entire zellij render — the screen becomes garbled and unusable.
Root cause: Zellij acts as a middleman for terminal graphics. When an image's pixel dimensions exceed the pane boundaries, the sixel/kitty image data bleeds past what zellij expects, corrupting its internal screen buffer. Zellij redraws fail to recover because the image escape sequences have already overwritten cell state. This is a known zellij limitation — multiplexers have to parse and clip image output, and zellij's clipping is incomplete for oversized images.
Current status: images preview fine until a large image is selected, then zellij's rendering breaks. This is a zellij-side bug with oversized image clipping. No clean workaround yet — can mitigate by setting max preview dimensions in yazi or waiting for a zellij fix.
Possible mitigation — cap yazi preview size in yazi.toml:
Related GitHub issues:
Zellij — Moving Panes into Stacks
The problem: no obvious keybinding to move an existing pane into an existing stack in zellij.
Solution: use zellij action stack-panes CLI action — takes pane IDs and combines them into a stack.
Getting pane IDs: need zellij action list-panes (added in v0.44.0), which isn't available on NixOS yet. Until then, zellij action dump-layout can be parsed for pane IDs as a fallback, or use multi-select (Alt+p on each pane) to stack interactively.
LibreOffice Calc — Reloading a File
To reload the current file in LibreOffice Calc: press Alt+F to open the File menu, then press Down arrow until you reach Reload, then press Enter.
SteelSeries Arctis 7 — Mic Not Showing Up
The problem: mic input wasn't appearing as an available source.
Solution: open pavucontrol → Configuration tab → select Game Output + Game Input profile for the SteelSeries Arctis 7.
Why this works: USB audio devices like the Arctis 7 expose multiple endpoints (output-only, output+input, chat, game, etc). PipeWire/PulseAudio represents these combos as profiles on the sound card. Profiles are entirely host-side — the device just advertises available USB audio endpoints, and the audio server decides which to activate. If the selected profile doesn't include a capture endpoint, no mic source gets created. Switching to a profile that includes input activates the capture endpoint and the mic appears.
Terminal equivalent:
Profile selection is persisted in ~/.local/state/wireplumber/ (PipeWire) or ~/.config/pulse/ (PulseAudio) so it survives reboots.
Linux Audio Debugging — Tools & Terminology
Audio stack (top to bottom):
Key terms:
Recording/playback tools tested:
Useful commands:
Agenix - rekeying secrets after adding a new host
When you add a new host public key to secrets/secrets.nix, you need to rekey so the secret gets re-encrypted for the new recipient.
The command that actually works:
Key gotchas:
-iwants the private SSH key of a host already insecrets.nix, NOT the.agefile- needs
sudobecause/etc/ssh/ssh_host_ed25519_keyis root-owned agenix -ralone fails with "no identity matched any of the recipients" — it doesn't auto-find the host key- the error messages are completely unhelpful

