aboutsummaryrefslogtreecommitdiffstatshomepage
Commit message (Collapse)AuthorAgeFilesLines
...
* feat(nix): audit + expand vm xdg.configFile symlink coverageLibravatar sommerfeld9 days1-1/+38
| | | | | | | | | | | | | | | | | | The VM doesn't run chezmoi, so every config the host gets via chezmoi must reach the VM via a nix symlink. Audit found gaps for tools whose binary IS in common.nix but whose dot_config tree was unlinked: bat, lsd, yazi, ripgrep, fd, wget, npm, ipython, gdb, clangd, ccache Plus the new tuicr claude-code skill (under ~/.claude/skills/tuicr/, NOT ~/.config — uses home.file instead of xdg.configFile). Reorganises the block by category and adds an INVARIANT comment pointing at the rule in .github/copilot-instructions.md. GUI/wayland-only tools (sway/mako/waybar/fuzzel/mpv/zathura/etc) stay unlinked: the VM is headless.
* feat(claude): add tuicr skill (zellij-adapted)Libravatar sommerfeld9 days2-0/+212
| | | | | | | | | | | | | Adapts upstream agavra/tuicr's tmux-based wrapper to zellij: - Detects $ZELLIJ instead of $TMUX - Spawns child via 'zellij action new-pane --floating' (or --direction with TUICR_PANE_MODE=split / TUICR_SPLIT_DIR=down) - Replaces tmux 'wait-for' with a mkfifo / printf done sentinel - Uses 'pgrep -x tuicr' for the cross-pane already-running probe (zellij has no list-panes equivalent) SKILL.md updated for zellij keybinds and a nix install path note.
* feat(nix): add tuicr from upstream flake to common profileLibravatar sommerfeld9 days2-1/+15
| | | | | | tuicr (TUI git-change reviewer) isn't packaged in nixpkgs, so pull it as a flake input with an overlay exposing pkgs.tuicr. The companion claude-code skill lives in dot_claude/skills/tuicr/ (separate commit).
* fix(just): chsh to nix-managed zsh after nix-switchLibravatar sommerfeld9 days1-0/+14
| | | | | | | | | | | | | | zsh now lives in nix/common.nix instead of meta/base.txt. Removing the pacman zsh package leaves /etc/passwd dangling at /usr/bin/zsh, so new login terminals die with 'shell not found'. Mirror the chsh logic from nix/bootstrap.sh (which only runs on the VM during first-time provisioning) into the nix-switch recipe so every `just sync` / `just init` re-asserts the login shell — and the host gets the same treatment as the VM. Idempotent: skips when the shell already matches, skips when ~/.nix-profile/bin/zsh is missing (pre-bootstrap state).
* refactor(pkg): drop provider-resolution fallback in mark_explicitLibravatar sommerfeld9 days1-9/+4
| | | | | | | | | Now that meta/*.txt is conventionally required to list installed package names (not virtual providers — see preceding commit dropping ttf-font-awesome in favour of the already-declared otf-font-awesome), the intersection with pacman -Qq is unnecessary. Failing loudly on a virtual-provider entry is actually useful: it surfaces a data-entry mistake instead of silently masking it.
* chore(pkg): drop redundant ttf-font-awesome from base.txtLibravatar sommerfeld9 days1-1/+0
| | | | | | | ttf-font-awesome is a virtual provided by otf-font-awesome (already declared on the line above) — paru resolves the former to the latter, so listing both adds nothing and confuses the mark-explicit step in pkg-apply.
* fix(pkg): skip mark-explicit for packages resolved to a different providerLibravatar sommerfeld9 days1-1/+9
| | | | | | | | | | paru may resolve a declared name to a provider with a different package name (e.g. ttf-font-awesome -> otf-font-awesome). Calling `pacman -D --asexplicit` on the declared name then fails with 'could not find or read package' and aborts the recipe. Intersect the declared list with `pacman -Qq` before bumping reasons; names not present in the local DB are silently skipped.
* fix(pkg): mark declared packages as explicit on applyLibravatar sommerfeld9 days1-2/+16
| | | | | | | | | | | | | | | `paru -S --needed` skips packages already on disk, so anything pulled in transitively first and *later* added to meta/*.txt stays marked as 'installed as a dependency' in the local pacman DB — and keeps showing up under `pacopt`. After each install pass, force the declared set to 'explicitly installed' via `pacman -D --asexplicit`. This treats meta/*.txt as the source of truth for install reason: anything listed there is explicit, anything else is a transitive dep. Idempotent on already-explicit packages (pacman just prints 'install reason is already explicit', which we discard).
* feat(pkg): declare btrfs-progs in base.txtLibravatar sommerfeld9 days2-6/+7
| | | | | | | | Root filesystem is btrfs; the userspace tools are needed for routine maintenance (scrub, balance, subvolume management) and inspection (`btrfs filesystem usage` — the only honest reporter on btrfs since plain `df` doesn't account for metadata/profiles/unallocated). Also used by the mkinitcpio btrfs hook at boot.
* feat(nix): add ipython to common profileLibravatar sommerfeld9 days1-0/+1
| | | | | | Interactive python REPL. Uses python3Packages.ipython so only the `ipython` binary lands on PATH — no stray system `python`/`python3`, preserving the 'tools managed by uv per-project' policy in common.nix.
* feat(pkg): declare linux + dosfstools in base.txtLibravatar sommerfeld9 days1-0/+2
| | | | | | | | | linux: previously installed only as an Optional Dep of base. Promote to an explicit declaration so it stops showing up under pacopt. dosfstools: required by udisks2 (and libblockdev-fs) for mounting FAT volumes — USB sticks, the EFI system partition, etc. Universally useful on any desktop install.
* feat(zsh): enrich pacopt with reverse-optdep infoLibravatar sommerfeld9 days1-1/+35
| | | | | | | | | | | Promote pacopt from a plain alias to a function. In addition to listing packages that remain installed solely as someone's optional dependency, each package is now annotated with its parent(s) and the upstream reason text from the parent's Optional Deps field. Implementation is pacman-only (no expac): one awk pass over 'pacman -Qi' builds a reverse index of every (parent, optdep, reason) edge in the local DB, then per leaf package the index is filtered for matching deps.
* feat(nix): silence home-manager news notificationsLibravatar sommerfeld9 days1-0/+3
| | | | Stops the 'X news items unread' banner on every home-manager switch.
* perf(git): disable delta hyperlinksLibravatar sommerfeld9 days1-1/+1
| | | | | | | | Delta's hyperlink resolution shells out to git rev-parse for every blob to build clickable file links, which is fine on bare metal but death-by-fork on a slow VM — 'git diff' could take many seconds while 'git diff | cat' returns instantly. Turn hyperlinks off; we get clickable nothing but visible-everything-fast diffs.
* fix(systemd): pin PASSWORD_STORE_DIR for pass-secret-serviceLibravatar sommerfeld9 days1-0/+2
| | | | | | | | | | | Mirror the drop-in already in place for protonmail-bridge. The default ~/.password-store doesn't exist on this system (store lives under $XDG_DATA_HOME); without this, pass-secret-service throws PassNotInitialized when the service is started outside a context that already exported PASSWORD_STORE_DIR (e.g. D-Bus activation before sway has imported env). That cascades into protonmail-bridge failing to persist its IMAP creds and Thunderbird seeing ephemeral passwords with 'no such user' errors.
* refactor(zsh): drop FIRECRAWL_API_KEY exportLibravatar sommerfeld11 days1-4/+0
| | | | | | Unused; the pass entry doesn't exist on most machines, so login emitted 'Error: copilot/firecrawl-api-key is not in the password store' on every shell start. Easier to drop than to gate.
* style(justfile): apply just --fmt (blank line between nix-update doc comments)Libravatar sommerfeld11 days1-0/+1
| | | | | | Just's formatter inserts a blank line so only the immediately-adjacent comment serves as the recipe's doc string. Pre-existing drift, surfaced when CI added 'just check-fmt' to the pipeline.
* fix(waybar): refactor A && B || C patterns to avoid shellcheck SC2015Libravatar sommerfeld11 days3-3/+4
| | | | | | | | Older shellcheck (Ubuntu's in CI) flags '[ test ] && cmd || true' as SC2015 because, despite the intent, A && B || C is not equivalent to if-then-else (C runs when A is true but B fails). Replace with explicit 'if … fi' or split into two 'A || continue' guards. Functionally identical, lint-clean across versions.
* ci: install basedpyright so just doctor passesLibravatar sommerfeld11 days1-0/+3
| | | | | | | The doctor recipe checks for basedpyright (used by 'just lint' for Python type-checking), but the CI workflow wasn't installing it, causing every run since the recipe was added to fail at the doctor step. Install it via pipx like ruff.
* zsh: hm wrapper needs --impure for builtins.getEnvLibravatar sommerfeld11 days1-1/+1
| | | | | | host.nix reads HOME/USER via builtins.getEnv, which returns "" under pure-eval (nix run's default). just-nix-switch already passes --impure; match it here.
* zsh: add hm wrapper for flake-based home-managerLibravatar sommerfeld11 days1-0/+12
| | | | | | | | | | | | The standalone 'home-manager' command defaults to the legacy ~/.config/home-manager/home.nix and errors out for flake users. The wrapper auto-selects the host/vm profile by /etc/os-release ID and points at whichever dotfiles checkout exists on the machine. Usage: hm news hm switch hm generations
* meta: declare bolt (Thunderbolt dock daemon)Libravatar sommerfeld11 days1-0/+3
|
* justfile: add nix-update recipe, wire into updateLibravatar sommerfeld11 days1-2/+15
| | | | | | Refreshes flake.lock (nixpkgs + home-manager) and re-activates the profile. Plugged into the existing 'just update' aggregate so a weekly 'just update' bumps pacman/AUR + flatpak + nix in one go.
* nix: re-add github-copilot-cli (now prebuilt-binary derivation)Libravatar sommerfeld11 days1-5/+1
| | | | | | | Upstream rewrote the derivation in 1.0.43+ to fetch a prebuilt binary from the copilot-cli releases (autoPatchelf + makeBinaryWrapper) instead of buildNpmPackage, sidestepping the /var/empty/.cache EACCES that blocked 1.0.40.
* drop residual Mason references after p6 migrationLibravatar sommerfeld11 days3-6/+4
| | | | | - zsh: remove ~/.local/share/nvim/mason/bin from PATH - justfile: update comments to reflect Mason removal
* nix: add codex; meta: virt-viewer to work.txtLibravatar sommerfeld11 days2-10/+2
|
* refactor(nix): deployment in vm.nix only; host uses chezmoi for dotfilesLibravatar sommerfeld11 days3-82/+68
| | | | | | | | | | | | | | | | | | | | | | | | | | Per user decision: on the Arch host, chezmoi remains the single deployer of $HOME dotfiles. nix/common.nix's xdg.configFile + sshConfig activation + .zshenv home.file block was causing home-manager to fight chezmoi on every nix-switch, materializing .backup files for nvim, zellij, zsh, git, ghostty, direnv. Resolution: - nix/common.nix: drop the entire deployment block, drop the my.dotfilesPath option, drop the let..in dotfiles/link helpers. Module is now deployment-agnostic: only installs packages. - nix/host.nix: drop my.dotfilesPath; explicit comment that chezmoi owns dotfile deployment on the host. - nix/vm.nix: gains everything previously in common.nix's deployment block — xdg.configFile (nvim/zellij/zsh/git/ghostty/direnv), home.activation.sshConfig, home.file.".zshenv". The 'dotfiles' let-binding (= $HOME/.local/share/dotfiles) and 'link' helper move here too, since they're vm-only now. Host runbook unchanged (`just sync`); first run after pulling will just be a no-op nix-switch instead of a backup-file storm.
* fix(nix): parameterize dotfiles path per profile; rename dockerfile LSPLibravatar sommerfeld11 days3-2/+26
| | | | | | | | | | | | | | | | | | | | - common.nix hardcoded the runtime dotfiles checkout to ~/.local/share/dotfiles, which is correct for the remote-dev VM but not the Arch host (where the canonical clone lives at ~/dotfiles). ssh activation was failing with 'cannot stat /home/sommerfeld/.local/share/dotfiles/private_dot_ssh/config' on every host nix-switch. Promote the path to a typed option (config.my.dotfilesPath) and set it from each profile: nix/host.nix -> $HOME/dotfiles nix/vm.nix -> $HOME/.local/share/dotfiles common.nix now wraps its config in 'config = { ... }' so the options can sit alongside. - dockerfile-language-server-nodejs was renamed in nixpkgs to dockerfile-language-server; pick up the new name to silence the evaluation warning (the rename will eventually become a hard error).
* fix(nix,nvim): drop nodePackages.* (removed from nixpkgs), drop ↵Libravatar sommerfeld11 days2-5/+7
| | | | | | | | | | | | | | | | | | | github-copilot-cli (broken) nodePackages was removed wholesale from nixpkgs; everything that lived under it must be referenced via its top-level name or dropped. - prettier: moved nodePackages.prettier -> prettier (top-level alias). - jsonlint: not available at top level. Dropped from nix/common.nix AND from the nvim-lint and conform-nvim configs in dot_config/nvim/lua/plugins/lsp.lua. jsonls already provides schema-aware diagnostics; jq still handles formatting. The jsonlint redundancy is acceptable to lose. - github-copilot-cli (1.0.40 in nixpkgs): buildNpmPackage derivation doesn't redirect HOME during npm postinstall, so it fails with EACCES on /var/empty/.cache on Determinate nix. Removed; install manually from https://github.com/github/copilot-cli into /usr/local/bin/ as before (current host already has it there).
* fix(nix,nvim): drop gh-actions-language-server (not in nixpkgs); export USER ↵Libravatar sommerfeld11 days3-2/+4
| | | | | | | | | | | | | | in nix-switch - gh-actions-language-server is an npm package (lttb/gh-actions-language-server) not packaged in nixpkgs. Removed from nix/common.nix and from the vim.lsp.enable list in dot_config/nvim/lua/plugins/lsp.lua. Restore later via a per-project flake.nix if working on a workflows-heavy repo. - just runs recipes with a sanitized env where $USER may be unset; home-manager's activation script dereferences it unconditionally and fails with 'USER: unbound variable'. Export USER (and HOME for symmetry) at the top of the nix-switch recipe.
* feat(pkg,nix): migrate build orchestrators + debuggers to nix; drop toolchainsLibravatar sommerfeld11 days2-31/+39
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Migrated to Home-Manager (nix/common.nix): cmake, ninja, ccache, sccache (build orchestrators — they only delegate to whatever compiler is on PATH, don't ship one themselves, so no ABI shadowing risk) valgrind (instruments at syscall/library boundary; works fine with pacman-built target binaries) doxygen (source-only documentation tool; was accidentally dropped in the previous sweep — restored here) Dropped entirely (per-project flake.nix + direnv .envrc instead): clang, lld, mold, rustup, npm Rationale: these are language/toolchain-specific compilers and linkers; when a project needs them, the project's own flake provides the version it wants, pinned in flake.lock. base-devel still ships gcc/ld/as/make for general-purpose system builds and one-offs. npm is also dropped from pacman; nodejs_24 in nix/common.nix already ships npm for the editor/AI-agent path. Project-side npm comes via per-project flake when needed. Updated nix/common.nix policy comment to match: only ban the actual compilers/linkers (cc/gcc/clang/ld) and forbidden runtimes (cargo, rustc, go, python3) — build orchestrators and instrumentation tools are explicitly allowed. The --- dev --- section in base.txt is now just perf and podman-* (kernel-coupled / system-runtime-coupled).
* feat(pkg,nix): migrate 14 leaf tools to nix; drop 6 unused packagesLibravatar sommerfeld11 days2-37/+37
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Migrated to Home-Manager (nix/common.nix): duf, gdu, nmap, procs, yazi, difftastic, direnv (was duplicated), git-absorb, samply, strace, t-rec, act, pandoc, gdb, lldb lldb stays nix-only (no longer in base.txt) — per user policy, only ever used to debug own builds, so glibc/kernel ABI skew vs the pacman-built system isn't a concern. Same logic could extend to valgrind, but valgrind has tighter glibc compat needs; perf links against kernel ABI and must match the running kernel. Both stay pacman. uv was already in nix; removed pacman duplicate. Kept on pacman (cannot migrate without breaking system builds, per nix/common.nix policy that bans compilers/linkers/build systems on PATH): ccache, clang, cmake, lld, mold, ninja, npm, rustup, sccache, podman-compose, podman-docker (system runtime integration), perf, valgrind (kernel/glibc-coupled), unzip (transitive via base), doxygen (huge nixpkgs closure not worth it). Dropped entirely (unused): android-tools, go, gpg-tui, luarocks (was for Mason-managed nvim plugin deps; Mason is gone), bash-completion (zsh-only setup), pandoc-bin (replaced by nix pandoc). jdk21-openjdk kept — still needed for the groovy/jenkins toolchain paths in nvim. Rewrote the --- dev --- section comment to explain the policy.
* fix(bootstrap): use pacman nix instead of curl installerLibravatar sommerfeld11 days1-17/+16
| | | | | | | | | | | | | | | | Pacman's 'nix' package is already in meta/base.txt and provides the same multi-user daemon setup (nix-daemon.socket already enabled via systemd-units/system.txt; flakes already enabled via /etc/nix/nix.conf from etc/). The curl-piped Determinate installer was adding nothing on top — and on a host where pacman already installed nix, it would create two competing nix binaries. Changes: - Add 'nix' to PREREQS so pacman installs it alongside the other prerequisites, before 'just init' runs. - Drop the curl install block. - Source /etc/profile.d/nix.sh (or nix-daemon.sh) before 'just init' so the nix-switch step inside 'just init' finds the binary in PATH.
* feat(pkg,nix): migrate pass-otp/zsh-completions/wget/gnupg to nix; drop curlLibravatar sommerfeld11 days2-11/+10
| | | | | | | | | | | | | | | | | | | | | | Cleanup pass following p7 review: - pass-otp: wired via pass.withExtensions in nix/common.nix (`pass otp ...` works against the same store). - zsh-completions: added as a separate package next to zsh + plugins (fpath picks it up via HM's nix-profile share/). - wget: already in nix/common.nix; removed pacman duplicate. - gnupg: already in nix/common.nix; removed pacman entry. pcscd still comes from pacman pcsclite (system service needs root + hardware access), nix gnupg's scdaemon dials it via /run/pcscd/pcscd.comm. - curl: removed; pulled transitively by base, base-devel, paru and many others. Kept on pacman: - pcsclite, ccid : pcscd is a system daemon; libs needed by HM scdaemon - man-db, man-pages : distro-specific - base, base-devel : meta-packages - pass-secret-service-bin : AUR-only
* feat(bootstrap): install nix + Home-Manager on Arch host (p8)Libravatar sommerfeld11 days2-4/+55
| | | | | | | | | | | | | | | | | Append two steps to the root bootstrap.sh: 5a. install nix via the Determinate Systems multi-user installer (same as remote-dev/nix; gives us a proper nix-daemon.service). 5b. chsh to ~/.nix-profile/bin/zsh after appending to /etc/shells. Add a 'just nix-switch' recipe that auto-picks the host vs vm profile based on /etc/os-release ID, and wire it into 'just init' and 'just sync' so day-to-day reconciliation also re-applies Home-Manager. The recipe is a no-op when nix isn't installed, so it stays safe for pre-bootstrap states and for hosts where the user opts out. Phase 8 of the nix-on-host migration plan.
* feat(pkg): drop leaf tools migrated to Home-ManagerLibravatar sommerfeld11 days2-35/+12
| | | | | | | | | | | | | | | | | | | | | | | | | | The following are now provisioned by Home-Manager via nix/common.nix and live under ~/.nix-profile/bin (which is first in PATH per phase p3): ripgrep, fd, bat, glow, fzf, lsd, jq, yq (yq-go), zoxide, just, sd, choose, dog, curlie, hyperfine, htop, fastfetch, tldr, rsync, mergiraf, git-delta (delta), tree-sitter-cli (tree-sitter), neovim, zellij, github-cli (gh), pass, openssh, git, zsh, zsh-syntax-highlighting, zsh-autosuggestions, zsh-history-substring-search, basedpyright-bin (basedpyright), rust-analyzer Kept: - pass-otp, zsh-completions: no Home-Manager equivalent yet - pcsclite: still needed by Home-Manager gnupg/scdaemon (see nix/host.nix scdaemon.conf) - curl, wget, man-db, man-pages, gnupg: system-fundamental, fine to keep duplicated. git/openssh/gnupg also come back as transitive deps of paru/sudo/etc. even if dropped here. Added hyperfine to nix/common.nix (missed in the p5 batch). Phase 7 of the nix-on-host migration plan.
* refactor(nvim,zsh): remove Mason; use Home-Manager-provisioned toolingLibravatar sommerfeld11 days6-126/+40
| | | | | | | | | | | | | | | | | | | | | | | | | LSPs, formatters, linters, and the lldb-dap debugger now come from ~/.nix-profile/bin (see nix/common.nix). lspconfig keeps the default configs; we just opt-in via vim.lsp.enable() with an explicit list. Changes: - dot_config/nvim/lua/plugins/lsp.lua: drop mason*, replace mason-lspconfig handler with explicit vim.lsp.enable({...}); drop groovy/jenkins formatters and lint entries; drop systemd lint (nginx + groovy + systemdlint tools dropped per plan). - dot_config/nvim/lua/plugins/debug.lua: drop mason-nvim-dap; drop codelldb adapter; switch dap.configurations.cpp to type='lldb' (lldb-dap is the upstream successor, ships with pkgs.lldb). - dot_config/nvim/init.lua: remove mason.nvim, mason-lspconfig.nvim, mason-tool-installer.nvim, mason-nvim-dap.nvim from vim.pack.add. - dot_config/nvim/lua/config/update.lua: remove MasonToolsUpdateSync. - dot_config/zsh/dot_zshrc: flip plugin source order — prefer ~/.nix-profile/share, fall back to /usr/share/zsh (was the other way around). - nix/bootstrap.sh: drop the uv-python3.11 step (no longer needed once Mason no longer source-builds Python LSPs on Ubuntu 20.04). Phase 6 of the nix-on-host migration plan.
* 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.