aboutsummaryrefslogtreecommitdiffstatshomepage
Commit message (Collapse)AuthorAgeFilesLines
* feat(git): user-level hooks auto-dispatch into <repo>/.githooks/Libravatar sommerfeld13 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 sommerfeld13 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 sommerfeld13 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 sommerfeld13 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 sommerfeld13 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 sommerfeld13 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 sommerfeld13 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 sommerfeld13 days1-6/+0
| | | | This reverts commit 1d7feb8d405e135dc6109052948b8b9240cf882a.
* fix(paru): pin llama-cpp-vulkan via IgnoreDevelLibravatar sommerfeld13 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 sommerfeld13 days1-14/+3
| | | | This reverts commit eb0f9d71ed9527b5de5c82c9acce7c04bbec71e7.
* fix(just): honor IgnorePkg in pkg-apply / pkg-fixLibravatar sommerfeld13 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 sommerfeld13 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 sommerfeld13 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 sommerfeld13 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 sommerfeld13 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 sommerfeld13 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 sommerfeld13 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 sommerfeld13 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.
* feat(sway): Super+o types VPN TOTP via wtypeLibravatar sommerfeld2026-05-143-0/+27
| | | | | | | Fetches the current code from pass-otp's vpn/totp entry and types it into the focused surface with wtype. Falls back to wl-copy + a notification when wtype isn't available or the focused surface lacks virtual-keyboard support (e.g. an Xwayland window).
* feat(pkg): add pass-otp for TOTP storageLibravatar sommerfeld2026-05-141-0/+1
| | | | | Enables `pass otp insert/show` for TOTP secrets, used as the source for the ungoogled-chromium VPN OTP autofill keybind.
* chore(gnupg): authorize new auth subkey for sshLibravatar sommerfeld2026-05-141-0/+1
|
* feat(git): add resign aliasLibravatar sommerfeld2026-05-141-0/+1
| | | | | | | Rebases onto @{u} re-signing each commit with the current author identity and key, while stripping any Co-authored-by lines. Hooks are disabled (core.hooksPath=/dev/null) so chezmoi's post-commit hook doesn't fire once per replayed commit.
* feat(teams): start units minimized to trayLibravatar sommerfeld2026-05-142-2/+4
| | | | | | teams-for-linux --minimized=true makes the app honor systemd autostart without popping a window on every login (parity with Signal's --start-in-tray).
* feat: teams autostart, llama-cpp-vulkan ignore, snxctl-chromium wrapperLibravatar sommerfeld2026-05-148-9/+127
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | systemd/user/teams-{sii,xsight}.service: autostart both Teams flatpak profiles on sway-session.target login. KillMode=mixed so SIGTERM hits only the wrapper process — both instances share the same flatpak app id, so killing by app id would take down the sibling instance. A 15s SIGKILL fallback covers the case where Electron tray-hides instead of quitting. Both units listed in systemd-units/user.txt. etc/pacman.conf: IgnorePkg = llama-cpp-vulkan. The AUR package rebuilds on every llama.cpp commit (multi-hour build). Update manually with `paru -S llama-cpp-vulkan` when intended. snxctl-chromium wrapper: - dot_local/share/snx-rs/bin/xdg-open: shim that flatpak-runs ungoogled-chromium, used only by snx-rs. - dot_config/systemd/user/snx-rs.service.d/10-chromium-saml.conf: drop-in prepending that dir to the daemon's PATH so snx-rs's opener-crate call to xdg-open lands in chromium, without affecting xdg-open for any other process. - dot_local/bin/snxctl-chromium: convenience wrapper that daemon-reloads and restarts snx-rs.service if the drop-in isn't yet applied, then execs `snxctl connect`. firefox/user-overrides.js: revert the dom.security.https_only_mode. upgrade_local and network.lna.local-network-to-localhost.skip-checks prefs — they didn't actually fix the SAML flow. Replaced with a comment pointing to the wrapper instead.
* style: apply shfmt/prettier/just fmt driftLibravatar sommerfeld2026-05-148-55/+70
| | | | | | Pure formatter output from shfmt (2-space indent, '|' line breaks), prettier (KEYBINDS.md), and 'just fmt' (justfile blank line). No behavior change.
* feat(remote-dev): add zoxide/clang-tools/node/uv/AI agents; bring git+ssh; ↵Libravatar sommerfeld2026-05-144-21/+133
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | SSH-format signing home.nix: - Add zoxide (fixes 'command not found' on shell start), clang-tools (no compiler driver), nodejs (Mason npm LSPs), uv (Mason python LSPs; does not install python3 in PATH, so Ubuntu's /usr/bin/python3 stays the system default), claude-code, github-copilot-cli. - Refine the leaf-tools policy comment: explicit denylist of build- toolchain binaries that would shadow Ubuntu's via PATH, plus a carve-out for editor/AI runtimes (node, uv, clang-tools). - Symlink ~/.config/git/{config,attributes,ignore} and ~/.ssh/config from the dotfiles tree. dot_config/zsh/dot_zshrc: guard direnv/zoxide/fzf inits with 'command -v X >/dev/null &&' so a fresh machine without one of them no longer prints a stderr error on every shell start. dot_config/git/config: append unconditional '[include] path = ~/.config/git/config.local' for machine-local overrides (used on the remote-dev VM to switch to SSH-format signing via the forwarded agent). Git silently skips missing include files. remote-dev/README.md: document the update flow (config-only vs HM rebuild), the single-shell leaf-tools policy, and the one-time VM setup for SSH-format commit signing (allowed_signers + config.local, ForwardAgent yes on the host).
* refactor(notifications): drop dismissed-state machinery; pending = visibleLibravatar sommerfeld2026-05-138-194/+34
| | | | | | | | | | | | | | | | | Set mako default-timeout=0 so notifications stay until acted upon. With auto-timeout off, mako's list IS the pending set, so the $XDG_RUNTIME_DIR/mako-dismissed bridge becomes dead weight. - mako/config: default-timeout=0; drop redundant [urgency=critical] default-timeout=0 override. - Delete dismiss-visible.sh and restore-pending.sh; sway calls makoctl directly (Mod+n=dismiss, Mod+Shift+n=dismiss --all, Mod+Ctrl+n=restore as undo). - Shrink mako-status.sh to a 20-line counter of makoctl list. - Rename mako-history.py -> notification-picker.py; lists only visible, dismisses via makoctl dismiss -n <id>. - Update waybar config.jsonc on-click path. - Update KEYBINDS.md wording (no more 'marks seen' / 'pending set').