aboutsummaryrefslogtreecommitdiffstatshomepage
Commit message (Collapse)AuthorAgeFilesLines
...
* feat(nix): add LSPs/formatters/linters/DAPs to common.nixLibravatar sommerfeld11 days2-12/+50
| | | | | | | | | | | | | | | | | | | | | | Replaces Mason entirely (phase p6 of the nix migration will rip out mason-tool-installer and friends). The set tracks the previous ensure_installed list in nvim's lsp.lua, with five niche tools dropped per the migration plan: - groovy-language-server, npm-groovy-lint - nginx-language-server, nginx-config-formatter - systemdlint systemd-lsp is renamed to systemd-language-server (the nixpkgs attr name). codelldb is replaced by lldb-dap (upstream successor, ships with pkgs.lldb); dap configs switch in phase p6. Drops jre, basedpyright, cargo, rustc from vm.nix — they only existed to work around Mason quirks on Ubuntu 20.04 (uv-python wheel incompatibility, source-build needs). With Mason gone, basedpyright comes from nixpkgs cleanly on both profiles. Phase 5 of the nix-on-host migration plan.
* feat(zsh): prepend ~/.nix-profile/bin to PATHLibravatar sommerfeld11 days1-1/+6
| | | | | | | | | So Home-Manager-provisioned tools shadow pacman/apt across host and VM, delivering identical tool versions from the same flake.lock. Mason bin stays for now; phase p6 of the nix migration removes it together with the Mason plugins. Phase 3 of the nix-on-host migration plan.
* refactor(nix): promote remote-dev/ to nix/ with common/vm/host splitLibravatar sommerfeld11 days11-299/+325
| | | | | | | | | | | | | | | | | | | | Restructures the Home-Manager profile to support both the Arch host and the Ubuntu remote-dev VM from the same flake. - remote-dev/ → nix/ (hard rename; .chezmoiignore updated) - home.nix split into common.nix (shared), vm.nix (Mason runtime carve-outs + podman stack), host.nix (gpg scdaemon delegation to system pcscd) - flake.nix exposes homeConfigurations.{vm,host} via a mkProfile helper - rj alias in dot_zshrc updated to ~/.local/share/dotfiles/nix - bootstrap.sh / justfile updated to use #vm against the new path The split is behaviour-preserving for the VM: vm.nix + common.nix together carry the same package set as the previous home.nix. host.nix is provisioned but not yet wired into bootstrap (phase p8). Phase 1 of the nix-on-host migration plan.
* refactor(sway): remove super+o VPN OTP keybindLibravatar sommerfeld11 days2-4/+0
| | | | No longer needed.
* feat(pkg): downgrade jdk-openjdk to jdk21-openjdkLibravatar sommerfeld11 days1-1/+1
| | | | | | | | Gradle 9.1 (and thus Mason's groovy-language-server build) doesn't support Java 26 bytecode yet — builds fail with 'Unsupported class file major version 70'. Nothing in the dotfiles uses a feature beyond JDK 21, and both packages provide the same java-runtime virtual, so dependents are unaffected.
* feat(zsh): add dj/rj aliases for dotfiles and remote-dev justfilesLibravatar sommerfeld11 days1-0/+2
| | | | | | | dj invokes ~/dotfiles/justfile and rj invokes ~/.local/share/dotfiles/remote-dev/justfile, both pinned to the justfile's directory via --working-directory so the aliases behave identically from any CWD.
* fix(nvim): wrap vim.pack.update in :PackUpdate user commandLibravatar sommerfeld11 days1-1/+3
| | | | | | | nvim_create_user_command passes the callback a table with command metadata (args, bang, ...). Newer neovim's vim.pack.update validates its first arg as a list of names — that metadata table fails the list check with 'names: expected list, got table'. Wrap it.
* refactor(git): use classic .git/hooks/ for per-clone overrideLibravatar sommerfeld12 days2-11/+10
| | | | | | | | | | | | | | | | | Switch the dispatcher's per-clone override location from the bespoke .git/hooks-local/ to the classic .git/hooks/. This is: - The untracked location git has used since forever, so no new convention to learn. - Where husky, lefthook, pre-commit-the-tool, and most other hook managers install by default — they now "just work" again under our global core.hooksPath. git init's *.sample files don't collide because the dispatcher only matches the exact hook name and the executable bit. The only behavior change is that a forgotten legacy .git/hooks/pre-commit from before core.hooksPath was set will start running again — that's arguably restoring expected git semantics, not a regression.
* feat(git): per-clone hook override at .git/hooks-local/Libravatar sommerfeld12 days2-16/+35
| | | | | | | | | | | | | | | | Adds an untracked per-clone override layer to the hook dispatcher. Lookup order is now: 1. <git-dir>/hooks-local/<name> — untracked, per-clone, ignored by git 2. <repo-top>/.githooks/<name> — tracked, shared with teammates Use case: a shared repo ships a .githooks/pre-commit you want to locally replace without modifying the tracked file. Drop your hook in .git/hooks-local/<name> (chmod +x) and the dispatcher will run it instead — the global commit-msg trailer-strip and pre-push gate still run on top. If neither override exists, only the global user-level logic runs.
* feat(git): user-level hooks auto-dispatch into <repo>/.githooks/Libravatar sommerfeld12 days9-10/+90
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Inverts the hook delegation model. Previously per-repo hooks required a project to either (a) write the entire hook themselves and lose the global signed-commit / agent-author gate, or (b) override core.hooksPath and write passthrough stubs that exec back to $HOME/.config/git/hooks/*. Both are ergonomically miserable. Now: the global hooks at ~/.config/git/hooks/ are *always* the entry point. Each one calls a shared dispatcher (_dispatch.sh) that runs <repo>/.githooks/<hookname> if it exists, propagating its exit status, and then continues with whatever the global hook itself wants to do. Projects just drop an executable file at .githooks/<name> — no core.hooksPath, no stubs, no boilerplate. Repos that don't have a .githooks/ dir keep working exactly as before. GIT_HOOK_DISPATCHED guards against re-entry so legacy repos using the old stub-and-exec pattern don't loop. pre-push tees stdin so both the repo hook and the global ref-list loop see the full push payload. Adds two new always-no-op global hooks (pre-commit, post-commit) purely so the dispatch happens for those events too — previously only commit-msg and pre-push existed globally. Refactors this dotfiles repo to use the new pattern: drops the self-delegating .githooks/pre-push stub and removes the per-repo core.hooksPath override from `just init` (now an idempotent unsetter to clean up the override from past bootstraps). The remote-dev VM's home-manager profile symlinks all four hooks plus _dispatch.sh.
* feat(git): commit-msg hook strips AI Co-authored-by trailersLibravatar sommerfeld12 days2-0/+61
| | | | | | | | | | | | | | | | | Various agentic tools (Copilot CLI, VS Code chat, etc.) auto-append `Co-authored-by: Copilot <...>` / Claude / Codex trailers, which then trip the pre-push hook's agent-coauthor check and force a manual amend before the push goes through. Scrub at commit time instead. Uses the same agent-substring list as executable_pre-push (kept in sync by comment). Triggered as commit-msg (not pre-commit — pre-commit runs before the message exists). Drops matching trailers in-place, collapses trailing blanks, and is a no-op otherwise. Also symlinks the new hook in the remote-dev home-manager config so it deploys on the Ubuntu VM. Bypass: `git commit --no-verify`.
* fix(remote-dev): symlink git pre-push hook with stripped chezmoi nameLibravatar sommerfeld12 days1-0/+5
| | | | | | | | | | `dot_config/git/hooks/executable_pre-push` only loses the `executable_` chezmoi attribute prefix during `chezmoi apply`. On remote-dev we use raw home-manager symlinks, so a directory symlink gave git a file literally named `executable_pre-push` — which is not a valid hook name and was silently ignored. Symlink each hook to its stripped target name (executable bit comes from the working-tree mode, which git follows through the symlink).
* fix(remote-dev): source hm-session-vars from .zshenvLibravatar sommerfeld12 days1-0/+6
| | | | | | | | | | | | home.sessionVariables get written to hm-session-vars.sh, which HM only auto-sources when programs.bash/zsh.enable = true (it injects a snippet into the rc file) or via ~/.profile (which zsh login shells don't read). We use a ZDOTDIR redirect and no HM-managed shells, so PODMAN_IGNORE_CGROUPSV1_WARNING (and any future session var) was never reaching the shell. Source it explicitly from the generated ~/.zshenv before redirecting to ZDOTDIR.
* feat(remote-dev): silence podman cgroups-v1 deprecation warningLibravatar sommerfeld12 days2-1/+10
| | | | | | | | Ubuntu 20.04 still defaults to cgroups v1; podman 5 emits a deprecation warning on every single invocation. Flipping the host to v2 is a reboot that affects every workload and only matters if we need rootless --memory/--cpus, so just silence the warning via the documented PODMAN_IGNORE_CGROUPSV1_WARNING env var on the home-manager side.
* fix(zsh): only rename zellij tab when our pane is focusedLibravatar sommerfeld12 days1-5/+17
| | | | | | | | | | | | | | | | | `zellij action rename-tab` always targets the focused tab — there is no CLI way to bind the rename to the calling pane. On session resurrect zellij re-spawns every shell almost simultaneously while one tab is focused, so every precmd hook fires and they all race to rename that single focused tab; the last writer wins and the rest of the tabs are stuck at `Tab #N`. This is the "all tabs got the same label" bug from earlier. Guard the rename hooks behind a focused-pane check using `zellij action list-clients` (matches the `terminal_<ZELLIJ_PANE_ID>` column). Background panes silently skip the rename and update lazily the next time the user focuses them and a prompt fires. After resurrect that means untouched tabs say `Tab #N` until you visit them — but no tab gets a wrong label anymore.
* fix(pacman): correct llama.cpp-vulkan IgnorePkg name (was llama-cpp-vulkan)Libravatar sommerfeld12 days1-3/+3
| | | | | | The AUR package is named with a dot, not a dash: `llama.cpp-vulkan`. The IgnorePkg entry used the wrong spelling, so it never matched and the package was upgraded on every -Syu.
* Revert "fix(paru): pin llama-cpp-vulkan via IgnoreDevel"Libravatar sommerfeld12 days1-6/+0
| | | | This reverts commit 1d7feb8d405e135dc6109052948b8b9240cf882a.
* fix(paru): pin llama-cpp-vulkan via IgnoreDevelLibravatar sommerfeld12 days1-0/+6
| | | | | | | | | | | | | | | pacman.conf's IgnorePkg only stops pkgver upgrades. paru in Devel mode runs `git ls-remote` against AUR -git sources during sysupgrade and rebuilds whenever upstream has a newer commit hash — which is exactly what was triggering the 1-2h llama-cpp-vulkan rebuild on every `just update`. IgnoreDevel is paru's purpose-built knob for skipping that devel recheck (paru.conf(5)). Manual `paru -S llama-cpp-vulkan` still works when an upgrade is intentional. (Replaces a botched first attempt that used IgnorePkg, which is not a valid paru.conf option.)
* Revert "fix(just): honor IgnorePkg in pkg-apply / pkg-fix"Libravatar sommerfeld12 days1-14/+3
| | | | This reverts commit eb0f9d71ed9527b5de5c82c9acce7c04bbec71e7.
* fix(just): honor IgnorePkg in pkg-apply / pkg-fixLibravatar sommerfeld12 days1-3/+14
| | | | | | | | | | | | | | | | | Pacman's IgnorePkg only applies to -Sy{u} upgrade operations; explicit `paru -S <pkg>` bypasses it entirely. `pkg-apply` and `pkg-fix` both pipe the meta/*.txt package lists into `paru -S --needed`, so every sync was reinstalling AUR pins (most painfully llama-cpp-vulkan, a 1-2h rebuild on every llama.cpp commit) whenever the AUR had a newer version, defeating the whole point of pinning. Parse IgnorePkg out of /etc/pacman.conf and strip those names from the list before piping to paru. `pkg-add` is intentionally left unfiltered: explicitly naming a package on the CLI is a deliberate opt-in that should still work for pinned entries. `pkg-update` (which is plain `paru -Syu`) already honors IgnorePkg via pacman itself — no change needed there.
* feat(mimeapps): make teams-for-linux (xsight profile) default for msteams://Libravatar sommerfeld12 days1-0/+2
| | | | | | | | | Both teams-sii.desktop and teams-xsight.desktop already advertise `MimeType=x-scheme-handler/msteams;` so they were registered as candidates, but mimeapps.list didn't pick a default and clicking an msteams:// link did nothing useful. Pin the xsight profile as the default; the sii profile is still available via `xdg-open` chooser / direct launch.
* refactor(zsh): rename zellij tabs to dir:cmd without position prefixLibravatar sommerfeld12 days2-8/+18
| | | | | | | | | | | | | | Zellij's default 'Tab #N' name is fixed at tab creation (the N is the immutable creation index, not the live position) and never auto-updates when tabs are closed or moved, so the default is actively misleading after any tab reorg. Tmux's `renumber-windows on` has no zellij equivalent and no plugin solves this cleanly. Restore shell-side renaming but drop the position prefix `N:` — visual order in the tab bar implies position. After a session resurrect or closing a middle tab, untouched tabs still show their previous dir:cmd label until the next prompt fires there, but at least there is no misleading number to second-guess.
* fix(yazi): render markdown with glow instead of okularLibravatar sommerfeld12 days1-2/+3
| | | | | | | | | okular is installed as flatpak (org.kde.okular), not as a native binary, so the bare `okular` invocation in the opener failed silently (orphan = true hides the ENOENT). glow is already in base.txt and renders inline in the terminal — better fit for a TUI file manager. block = true keeps yazi waiting until the user quits glow, mirroring `less`-style behaviour.
* fix(yazi): rename opener rule key from `name` to `url`Libravatar sommerfeld12 days1-2/+2
| | | | | | Yazi tightened its config schema; `name` is no longer accepted for glob-based opener rules, only `url` (or `mime`). Without this fix yazi errors on startup and falls back to preset settings.
* revert: drop snxctl-chromium wrapper, snx-rs works with default browser nowLibravatar sommerfeld12 days4-53/+2
| | | | | | | | | | | | User confirms snx-rs's SAML loopback no longer needs chromium routing. Remove: - dot_local/bin/snxctl-chromium (PATH-override wrapper) - dot_local/share/snx-rs/bin/xdg-open (chromium shim) - snx-rs LibreWolf SAML note in user-overrides.js The waybar snx-vpn toggle now just runs `snxctl connect` detached, no wrapper indirection.
* docs(remote-dev): mark cgroups v2 switch as optionalLibravatar sommerfeld12 days1-7/+8
| | | | | | Affects the whole host and requires a reboot — only worth doing if you need rootless --memory/--cpus limits. Rootless podman otherwise runs fine on cgroups v1.
* feat(remote-dev): rootless podman setupLibravatar sommerfeld12 days2-0/+70
| | | | | | | | | | | | | Adds podman + helpers (crun, conmon, netavark, aardvark-dns, slirp4netns, passt) to the home-manager profile, plus rootless-sane registries.conf, storage.conf (overlay driver, kernel-native — VM kernel 5.15 supports rootless overlay since 5.13, no fuse-overlayfs needed), and policy.json. Documents host-side prerequisites in remote-dev/README.md: install uidmap, ensure subuid/subgid entries for the user, and enable cgroups v2 (systemd.unified_cgroup_hierarchy=1) so rootless resource limits work on Ubuntu 20.04.
* feat(remote-dev): add mergirafLibravatar sommerfeld2026-05-141-0/+1
| | | | | git config defines a mergiraf merge driver; install it on the VM so .gitattributes references actually resolve.
* fix(remote-dev): materialize ~/.ssh/config with 0600 permsLibravatar sommerfeld2026-05-141-2/+8
| | | | | | | | | mkOutOfStoreSymlink exposes the working-tree file's perms. Under Ubuntu's default umask 002, git checks out private_dot_ssh/config as 0664; OpenSSH refuses any group-writable ssh_config. Replace the home.file symlink with a home-manager activation step that copies the file to a real ~/.ssh/config with 0600.
* fix(zsh): preserve forwarded SSH_AUTH_SOCK in SSH sessionsLibravatar sommerfeld2026-05-141-2/+6
| | | | | | | | | | zprofile unconditionally pointed SSH_AUTH_SOCK at the local gpg-agent's ssh socket. On remote machines (e.g. remote-dev VM) that clobbers ssh-agent forwarding — `ssh-add -L` reports no identities because the VM's gpg-agent has no keys. Only override when there's no forwarded socket (no $SSH_CONNECTION or no $SSH_AUTH_SOCK from sshd).
* fix(remote-dev): install basedpyright outside MasonLibravatar sommerfeld2026-05-144-12/+28
| | | | | | | | | | | | | | | | Mason's pypi distribution of basedpyright pulls nodejs-wheel-binaries which only ships manylinux_2_28 Linux wheels. uv's python-build- standalone interpreter is tagged manylinux2014 (glibc 2.17 for max portability) and rejects those wheels; pip then falls back to building Node 24 from source, which fails on Ubuntu 20.04's gcc 9.4 (needs gcc >=10 for -std=gnu++20). Provide basedpyright via the system package manager instead: - pacman on Arch (added to meta/base.txt) - pkgs.basedpyright on the VM (added to remote-dev/home.nix) Drop it from mason-tool-installer's ensure_installed; lspconfig picks it up from PATH. Document the exception in remote-dev/README.md.
* fix(remote-dev): switch python3.11 source from deadsnakes PPA to uvLibravatar sommerfeld2026-05-143-46/+51
| | | | | | | | | | | | The deadsnakes PPA may not be reachable on every VM (corporate apt proxy, Ubuntu derivatives that add-apt-repository misdetects, etc.). `uv python install 3.11` works on any distro: it fetches a portable python-build-standalone CPython into ~/.local/share/uv/python/, which is manylinux-wheel-compatible. Symlink the resulting binary to ~/.local/bin/python3.11 (already on PATH from zprofile). Move the step to after `home-manager switch` since uv comes from the nix profile.
* fix(remote-dev): use deadsnakes python3.11 instead of nix for MasonLibravatar sommerfeld2026-05-143-25/+38
| | | | | | | | | | | | Nix's python rejects manylinux wheels by design (its libc is patched), which forced pip in Mason's per-pkg venvs to compile nodejs-wheel-binaries (pulled in by basedpyright) from source. That source build then failed on Ubuntu 20.04's gcc 9.4 — Node 24 requires C++20 (g++ >= 12.2.0). Replace the nix python311-versioned-only derivation with an Ubuntu-native python3.11 from the deadsnakes PPA. It satisfies Mason's >=3.10 version requirement, accepts manylinux wheels, and the versioned binary name leaves /usr/bin/python3 untouched (leaf-tools policy preserved).
* feat(nvim): wire OSC 52 clipboard provider on SSH sessionsLibravatar sommerfeld2026-05-141-2/+16
| | | | | | | | | | | | | | | Previously `clipboard` was set to empty inside SSH sessions on the assumption no clipboard tool would be reachable. That broke yank → host-clipboard on the remote-dev VM. nvim ≥0.10 ships a built-in OSC 52 provider (vim.ui.clipboard.osc52). The terminal emulator (ghostty locally, zellij forwarding inside it) handles the escape sequence and writes to the host's clipboard, so we get yank-to-host without needing wl-copy/xclip on the VM. Paste over OSC 52 is rarely supported by terminals (security), so we wire it but it's effectively a no-op; bracketed paste from the terminal still delivers clipboard contents into the buffer.
* revert(nvim)+fix(remote-dev): keep Mason authoritative, give it cargo+rustcLibravatar sommerfeld2026-05-142-61/+50
| | | | | | | | | | | | | User policy: Mason should install everything it lists regardless of host-provided versions. Revert the PATH-filtering wrapper around ensure_installed (b2f129e) — back to a plain table literal. For shellharden specifically, Mason's only install source is `cargo install`. The Arch host has cargo via base-devel/rustup; the VM previously didn't, so Mason errored "ENOENT cargo". Add `cargo` and `rustc` to the remote-dev nix profile so Mason can build it on the VM too. Drop the shellharden package from home.nix — Mason owns it now, no more provider competition with the nix-profile binary.
* fix(remote-dev): expose python3.11 (versioned-only) for Mason pip installsLibravatar sommerfeld2026-05-141-1/+12
| | | | | | | | | | | | | | | | | Ubuntu 20.04's stock python3 is 3.8.10, which fails Mason's pep440 checks for autotools-language-server, codespell, mdformat, nginx-language-server, systemdlint, yamllint (all want >=3.9 or >=3.10). Mason's pypi installer (verified against upstream lua/mason-core/installer/managers/pypi.lua) probes python3.6 through python3.14 in PATH in addition to plain python3, so providing python3.11 alone (without python3) is enough. Add a thin runCommand derivation that symlinks ONLY pkgs.python311/bin/python3.11 into the profile — not python3 or python — so we don't shadow Ubuntu's /usr/bin/python3 and keep the leaf-tools policy intact.
* fix(nvim): skip Mason install for tools already on PATHLibravatar sommerfeld2026-05-141-44/+57
| | | | | | | | | | | | | | | Mason's installer tries one source per package. For tools that we already provide via the system package manager (Arch pkgs on the host) or nix-profile (on the remote-dev VM), Mason will keep trying to (re-)install via cargo/pip/etc. and report failures — but conform.nvim/nvim-lint resolve their binary from PATH anyway, so the Mason install is redundant. Filter ensure_installed at startup against vim.fn.executable(). Keeps behaviour identical on a fresh host (Mason still pulls everything), but silences spurious failures for tools that the user has chosen to provide system-wide (shellharden via nix-profile being the immediate case).
* fix(nvim,remote-dev): fall back to PATH node + provide ↵Libravatar sommerfeld2026-05-144-8/+43
| | | | | | | | | | | | | | | | | | | | | | | | | | JRE/shellharden/python3-venv copilot.lua was hard-coding the chezmoi-pinned Node 24 at ~/.local/share/copilot-node/bin/node, which only exists on the Arch host where chezmoi runs run_onchange_after_install-copilot-node.sh. On the remote-dev VM the path is absent, so copilot-language-server spawned with cmd[0]=<missing> and printed 'Could not determine Node.js version'. Probe the pinned path with vim.fn.executable() and fall back to 'node' from PATH otherwise. For the VM PATH 'node' to be a supported version, switch home.nix from the rolling 'nodejs' alias to 'nodejs_24' (the version the chezmoi script also pins on the host). Address the cluster of Mason install failures on the VM: - autotools-language-server, codespell, mdformat, nginx-language-server, systemdlint -- pip-installed; fail because Ubuntu's python3 ships without venv. bootstrap.sh now apt-installs python3-venv; README documents the manual command for existing VMs. - groovy-language-server -- needs a JRE. Add 'jre' to home.packages. - shellharden -- Mason's cargo fallback can't run under our leaf-tools policy. Provide the binary via nix-profile instead so Mason finds it on PATH.
* feat(remote-dev): add justfile with update/pull/switch/gc recipesLibravatar sommerfeld2026-05-142-10/+34
| | | | | | | | | | | | | Wraps the bootstrap-day-2 incantations so you don't have to remember `home-manager switch --impure --flake '.#vm' -b backup` and its zsh quoting gotcha. Recipes: - `just update` — pull + switch (the everyday one) - `just pull` — config-only changes, no nix rebuild - `just switch` — rebuild HM from the current checkout - `just gc` — expire HM generations >7d and gc the nix store README updated to use these.
* fix(zsh): make compdef guard check completion fn, also wire nix-profile fpathLibravatar sommerfeld2026-05-141-8/+19
| | | | | | | | | | | | | | | | | | Previous guard checked `$+commands[Y]` (binary present in PATH), but the `compdef: unknown command or service: Y` message comes from compdef when the *completion function* `_Y` isn't registered — on the remote-dev VM `systemctl`, `just`, `lsd` are all on PATH yet zsh has no `_systemctl` because Ubuntu's system zsh doesn't include nix-profile's share/zsh/site-functions in fpath. Two-part fix: 1. Prepend $HOME/.nix-profile/share/zsh/{site-functions,vendor-completions} to fpath (when they exist) before compinit, so the completions get loaded on the VM the same way they do on Arch. 2. Switch the compdef guard to `$+_comps[Y]` — the assoc-array compinit actually populates with every command that has a registered completion handler. Still belt-and-suspenders in case something ships a binary without a matching completion file.
* fix(remote-dev): whitelist claude-code/copilot-cli unfreeLibravatar sommerfeld2026-05-141-1/+11
| | | | | | | | The flake set `allowUnfree = false` so `home-manager switch` failed with "Refusing to evaluate package 'claude-code-...' because it has an unfree license". Switch to `allowUnfreePredicate` with an explicit name allowlist — keeps the door closed for everything else while permitting just the two AI agents we actually want.
* docs(remote-dev): quote flake ref so zsh extendedglob doesn't chokeLibravatar sommerfeld2026-05-141-1/+5
| | | | | | `home-manager switch --flake .#vm` fails under our zsh (which sets `extendedglob`) because `#` then becomes a glob qualifier and `.#vm` parses as an unmatched pattern. Quoting the ref sidesteps it.
* feat(remote-dev): add just to the nix profileLibravatar sommerfeld2026-05-141-0/+1
| | | | | So the dotfiles `justfile` (and any in-tree project justfiles the user checks out on the VM) work without falling back to make/scripts.
* fix(zsh): guard compdef on target command being installedLibravatar sommerfeld2026-05-141-5/+11
| | | | | | | | | | | | | | On minimal hosts (remote-dev VM, fresh container) several of the `compdef alias=target` lines fail at login with messages like: compdef: unknown command or service: just compdef: unknown command or service: systemctl compdef: unknown command or service: lsd — because zsh has no `_just`/`_systemctl`/`_lsd` completion function loaded when the binary isn't on the system. Wrap each call in a small helper that checks $commands[<target>] first so absent tools just silently skip their alias completion instead of spamming the prompt.
* feat: add another work includeIfLibravatar sommerfeld2026-05-141-0/+2
|
* refactor(zsh): stop renaming zellij tabs from the shellLibravatar sommerfeld2026-05-141-9/+7
| | | | | | | | | | | | | | | | | | | The hand-rolled `N:dir:cmd` tab labels could never stay in sync: - After session resurrection, tab names are restored from disk but no shell-visible event fires, so labels stayed stale until the user hit Enter to trigger precmd. - After closing a middle tab, zellij renumbers surviving tabs but again emits no per-pane event, so the `N:` prefix on every tab to the right silently became wrong. - Once a tab has a custom name, zellij's tab-bar plugin uses it verbatim — there's no way to keep the default `Tab #N` numbering while also injecting dir/cmd info. The only plugin that addresses this (vmaerten/ zellij-tab-rename) requires zellij built from main. Dropping the hooks restores zellij's built-in `Tab #N`, which is the single label that stays correct across resurrect and renumber. The zsh prompt already shows CWD inside the pane.
* feat(sway): bspwm-style workspace back-and-forth toggleLibravatar sommerfeld2026-05-142-0/+5
| | | | | | workspace_auto_back_and_forth yes makes `workspace number N` jump back to the previously focused workspace when N is already current. Applies to both $mod+N keybinds and waybar workspace clicks.
* feat(waybar): snx-rs VPN status indicator + click toggleLibravatar sommerfeld2026-05-143-0/+57
| | | | | | | | | | | New custom/snx-vpn module sits next to custom/vpn (the wireguard one): - snx-vpn-status.sh shells out to `snxctl status` (timeout 2s) and maps the output to three states: down (grey strikethrough), connecting/MFA (amber), up (green). Tooltip shows the full status block when up. - snx-vpn-toggle.sh disconnects when up, runs snxctl-chromium detached when down (so SAML lands in the flatpak ungoogled-chromium without blocking waybar). Both paths refresh the module via SIGRTMIN+9.
* refactor(snxctl-chromium): drop daemon drop-in, override snxctl's PATHLibravatar sommerfeld2026-05-143-42/+15
| | | | | | | | | | | | snx-rs.service is a system unit, not --user, so the prior approach of overriding the daemon's PATH via a systemd drop-in could never apply. And it wasn't needed anyway: snxctl itself runs opener::open(url) in-process, so prepending the shim dir to snxctl's PATH is enough. - Drop dot_config/systemd/user/snx-rs.service.d/10-chromium-saml.conf. - snxctl-chromium now just sets PATH and exec's snxctl connect. - xdg-open shim no longer forces --new-window so chromium can reuse a warm window (faster SAML round-trip).
* feat(sway): fuzzy search in power menuLibravatar sommerfeld2026-05-141-1/+2
| | | | | Drop --hide-search and enable --matching=fuzzy --insensitive so typing 'po' jumps to Poweroff, 'su' to Suspend, etc.