| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Both org.mozilla.thunderbird and io.mpv.Mpv are already installed via
flatpak, but several places still launched the system binaries (because
they were in PATH). Worse, `mpv` was kept on the host *only* for the
streamlink-launches-mpv path, and `thunderbird` was being pulled in as
a hard dep of external-editor-revived even though it was never the
mailer actually used. Untangle both.
Thunderbird
-----------
* dot_config/sway/executable_tb-toggle.sh,
dot_config/sway/executable_tb-autostart.sh:
swap `thunderbird` → `flatpak run org.mozilla.thunderbird`. The
`app_id` matcher in sway config already targets the flatpak id, so
the scratchpad-stash and Super+t toggle keep working unchanged.
* etc/pacman.conf:
add `AssumeInstalled = thunderbird=999.0-1`. external-editor-revived
(AUR) hard-depends on `thunderbird`; this satisfies the dep without
installing the package. Run `sudo pacman -Rns thunderbird` after
deploy to remove the now-unneeded system binary.
* meta/base.txt: document the AssumeInstalled trick next to the
external-editor-revived entry.
mpv
---
* dot_config/streamlink/config: `player=mpv` → `player=flatpak run
io.mpv.Mpv`. The flatpak already pulls in our ~/.config/mpv via the
read-only filesystem override (see
run_onchange_after_deploy-flatpak-overrides.sh.tmpl), so behavior is
unchanged.
* dot_local/bin/executable_linkhandler: same swap for inline video URLs.
* dot_local/bin/executable_mpv: deleted. The wrapper only existed to
bwrap /usr/bin/mpv into _sandbox-net-parser; flatpak's own sandbox
supersedes that.
* dot_local/bin/executable__sandbox-net-parser,
dot_local/bin/executable_streamlink: comment refresh — mpv is no
longer one of the tools this wraps, and the streamlink wrapper now
forwards to the flatpak player rather than nested-bwrap caveats.
* meta/base.txt: drop `mpv` from the host package list and update the
surrounding comment.
README.md: refresh the media row of the stack table to match.
On-host steps:
chezmoi apply -v
sudo pacman -Syu # picks up AssumeInstalled
sudo pacman -Rns thunderbird mpv # safe now
flatpak install -y flathub org.mozilla.thunderbird io.mpv.Mpv
swaymsg reload # pick up new tb scripts
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Upstream marked org.mozilla.Thunderbird end-of-life. Flathub split it
into two replacement IDs:
org.mozilla.thunderbird monthly release channel (new default)
org.mozilla.thunderbird_esr ESR / long-term-support channel
Move to the lowercase monthly-release flatpak, which is what Mozilla
now recommends for regular desktop users and gets features at the same
cadence as Firefox.
Renamed references in:
* meta/flatpak.txt - the package list the user installs from
* meta/base.txt - comment in the mail-bits section
* dot_config/sway/config - window-match app_id rule for marking
* dot_config/mimeapps.list - mailto/ics/webcal handler .desktop names
* run_onchange_after_deploy-thunderbird.sh.tmpl - profile path under
~/.var/app/<id>/.thunderbird/
* run_onchange_after_deploy-tb-eer.sh.tmpl - flatpak override target
and sandbox path for External Editor Revived bridge
* run_onchange_after_deploy-pteid-pkcs11.sh.tmpl - Mozilla-family
flatpak NSS DB registration list
* README.md - doc snippets and xdg-mime example
On-host migration:
flatpak install -y flathub org.mozilla.thunderbird
# Preserve accounts, OpenPGP keys, calendars, EER bridge wrapper:
mv ~/.var/app/org.mozilla.Thunderbird ~/.var/app/org.mozilla.thunderbird
flatpak uninstall -y org.mozilla.Thunderbird
chezmoi apply -v
update-desktop-database ~/.local/share/applications 2>/dev/null || true
Verify mail handler:
xdg-mime query default x-scheme-handler/mailto
# -> org.mozilla.thunderbird.desktop
|
| |
|
|
|
|
|
|
|
|
|
| |
Same rationale as the previous commit: the new policy is "if you don't
want the machine to sleep, plug it in." An SSH-only inhibit in zprofile
is redundant on AC (logind already ignores the lid) and inconsistent on
battery (it would hold the lock for an SSH-attached idle session,
defeating the schedule).
Also removes a stale doc reference to zellij-inhibit-suspend.path which
no longer exists.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
New, simpler suspend policy:
AC plugged in -> never auto-suspends (lid close ignored, idle no-op)
On battery only -> lid close suspends, swayidle suspends at 30 min idle
This replaces the SSH/zellij-aware inhibit machinery with a rule that
matches the user's mental model: if you don't want the machine to
sleep, plug it in. Long-running tasks (builds, downloads, SSH
sessions, headless services) just need AC.
Changes:
* etc/systemd/logind.conf.d/20-lid-ac.conf: set
HandleLidSwitchExternalPower=ignore so logind itself handles the AC
case at the source. No userspace daemon, no race, no rate-limit risk.
* dot_local/bin/on-battery-suspend: tiny POSIX wrapper that exits 0
when any /sys/class/power_supply/{AC,ADP}*/online == 1, else execs
`systemctl suspend`.
* dot_config/systemd/user/swayidle.service: add
`timeout 1800 on-battery-suspend`. Idle suspend now exists, but only
when on battery.
* Delete zellij-inhibit-suspend.{path,service} + watcher script and
remove the entry from systemd-units/user.txt. The .path
re-trigger storm bug is moot because the whole mechanism is gone.
Manual suspends (sway XF86Sleep keybind, sway power submode `s`,
`systemctl suspend` over SSH) still always work regardless of AC --
explicit user intent wins.
Also drop /migrate-podman-to-btrfs.sh from .gitignore; the one-off
migration script has been deleted now that the user has switched their
podman storage to the btrfs driver.
On-host steps to apply:
chezmoi apply -v
systemctl --user daemon-reload
systemctl --user reset-failed zellij-inhibit-suspend.service zellij-inhibit-suspend.path || true
systemctl --user stop zellij-inhibit-suspend.path zellij-inhibit-suspend.service || true
systemctl --user disable zellij-inhibit-suspend.path || true
systemctl --user restart swayidle.service
# logind drop-in is reloaded automatically by the etc deploy script.
Verify:
systemctl status systemd-logind | grep -i lid
loginctl show-session $XDG_SESSION_ID | grep -i lid
# Unplug AC -> close lid -> should suspend.
# Plug AC -> close lid -> nothing happens.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The previous watcher exited immediately whenever no SSH-spawned zellij
was present. That caused a start-rate-limit storm:
.path triggers service (zellij dir non-empty)
-> watcher exits because no SSH zellij
-> service stops
-> .path retriggers (zellij dir still non-empty)
-> ... 5 starts in 10s, systemd stops the path unit
-> no inhibitor ever again, even after you SSH in
Restructure so the watcher stays alive for the entire zellij socket
directory lifetime and acquires/releases its own systemd-inhibit lock
dynamically based on SSH-zellij presence:
* Watcher now polls and exits only when the zellij socket dir is empty,
matching the .path's trigger condition so it never re-fires while
zellij is alive.
* systemd-inhibit removed from ExecStart - watcher self-inhibits via a
child 'systemd-inhibit ... sleep infinity' it can terminate on demand.
* StartLimitIntervalSec=0 on the service as belt-and-braces against
any future regression of the cycle.
Recovery from the rate-limit hit:
systemctl --user reset-failed zellij-inhibit-suspend.service zellij-inhibit-suspend.path
systemctl --user daemon-reload
systemctl --user restart zellij-inhibit-suspend.path
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Confirmed root cause: this hardware's S3 (deep) firmware path triggers a
fatal wake-from-suspend hang only on linux-hardened. INIT_ON_FREE + slab
hardening + tighter locking turn a latent driver race that stock linux
gets away with into an unrecoverable panic so early the journal isn't
even flushed. mem_sleep_default=s2idle bypasses the BIOS S3 path
entirely (s0ix is a pure-kernel low-power state) and suspends/resumes
reliably under hardened.
This is a widespread Lenovo S3 firmware issue across post-2018
ThinkPads (see Ubuntu T560, X1C9/10/11 reports). Lenovo themselves
moved newer firmwares to s2idle-only. Not a linux-hardened bug per se;
just hardened being a strict enough kernel to make the bug fatal.
Keep:
* mem_sleep_default=s2idle in etc/kernel/cmdline-linux-hardened.tmpl
(only the hardened UKI; stock linux keeps unchanged shared cmdline)
Revert (all the diagnostic / speculative scaffolding from the last
few commits):
* MODULES=(intel_lpss_pci) → MODULES=() — Arch wiki touchpad fix was
not the cause here
* nmi_watchdog=panic softlockup_panic=1 panic=10 — only needed to
auto-reboot during diagnosis
* no_console_suspend — diagnostic-only
* etc/systemd/logind.conf.d/20-no-suspend.conf — masking workaround
* sleep-target masking block in run_onchange_after_deploy-etc.sh.tmpl,
replaced with a one-shot cleanup that removes any leftover
/dev/null symlinks from systems that ran the previous version
* systemd-pstore.service from systemd-units/system.txt — added only to
catch the diagnostic panic
* diagnose-suspend.sh helper (and its .gitignore/.chezmoiignore entries)
* sway suspend → lock-session keybind workaround
* power-menu.sh Suspend entry restoration
* KEYBINDS.md docs
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
fixed
linux-hardened wedges on resume from S3 (NVMe/i915/iwlwifi driver UAF
exposed by INIT_ON_FREE + slab hardening). Until root-caused, take
suspend off the table while keeping lock + DPMS intact.
- etc/systemd/logind.conf.d/20-no-suspend.conf: lid close, suspend
key, hibernate key all map to 'lock'; IdleAction=ignore (swayidle
drives DPMS+swaylock independently).
- run_onchange_after_deploy-etc.sh.tmpl: mask sleep.target,
suspend.target, hibernate.target, hybrid-sleep.target,
suspend-then-hibernate.target via /etc/systemd/system -> /dev/null
symlinks. Catches 'systemctl suspend' from any source.
- dot_config/sway/config: XF86Sleep and system-mode 's' now run
loginctl lock-session instead of systemctl suspend.
- dot_config/sway/executable_power-menu.sh: drop Suspend entry.
- KEYBINDS.md: reflect new behaviour.
To re-enable later: remove the logind drop-in + symlink loop, then
sudo systemctl daemon-reload.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A local zellij session (sway terminal, attended) shouldn't keep the
laptop awake — that's the user actively in front of the machine, and
normal suspend behaviour should apply. Only zellij sessions that were
spawned from an SSH context need the persistent inhibit, so detach +
disconnect leaves the host awake until the session ends.
Use /proc/<pid>/environ to detect SSH-spawned zellij: the daemonised
zellij server is exec'd by the client and Linux preserves the exec-time
environment for the life of the process, so SSH_CONNECTION= survives
the SSH session closing. Walk every running `zellij` pid; hold the
lock as long as at least one of them has SSH_CONNECTION in its environ.
The .path unit still fires on every zellij socket creation, but if no
SSH-spawned zellij exists the watcher exits immediately and the service
stops with no harm done — a couple of cheap process spawns per local
session start, no inhibitor side-effects.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The SSH-shell inhibitor in dot_zprofile is bound to the lifetime of the
login shell, so it disappears the moment the user detaches a zellij
session and disconnects — defeating the whole point of using zellij for
persistent remote work.
Add a user-scope path+service+watcher trio that ties the inhibit lock
to the existence of zellij sessions instead:
- dot_local/bin/executable_zellij-inhibit-watcher
Polls `zellij list-sessions --short` every 15s, exits when none
remain. Override poll interval via $ZELLIJ_INHIBIT_POLL.
- dot_config/systemd/user/zellij-inhibit-suspend.service
Wraps the watcher in `systemd-inhibit --what=sleep:idle:handle-lid-switch
--mode=block`. When the watcher exits, the service stops and the
lock is released.
- dot_config/systemd/user/zellij-inhibit-suspend.path
Activates the service whenever $XDG_RUNTIME_DIR/zellij becomes
non-empty (i.e. zellij creates its first session socket). Re-fires
on every empty→non-empty transition.
Enable via systemd-units/user.txt (the .path unit; the service is
on-demand).
The existing SSH-shell inhibitor is kept as a backstop for non-zellij
remote sessions and is now documented as such.
VM (nix/vm.nix) deliberately not updated: the Ubuntu remote-dev VM
never suspends, so the inhibit machinery would be inert there.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A remote session is useless if the laptop suspends mid-command, but
logind doesn't suppress lid-close or idle-suspend for SSH sessions on
its own — you have to hold an explicit inhibitor lock.
When $SSH_CONNECTION is set, re-exec the login shell under
`systemd-inhibit --what=sleep:idle:handle-lid-switch --mode=block`
so the lock is bound to the shell's lifetime: it covers swayidle,
logind's HandleLidSwitch, and any other consumer that respects
inhibit locks, and it's released the moment the SSH session ends.
A guard env var prevents recursion if the user nests a login shell
inside the wrapped one (e.g. `exec zsh -l`).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
fuse-overlayfs is dog-slow on `podman commit` (and noticeably slower
than native overlay/btrfs for layer extraction in general) because every
read/write round-trips through a FUSE daemon. The kernel overlay driver
does not support btrfs as a lowerdir, so on a btrfs root fs the choices
were:
- fuse-overlayfs (slow, but works)
- btrfs (native subvolume + CoW snapshot per layer; fast)
Switching graph drivers is destructive — the on-disk layout is
incompatible, so a one-time `podman system reset --force` is required.
A migration helper script lives at the repo root (gitignored,
chezmoiignored) that snapshots stateful containers, exports images and
volumes, runs the reset, and restores everything on the new driver.
Drops fuse-overlayfs from meta/base.txt — no longer needed and pulls
in libfuse3 transitively for nothing. (Flatpak still depends on it for
its own sandbox; pacman won't actually uninstall the binary while
flatpak is around — that's fine.)
VM (nix/vm.nix) is unaffected: it sets its own storage.conf inline
with driver=overlay since its rootfs is ext4.
|
| | |
|
| | |
|
| |
|
|
|
|
| |
Add dot_config/tuicr/config.toml with theme = "gruvbox-dark".
Symlinked from nix/vm.nix per the symlink invariant so the same
config applies on both host (via chezmoi) and VM (via home-manager).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Previously every new login retargeted ~/.ssh/agent.sock to its own
per-connection forwarded socket. That broke a multi-connection setup
when the most-recent connection (which 'won' the symlink) dropped:
all surviving connections' panes would point at a dead socket until a
fresh login from a surviving connection re-ran zprofile.
zprofile: only retarget when the existing symlink target is dead
(sshd unlinks the per-connection socket on disconnect, so [[ -S ]] on
the resolved path is a reliable liveness probe). First connection
seeds the symlink, subsequent logins keep using it.
ssh-agent-refresh: scan /tmp/ssh-*/agent.* for any live forwarded
socket and retarget to the first that responds to ssh-add. Lets the
surviving connection recover without waiting for a new login shell.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Switching to nix's zsh on the Arch host left two functional gaps the
Arch zsh package used to fill:
1. /usr/share/zsh/site-functions in fpath: pacman, paru, systemctl,
journalctl, flatpak, docker, kubectl, makepkg etc. drop their
completions there. nix zsh's compiled-in fpath doesn't include
/usr/share so we lose all of them silently. Added that path (and
vendor-completions for the VM's apt-installed completions) to the
existing fpath loop, guarded by [[ -d ]].
2. HELPDIR for the run-help / help-alias machinery: needed so 'help cd'
etc. find the per-builtin help docs. Pick the first existing version
dir, preferring nix-profile so it matches the running zsh version.
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
tuicr's upstream flake uses the legacy 'defaultPackage.<system>' output
schema, not 'packages.<system>.default' — fixes the home-manager switch
error 'attribute packages missing' at nix/flake.nix:28.
zsh: removing the system zsh package took /etc/zsh/zprofile with it,
which used to 'source /etc/profile' and pull in /etc/profile.d/*.sh
(flatpak.sh, nix.sh, etc.). Reconstruct XDG_DATA_DIRS in dot_zprofile
defensively, including per-user + system flatpak exports + nix-profile
share, so 'flatpak update' stops warning and desktop entries from
flatpak/nix-installed apps work in launchers (fuzzel).
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Waybar (and other user services) was inheriting the bare pre-login
PATH from systemd --user, missing ~/.nix-profile/bin and ~/.local/bin.
Modules that call nix-provisioned binaries (pass, python3, ncat from
common.nix) silently picked up system copies instead — symptom was
waybar showing different output from the same script when invoked
manually (thunderbird tb-unread.sh, wifi-status.sh).
Also propagate GNUPGHOME and GPG_TTY so pinentry / pass-otp inside
user services behave the same as in the interactive shell.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Forwarded SSH_AUTH_SOCK lives at /tmp/ssh-XXX/agent.NNN — a
per-connection path that disappears on disconnect, leaving every
long-running zellij pane (and its children: claude-code, nvim, …)
pointing at a dead socket. Reattaching after reconnect doesn't help:
the env was captured when zellij first started.
Fix: maintain ~/.ssh/agent.sock as a symlink, re-aimed at the live
forwarded socket on every login (zprofile). Export the stable path so
processes inherit a value that survives reconnects — git fetch /
commit signing keep working in re-attached zellij panes with zero
per-pane re-export.
Adds 'ssh-agent-refresh' helper for transitional panes still holding
the dead per-connection path: re-exports SSH_AUTH_SOCK to the stable
symlink and validates with ssh-add -l. Already-running children
(claude-code) must still be restarted since env is inherited, not
observed.
|
| |
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
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
|
| |
|
|
|
| |
- zsh: remove ~/.local/share/nvim/mason/bin from PATH
- justfile: update comments to reflect Mason removal
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
| |
No longer needed.
|
| |
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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`.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
`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.
|
| |
|
|
| |
This reverts commit 1d7feb8d405e135dc6109052948b8b9240cf882a.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.)
|
| |
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
| |
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).
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
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.
|