aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--dot_config/git/hooks/_dispatch.sh2
-rwxr-xr-xdot_config/git/hooks/executable_commit-msg8
-rwxr-xr-xdot_config/git/hooks/executable_post-commit2
-rwxr-xr-xdot_config/git/hooks/executable_pre-commit2
-rwxr-xr-xdot_config/git/hooks/executable_pre-push2
-rw-r--r--dot_config/sway/executable_brightness-osd.sh2
-rw-r--r--dot_config/sway/executable_bt-toggle.sh2
-rwxr-xr-xdot_config/sway/executable_display-toggle.sh2
-rwxr-xr-xdot_config/sway/executable_display-watcher.sh2
-rw-r--r--dot_config/sway/executable_emoji-picker.sh2
-rw-r--r--dot_config/sway/executable_emoji-wofi.sh2
-rw-r--r--dot_config/sway/executable_power-menu.sh2
-rw-r--r--dot_config/sway/executable_tb-autostart.sh2
-rw-r--r--dot_config/sway/executable_tb-toggle.sh2
-rw-r--r--dot_config/sway/executable_type-vpn-otp.sh2
-rw-r--r--dot_config/sway/executable_vol-osd.sh2
-rw-r--r--dot_config/systemd/user/wob.service4
-rwxr-xr-xdot_config/waybar/executable_arch-audit-status.sh2
-rw-r--r--dot_config/waybar/executable_clip-picker.sh2
-rw-r--r--dot_config/waybar/executable_dock-status.sh2
-rwxr-xr-xdot_config/waybar/executable_failed-units-status.sh2
-rwxr-xr-xdot_config/waybar/executable_lostfiles-status.sh2
-rw-r--r--dot_config/waybar/executable_mako-status.sh2
-rwxr-xr-xdot_config/waybar/executable_memory-status.sh2
-rwxr-xr-xdot_config/waybar/executable_pacdiff-status.sh2
-rw-r--r--dot_config/waybar/executable_snx-vpn-status.sh2
-rw-r--r--dot_config/waybar/executable_snx-vpn-toggle.sh2
-rw-r--r--dot_config/waybar/executable_tb-unread.sh2
-rwxr-xr-xdot_config/waybar/executable_update-status.sh2
-rw-r--r--dot_config/waybar/executable_vpn-status.sh2
-rw-r--r--dot_config/waybar/executable_vpn-toggle.sh2
-rw-r--r--dot_config/waybar/executable_webcam-status.sh2
-rwxr-xr-xdot_config/waybar/executable_wifi-status.sh2
-rw-r--r--dot_config/waybar/executable_wifi-toggle.sh2
-rw-r--r--dot_local/bin/executable__sandbox-net-parser2
-rw-r--r--dot_local/bin/executable_dictate2
-rwxr-xr-xdot_local/bin/executable_linkhandler2
-rw-r--r--dot_local/bin/executable_ocr2
-rw-r--r--dot_local/bin/executable_on-battery-suspend2
-rwxr-xr-xdot_local/bin/executable_record4
-rwxr-xr-xdot_local/bin/executable_rqr2
-rw-r--r--dot_local/bin/executable_streamlink2
-rwxr-xr-xdot_local/bin/executable_togreta2
-rwxr-xr-xdot_local/bin/executable_tokodi2
-rwxr-xr-xdot_local/bin/executable_wqr2
-rw-r--r--dot_local/bin/executable_yt-dlp2
-rw-r--r--etc/pacman.conf2
-rw-r--r--etc/systemd/system/syncthing@.service53
-rw-r--r--justfile50
-rw-r--r--meta/base.txt11
-rw-r--r--meta/btc.txt3
-rw-r--r--nix/common.nix13
-rw-r--r--nix/flake.lock20
-rw-r--r--nix/flake.nix11
-rw-r--r--nix/host.nix7
-rwxr-xr-xrun_onchange_after_deploy-etc.sh.tmpl2
-rwxr-xr-xrun_onchange_after_deploy-firefox.sh.tmpl2
-rw-r--r--run_onchange_after_deploy-flatpak-overrides.sh.tmpl2
-rw-r--r--run_onchange_after_deploy-pteid-pkcs11.sh.tmpl2
-rw-r--r--run_onchange_after_deploy-tb-eer.sh.tmpl2
-rw-r--r--run_onchange_after_deploy-thunderbird.sh.tmpl2
-rwxr-xr-xrun_onchange_after_install-copilot-node.sh2
-rw-r--r--systemd-units/system.txt3
63 files changed, 181 insertions, 108 deletions
diff --git a/dot_config/git/hooks/_dispatch.sh b/dot_config/git/hooks/_dispatch.sh
index ed5acbf..9ba6e3b 100644
--- a/dot_config/git/hooks/_dispatch.sh
+++ b/dot_config/git/hooks/_dispatch.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Sourced by every hook in this directory. Runs the per-repo hook of
# the same name and then returns control so the calling user-level
# hook can do its own work after.
diff --git a/dot_config/git/hooks/executable_commit-msg b/dot_config/git/hooks/executable_commit-msg
index e484ccb..628ac94 100755
--- a/dot_config/git/hooks/executable_commit-msg
+++ b/dot_config/git/hooks/executable_commit-msg
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Strip Co-authored-by trailers whose identity looks like a coding agent
# (Copilot, Claude, Codex, ChatGPT, Cursor, Aider, Devin, ...). Various
# tools — GitHub Copilot CLI, VS Code chat, etc. — append these
@@ -58,7 +58,11 @@ esac
# Collapse any trailing blank lines produced by the removal so we don't
# leave a dangling blank trailer block.
-sed -e :a -e '/^$/{$d;N;ba' -e '}' "$tmp" >"$msg_file"
+awk '
+ NF { last = NR }
+ { lines[NR] = $0 }
+ END { for (i = 1; i <= last; i++) print lines[i] }
+' "$tmp" >"$msg_file"
printf 'commit-msg: stripped AI Co-authored-by trailer(s).\n' >&2
exit 0
diff --git a/dot_config/git/hooks/executable_post-commit b/dot_config/git/hooks/executable_post-commit
index 45f13f0..69d85f9 100755
--- a/dot_config/git/hooks/executable_post-commit
+++ b/dot_config/git/hooks/executable_post-commit
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# User-level post-commit. No global checks — exists purely so that
# `<repo>/.githooks/post-commit` gets picked up automatically without
# the project needing to override core.hooksPath. If there is no
diff --git a/dot_config/git/hooks/executable_pre-commit b/dot_config/git/hooks/executable_pre-commit
index 548925b..76d623b 100755
--- a/dot_config/git/hooks/executable_pre-commit
+++ b/dot_config/git/hooks/executable_pre-commit
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# User-level pre-commit. No global checks — exists purely so that
# `<repo>/.githooks/pre-commit` gets picked up automatically without
# the project needing to override core.hooksPath. If there is no
diff --git a/dot_config/git/hooks/executable_pre-push b/dot_config/git/hooks/executable_pre-push
index 286958b..b0915bf 100755
--- a/dot_config/git/hooks/executable_pre-push
+++ b/dot_config/git/hooks/executable_pre-push
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Reject pushes that include commits which:
# * lack a good signature, or
# * have a committer different from this repo's user.name / user.email, or
diff --git a/dot_config/sway/executable_brightness-osd.sh b/dot_config/sway/executable_brightness-osd.sh
index cc802ad..614fc6f 100644
--- a/dot_config/sway/executable_brightness-osd.sh
+++ b/dot_config/sway/executable_brightness-osd.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Print brightness percent to wob's fifo to flash a brightness bar.
# Usage: brightness-osd.sh up|down
set -eu
diff --git a/dot_config/sway/executable_bt-toggle.sh b/dot_config/sway/executable_bt-toggle.sh
index 02b72f9..29ec6c6 100644
--- a/dot_config/sway/executable_bt-toggle.sh
+++ b/dot_config/sway/executable_bt-toggle.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Toggle Bluetooth power via bluetoothctl. Uses notify-send's synchronous
# hint so repeated toggles replace the previous notification instead of
# stacking.
diff --git a/dot_config/sway/executable_display-toggle.sh b/dot_config/sway/executable_display-toggle.sh
index 39e3367..50f84f8 100755
--- a/dot_config/sway/executable_display-toggle.sh
+++ b/dot_config/sway/executable_display-toggle.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Display mode manager: laptop-off ↔ side-by-side.
# (no arg) toggle between modes (F7 / Super+x d).
# apply re-apply the saved mode (used by display-watcher after
diff --git a/dot_config/sway/executable_display-watcher.sh b/dot_config/sway/executable_display-watcher.sh
index 94ee943..7e446f5 100755
--- a/dot_config/sway/executable_display-watcher.sh
+++ b/dot_config/sway/executable_display-watcher.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Watch sway output events. When the set of connected external displays
# changes (plug/unplug), re-apply the preferred layout via display-toggle.sh.
# Manual F7 toggles don't trip this because they don't change external count.
diff --git a/dot_config/sway/executable_emoji-picker.sh b/dot_config/sway/executable_emoji-picker.sh
index 2a18283..86a379f 100644
--- a/dot_config/sway/executable_emoji-picker.sh
+++ b/dot_config/sway/executable_emoji-picker.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Bemoji wrapper: drop skin-tone variants (U+1F3FB..U+1F3FF) so the
# picker isn't cluttered with five copies of every people-emoji.
# Bemoji pipes its emoji list to whatever BEMOJI_PICKER_CMD evaluates
diff --git a/dot_config/sway/executable_emoji-wofi.sh b/dot_config/sway/executable_emoji-wofi.sh
index 8d37240..1c16169 100644
--- a/dot_config/sway/executable_emoji-wofi.sh
+++ b/dot_config/sway/executable_emoji-wofi.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Bemoji picker backend: filter out skin-tone variants
# (U+1F3FB..U+1F3FF) before handing the emoji list to wofi.
set -eu
diff --git a/dot_config/sway/executable_power-menu.sh b/dot_config/sway/executable_power-menu.sh
index 999259c..40598a8 100644
--- a/dot_config/sway/executable_power-menu.sh
+++ b/dot_config/sway/executable_power-menu.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Keyboard-driven power menu via wofi --dmenu (j/k navigation).
set -eu
diff --git a/dot_config/sway/executable_tb-autostart.sh b/dot_config/sway/executable_tb-autostart.sh
index 13c8fe8..3a85dc5 100644
--- a/dot_config/sway/executable_tb-autostart.sh
+++ b/dot_config/sway/executable_tb-autostart.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Launch Thunderbird and stash the main window into the scratchpad once sway
# marks it. Used at sway startup so TB is running but hidden from the outset.
# Invoking Super+t (tb-toggle.sh) while TB isn't running takes a different
diff --git a/dot_config/sway/executable_tb-toggle.sh b/dot_config/sway/executable_tb-toggle.sh
index 56bb662..13382ed 100644
--- a/dot_config/sway/executable_tb-toggle.sh
+++ b/dot_config/sway/executable_tb-toggle.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Toggle the Thunderbird main window between the sway scratchpad and the
# current workspace (tiled). If Thunderbird isn't running yet, launch it —
# the for_window rule in sway config will mark it and stash it.
diff --git a/dot_config/sway/executable_type-vpn-otp.sh b/dot_config/sway/executable_type-vpn-otp.sh
index b3f0924..f62ecbc 100644
--- a/dot_config/sway/executable_type-vpn-otp.sh
+++ b/dot_config/sway/executable_type-vpn-otp.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Fetch the current VPN TOTP from pass-otp and type it into the focused
# surface via wtype. If wtype isn't available or fails (focused surface
# lacks virtual-keyboard support, e.g. an Xwayland app), copy the code
diff --git a/dot_config/sway/executable_vol-osd.sh b/dot_config/sway/executable_vol-osd.sh
index 7e324e0..e593710 100644
--- a/dot_config/sway/executable_vol-osd.sh
+++ b/dot_config/sway/executable_vol-osd.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Print 0–100 to wob's fifo to flash a volume bar overlay.
# Usage: vol-osd.sh up|down|mute (mute toggles)
set -eu
diff --git a/dot_config/systemd/user/wob.service b/dot_config/systemd/user/wob.service
index d9c0869..559487a 100644
--- a/dot_config/systemd/user/wob.service
+++ b/dot_config/systemd/user/wob.service
@@ -6,8 +6,8 @@ ConditionEnvironment=WAYLAND_DISPLAY
[Service]
Type=simple
-ExecStartPre=/usr/bin/sh -c 'rm -f "$XDG_RUNTIME_DIR/wob.sock" && mkfifo "$XDG_RUNTIME_DIR/wob.sock"'
-ExecStart=/usr/bin/sh -c 'exec tail -f "$XDG_RUNTIME_DIR/wob.sock" | %h/.nix-profile/bin/wob'
+ExecStartPre=%h/.nix-profile/bin/dash -c 'rm -f "$XDG_RUNTIME_DIR/wob.sock" && mkfifo "$XDG_RUNTIME_DIR/wob.sock"'
+ExecStart=%h/.nix-profile/bin/dash -c 'exec tail -f "$XDG_RUNTIME_DIR/wob.sock" | %h/.nix-profile/bin/wob'
ExecStopPost=/usr/bin/rm -f %t/wob.sock
Restart=on-failure
RestartSec=2s
diff --git a/dot_config/waybar/executable_arch-audit-status.sh b/dot_config/waybar/executable_arch-audit-status.sh
index 73edf6f..3c25c18 100755
--- a/dot_config/waybar/executable_arch-audit-status.sh
+++ b/dot_config/waybar/executable_arch-audit-status.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Waybar custom/arch-audit: shows count of installed packages with known
# CVEs that already have a fix available in the repos. Source of truth
# is /run/arch-audit.txt, refreshed daily by arch-audit.timer (system
diff --git a/dot_config/waybar/executable_clip-picker.sh b/dot_config/waybar/executable_clip-picker.sh
index d7f5b61..c94e3de 100644
--- a/dot_config/waybar/executable_clip-picker.sh
+++ b/dot_config/waybar/executable_clip-picker.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Clipboard picker on top of cliphist + wofi (vim-nav, hide-search,
# Alt-d to delete the highlighted entry).
#
diff --git a/dot_config/waybar/executable_dock-status.sh b/dot_config/waybar/executable_dock-status.sh
index b8093fb..ca6d031 100644
--- a/dot_config/waybar/executable_dock-status.sh
+++ b/dot_config/waybar/executable_dock-status.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Detect a Lenovo ThinkPad USB-C Dock Gen2 by its distinctive built-in
# ethernet adapter (17ef:a387). The dock's USB hubs share product IDs
# with internal ThinkPad hubs on some models, but the ethernet is only
diff --git a/dot_config/waybar/executable_failed-units-status.sh b/dot_config/waybar/executable_failed-units-status.sh
index da7db49..9066904 100755
--- a/dot_config/waybar/executable_failed-units-status.sh
+++ b/dot_config/waybar/executable_failed-units-status.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Waybar custom/failed-units: shows count of failed systemd units across
# the system bus and the current user's session bus. Hidden when zero.
# Mako fires only on transition upward (count went up since last check),
diff --git a/dot_config/waybar/executable_lostfiles-status.sh b/dot_config/waybar/executable_lostfiles-status.sh
index f5f1099..be1adae 100755
--- a/dot_config/waybar/executable_lostfiles-status.sh
+++ b/dot_config/waybar/executable_lostfiles-status.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Waybar custom/lostfiles: shows count of filesystem entries not owned
# by any pacman package (and not on lostfiles' built-in safe-list).
# Source of truth is /run/lostfiles.txt, refreshed weekly by
diff --git a/dot_config/waybar/executable_mako-status.sh b/dot_config/waybar/executable_mako-status.sh
index 4e9f053..bab3765 100644
--- a/dot_config/waybar/executable_mako-status.sh
+++ b/dot_config/waybar/executable_mako-status.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Waybar status: count of currently-visible mako notifications. With
# default-timeout=0 in mako/config, "visible" == "pending"; once a
# notification is dismissed it's gone and never comes back.
diff --git a/dot_config/waybar/executable_memory-status.sh b/dot_config/waybar/executable_memory-status.sh
index 33ccc04..5b19ca5 100755
--- a/dot_config/waybar/executable_memory-status.sh
+++ b/dot_config/waybar/executable_memory-status.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Emit waybar JSON with memory usage. Used% uses a heat scale (green → red),
# available% uses the inverse (red → green). Values embedded via Pango span.
set -eu
diff --git a/dot_config/waybar/executable_pacdiff-status.sh b/dot_config/waybar/executable_pacdiff-status.sh
index c9278d2..92eb6a8 100755
--- a/dot_config/waybar/executable_pacdiff-status.sh
+++ b/dot_config/waybar/executable_pacdiff-status.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Waybar custom/pacdiff: shows count of unresolved .pacnew/.pacsave files.
# Source of truth is `pacdiff -o` (output mode — lists differing files,
# does nothing). Hidden when zero. Mako fires once when the count goes
diff --git a/dot_config/waybar/executable_snx-vpn-status.sh b/dot_config/waybar/executable_snx-vpn-status.sh
index 9088630..f88c3a0 100644
--- a/dot_config/waybar/executable_snx-vpn-status.sh
+++ b/dot_config/waybar/executable_snx-vpn-status.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Waybar custom/snx-vpn module: report the snx-rs (Check Point) tunnel
# state. `snxctl status` is fast (talks over a local UDS to the daemon)
# but might briefly stall during connect; cap it with `timeout`.
diff --git a/dot_config/waybar/executable_snx-vpn-toggle.sh b/dot_config/waybar/executable_snx-vpn-toggle.sh
index c21643b..80ced4c 100644
--- a/dot_config/waybar/executable_snx-vpn-toggle.sh
+++ b/dot_config/waybar/executable_snx-vpn-toggle.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Toggle the snx-rs (Check Point) tunnel.
#
# Refresh the waybar custom/snx-vpn module immediately with SIGRTMIN+9.
diff --git a/dot_config/waybar/executable_tb-unread.sh b/dot_config/waybar/executable_tb-unread.sh
index 200cb70..b969215 100644
--- a/dot_config/waybar/executable_tb-unread.sh
+++ b/dot_config/waybar/executable_tb-unread.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Emit waybar JSON with the count of unread messages in the protonmail-bridge
# IMAP Inbox. Requires bridge credentials in `pass` at the paths below; the
# bridge prints them via `protonmail-bridge --cli` → `info`.
diff --git a/dot_config/waybar/executable_update-status.sh b/dot_config/waybar/executable_update-status.sh
index 2317256..cbd899e 100755
--- a/dot_config/waybar/executable_update-status.sh
+++ b/dot_config/waybar/executable_update-status.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Waybar custom/update: gentle reminder that the system hasn't been
# upgraded recently. Source of truth is /var/log/pacman.log — the last
# "[PACMAN] starting full system upgrade" entry. No daemon, no -Sy
diff --git a/dot_config/waybar/executable_vpn-status.sh b/dot_config/waybar/executable_vpn-status.sh
index 3e6faba..9a5016f 100644
--- a/dot_config/waybar/executable_vpn-status.sh
+++ b/dot_config/waybar/executable_vpn-status.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Waybar custom/vpn module: report whether the wireguard interface
# (managed by systemd-networkd) is admin-up. Pango markup makes the
# state visually unambiguous (green shield up, red strikethrough down)
diff --git a/dot_config/waybar/executable_vpn-toggle.sh b/dot_config/waybar/executable_vpn-toggle.sh
index c348971..1a996df 100644
--- a/dot_config/waybar/executable_vpn-toggle.sh
+++ b/dot_config/waybar/executable_vpn-toggle.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Toggle the wireguard interface managed by systemd-networkd. Polkit
# rule (etc/polkit-1/rules.d/50-networkd-wheel.rules) lets wheel-group
# members invoke networkctl up/down without a password prompt.
diff --git a/dot_config/waybar/executable_webcam-status.sh b/dot_config/waybar/executable_webcam-status.sh
index 2441039..be78774 100644
--- a/dot_config/waybar/executable_webcam-status.sh
+++ b/dot_config/waybar/executable_webcam-status.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Emit waybar JSON when any /dev/video* device is held open by a process.
# V4L2 capture (firefox, zoom, OBS, etc.) doesn't go through PipeWire's
# privacy portal, so the built-in waybar privacy module never sees it.
diff --git a/dot_config/waybar/executable_wifi-status.sh b/dot_config/waybar/executable_wifi-status.sh
index 93b3048..2b3201b 100755
--- a/dot_config/waybar/executable_wifi-status.sh
+++ b/dot_config/waybar/executable_wifi-status.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Emit waybar JSON describing wifi link state.
#
# Uses iwd's D-Bus API for state + SSID (net.connman.iwd is a documented,
diff --git a/dot_config/waybar/executable_wifi-toggle.sh b/dot_config/waybar/executable_wifi-toggle.sh
index 2eb27bc..e57f11f 100644
--- a/dot_config/waybar/executable_wifi-toggle.sh
+++ b/dot_config/waybar/executable_wifi-toggle.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Toggle wifi (wlan0) Powered state via iwd's D-Bus API. Driven by waybar
# on-click on the custom/wifi module.
set -eu
diff --git a/dot_local/bin/executable__sandbox-net-parser b/dot_local/bin/executable__sandbox-net-parser
index 3189d00..6b55d08 100644
--- a/dot_local/bin/executable__sandbox-net-parser
+++ b/dot_local/bin/executable__sandbox-net-parser
@@ -1,4 +1,4 @@
-#!/usr/bin/env sh
+#!/usr/bin/env dash
# Sandbox wrapper for tools that parse data from untrusted network
# sources (yt-dlp, streamlink). The threat model is RCE in a
# subtitle / muxer / extractor that walks the user's home directory
diff --git a/dot_local/bin/executable_dictate b/dot_local/bin/executable_dictate
index bf1157c..7ad80bb 100644
--- a/dot_local/bin/executable_dictate
+++ b/dot_local/bin/executable_dictate
@@ -1,4 +1,4 @@
-#!/usr/bin/env sh
+#!/usr/bin/env dash
# Push-to-talk dictation. Toggle: 1st invocation starts recording;
# 2nd stops, transcribes via whisper.cpp, types the result into the focused
# window with wtype, and copies it to the clipboard.
diff --git a/dot_local/bin/executable_linkhandler b/dot_local/bin/executable_linkhandler
index a440634..e44dcc1 100755
--- a/dot_local/bin/executable_linkhandler
+++ b/dot_local/bin/executable_linkhandler
@@ -1,4 +1,4 @@
-#!/usr/bin/env sh
+#!/usr/bin/env dash
resolve_url() {
if [ -f "$1" ]; then
diff --git a/dot_local/bin/executable_ocr b/dot_local/bin/executable_ocr
index 5ce8b08..aeadb51 100644
--- a/dot_local/bin/executable_ocr
+++ b/dot_local/bin/executable_ocr
@@ -1,4 +1,4 @@
-#!/usr/bin/env sh
+#!/usr/bin/env dash
# OCR a screen region (default) or an image file → clipboard.
#
# Usage:
diff --git a/dot_local/bin/executable_on-battery-suspend b/dot_local/bin/executable_on-battery-suspend
index 2f39cc7..93155d6 100644
--- a/dot_local/bin/executable_on-battery-suspend
+++ b/dot_local/bin/executable_on-battery-suspend
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Suspend the system, but only if running on battery. Used as the
# swayidle `timeout` action so idle suspends save battery without ever
# firing while the laptop is plugged in.
diff --git a/dot_local/bin/executable_record b/dot_local/bin/executable_record
index ff57758..ac88771 100755
--- a/dot_local/bin/executable_record
+++ b/dot_local/bin/executable_record
@@ -1,4 +1,4 @@
-#!/usr/bin/env sh
+#!/usr/bin/env dash
pid_file="/tmp/recordpid"
log_file="/tmp/record.log"
@@ -9,7 +9,7 @@ pid_exists() {
is_running() {
if pid_exists; then
- ps "$(cat "$pid_file")" >/dev/null 2>&1 || return 1
+ kill -0 "$(cat "$pid_file")" >/dev/null 2>&1 || return 1
else
return 1
fi
diff --git a/dot_local/bin/executable_rqr b/dot_local/bin/executable_rqr
index 335f55b..76ea698 100755
--- a/dot_local/bin/executable_rqr
+++ b/dot_local/bin/executable_rqr
@@ -1,4 +1,4 @@
-#!/usr/bin/env sh
+#!/usr/bin/env dash
text="$(zbarcam -q -1 --raw)"
printf '%s' "$text" | wl-copy
diff --git a/dot_local/bin/executable_streamlink b/dot_local/bin/executable_streamlink
index d13a66d..591fffd 100644
--- a/dot_local/bin/executable_streamlink
+++ b/dot_local/bin/executable_streamlink
@@ -1,4 +1,4 @@
-#!/usr/bin/env sh
+#!/usr/bin/env dash
# Thin wrapper: run streamlink inside _sandbox-net-parser. The
# sandbox keeps `/` bind-mounted, so streamlink's configured player
# (`flatpak run io.mpv.Mpv` — see ~/.config/streamlink/config) is reachable
diff --git a/dot_local/bin/executable_togreta b/dot_local/bin/executable_togreta
index 9a189f9..3aa0afb 100755
--- a/dot_local/bin/executable_togreta
+++ b/dot_local/bin/executable_togreta
@@ -1,4 +1,4 @@
-#!/usr/bin/env sh
+#!/usr/bin/env dash
if [ -z "$1" ]; then
url=$(wl-paste)
diff --git a/dot_local/bin/executable_tokodi b/dot_local/bin/executable_tokodi
index aec226c..469f851 100755
--- a/dot_local/bin/executable_tokodi
+++ b/dot_local/bin/executable_tokodi
@@ -1,4 +1,4 @@
-#!/usr/bin/env sh
+#!/usr/bin/env dash
if [ -z "$1" ]; then
url=$(wl-paste)
diff --git a/dot_local/bin/executable_wqr b/dot_local/bin/executable_wqr
index f878fdf..5f9d36d 100755
--- a/dot_local/bin/executable_wqr
+++ b/dot_local/bin/executable_wqr
@@ -1,4 +1,4 @@
-#!/usr/bin/env sh
+#!/usr/bin/env dash
if [ -z "$1" ]; then
text=$(wl-paste)
diff --git a/dot_local/bin/executable_yt-dlp b/dot_local/bin/executable_yt-dlp
index 87947a8..df62831 100644
--- a/dot_local/bin/executable_yt-dlp
+++ b/dot_local/bin/executable_yt-dlp
@@ -1,4 +1,4 @@
-#!/usr/bin/env sh
+#!/usr/bin/env dash
# Thin wrapper: run yt-dlp inside _sandbox-net-parser. See that
# script for the threat model and the SANDBOX=0 escape hatch.
exec _sandbox-net-parser "$HOME/.nix-profile/bin/yt-dlp" "$@"
diff --git a/etc/pacman.conf b/etc/pacman.conf
index 7097940..8f8be59 100644
--- a/etc/pacman.conf
+++ b/etc/pacman.conf
@@ -24,7 +24,7 @@ Architecture = auto
# Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup
# llama.cpp-vulkan: AUR rebuilds on every llama.cpp commit (1-2 hour build);
# pin and update manually with `paru -S llama.cpp-vulkan` when intended.
-IgnorePkg = llama.cpp-vulkan
+#IgnorePkg =
#IgnoreGroup =
#NoUpgrade =
diff --git a/etc/systemd/system/syncthing@.service b/etc/systemd/system/syncthing@.service
new file mode 100644
index 0000000..ff4eba7
--- /dev/null
+++ b/etc/systemd/system/syncthing@.service
@@ -0,0 +1,53 @@
+[Unit]
+Description=Syncthing - Open Source Continuous File Synchronization for %I
+Documentation=man:syncthing(1)
+After=network.target
+StartLimitIntervalSec=60
+StartLimitBurst=4
+
+[Service]
+User=%i
+Environment="STLOGFORMATTIMESTAMP="
+Environment="STLOGFORMATLEVELSTRING=false"
+Environment="STLOGFORMATLEVELSYSLOG=true"
+ExecStart=/home/%i/.nix-profile/bin/syncthing serve --no-browser --no-restart --allow-newer-config
+Restart=on-failure
+RestartSec=1
+SuccessExitStatus=3 4
+RestartForceExitStatus=3 4
+
+# Best-effort sandboxing, based on the nixpkgs Syncthing system unit.
+ProtectSystem=full
+ProtectKernelTunables=true
+ProtectKernelModules=true
+ProtectKernelLogs=true
+ProtectControlGroups=true
+ProtectHostname=true
+ProtectClock=true
+NoNewPrivileges=true
+RestrictSUIDSGID=true
+MemoryDenyWriteExecute=true
+RestrictNamespaces=true
+RestrictRealtime=true
+RestrictAddressFamilies=AF_INET AF_INET6 AF_NETLINK AF_UNIX
+CapabilityBoundingSet=
+AmbientCapabilities=
+LockPersonality=true
+SystemCallArchitectures=native
+RemoveIPC=true
+PrivateIPC=true
+PrivateTmp=disconnected
+PrivateDevices=true
+DevicePolicy=closed
+PrivatePIDs=true
+ProtectProc=invisible
+ProcSubset=pid
+SystemCallFilter=@system-service
+SystemCallFilter=~@privileged
+SystemCallFilter=~io_uring_setup io_uring_enter io_uring_register
+SystemCallErrorNumber=EPERM
+UMask=7027
+InaccessiblePaths=-/nonexistent
+
+[Install]
+WantedBy=multi-user.target
diff --git a/justfile b/justfile
index dec9200..287955b 100644
--- a/justfile
+++ b/justfile
@@ -6,15 +6,15 @@ default:
# Setup
# ═══════════════════════════════════════════════════════════════════
-# First-time machine setup: regenerate chezmoi config, install git hooks, deploy dotfiles, install base packages, enable curated units, switch Home-Manager
-init: _chezmoi-init _install-hooks apply (pkg-apply "base") unit-apply nix-switch
+# First-time machine setup: regenerate chezmoi config, install git hooks, deploy dotfiles, install base packages, switch Home-Manager, enable curated units
+init: _chezmoi-init _install-hooks apply (pkg-apply "base") nix-switch unit-apply
# ═══════════════════════════════════════════════════════════════════
# Day-to-day
# ═══════════════════════════════════════════════════════════════════
-# Reconcile everything: deploy dotfiles + /etc, top up packages, enable curated units, sync Home-Manager
-sync: apply pkg-fix unit-apply nix-switch
+# Reconcile everything: deploy dotfiles + /etc, top up packages, sync Home-Manager, enable curated units
+sync: apply pkg-fix nix-switch unit-apply
# Deploy dotfiles AND /etc atomically (chezmoi apply; /etc handled by onchange template)
apply:
@@ -72,7 +72,7 @@ pkg-update:
# Run after this to pick up newer versions of nix-managed tools.
nix-update:
- #!/bin/sh
+ #!/usr/bin/env dash
set -eu
if ! command -v nix >/dev/null 2>&1; then
echo "nix not installed; skipping flake update" >&2
@@ -84,7 +84,7 @@ nix-update:
# Update all user-scope flatpaks (Flathub apps + URL bundles when their version changes)
flatpak-update:
- #!/bin/sh
+ #!/usr/bin/env dash
set -eu
flatpak update --user -y --noninteractive
[ -f meta/flatpak.txt ] || exit 0
@@ -459,7 +459,7 @@ dotfiles-diff *paths:
# 3-way merge dotfile conflicts; pass a path for one file, or omit to merge all
dotfiles-merge *paths:
- #!/bin/sh
+ #!/usr/bin/env dash
if [ -n '{{ paths }}' ]; then
chezmoi merge -S . {{ paths }}
else
@@ -468,7 +468,7 @@ dotfiles-merge *paths:
# Show dotfile drift (wraps 'chezmoi status')
dotfiles-status:
- #!/bin/sh
+ #!/usr/bin/env dash
echo "=== Dotfile drift ==="
chezmoi status -S . || true
@@ -485,7 +485,7 @@ dotfiles-status:
# List curated systemd units with their enabled/active state
unit-list:
- #!/bin/sh
+ #!/usr/bin/env dash
_render() {
scope=$1 file=$2
sctl="systemctl"; [ "$scope" = user ] && sctl="systemctl --user"
@@ -514,7 +514,7 @@ unit-list:
# Enable all curated systemd units (idempotent, soft-fail per unit); walks system + user lists
unit-apply:
- #!/bin/sh
+ #!/usr/bin/env dash
if [ -f systemd-units/system.txt ]; then
sed -E 's/[[:space:]]*#.*$//; /^[[:space:]]*$/d' systemd-units/system.txt | while read -r u; do
sudo systemctl enable --now "$u" \
@@ -530,7 +530,7 @@ unit-apply:
# Show drift between curated units and actually-enabled systemd units (system + user)
unit-status:
- #!/bin/sh
+ #!/usr/bin/env dash
tmp=$(mktemp -d); trap 'rm -rf "$tmp"' EXIT
_drift() {
scope=$1 label=$2
@@ -568,7 +568,7 @@ unit-status:
# inferred by probing `systemctl [--user] cat <unit>` (system wins on tie).
unit-add +units:
- #!/bin/sh
+ #!/usr/bin/env dash
set -eu
_scope() {
u=$1
@@ -606,7 +606,7 @@ unit-add +units:
# inferred from which list currently contains the unit.
unit-forget +units:
- #!/bin/sh
+ #!/usr/bin/env dash
set -eu
for u in {{ units }}; do
scope=
@@ -620,7 +620,8 @@ unit-forget +units:
continue
fi
file="systemd-units/${scope}.txt"
- sed -i "/^$(printf '%s' "$u" | sed 's/[]\/$*.^[]/\\&/g')\$/d" "$file"
+ awk -v target="$u" '$0 != target { print }' "$file" > "$file.tmp"
+ mv "$file.tmp" "$file"
echo "removed $u from ${scope}"
if [ "$scope" = user ]; then
systemctl --user disable --now "$u" \
@@ -985,7 +986,7 @@ etc-restore +paths:
# Show package drift: missing packages in adopted groups + undeclared installed packages
pkg-status:
- #!/bin/sh
+ #!/usr/bin/env dash
flatpaks=$(flatpak list --user --app --columns=application 2>/dev/null || true)
echo "=== Package drift ==="
just _active-packages | while read -r pkg; do
@@ -1002,7 +1003,7 @@ pkg-status:
# Print undeclared packages one per line, unindented (pipe to 'paru -Rs -' to remove pacman entries)
undeclared:
- #!/bin/sh
+ #!/usr/bin/env dash
active=$(just _active-packages)
pacman -Qqe | while read -r pkg; do
echo "$active" | grep -qxF "$pkg" || echo "$pkg"
@@ -1017,7 +1018,7 @@ undeclared:
# Show per-group install coverage; pass a group name for a per-package breakdown
pkg-list group="":
- #!/bin/sh
+ #!/usr/bin/env dash
is_installed() {
# $1: group name, $2: package/app id
if [ "$1" = "flatpak" ]; then
@@ -1076,7 +1077,7 @@ pkg-list group="":
# Install one or more package groups, or all groups if none given (e.g. just pkg-apply base intel)
pkg-apply *groups:
- #!/bin/sh
+ #!/usr/bin/env dash
set -eu
# `paru -S --needed` is a no-op for already-installed packages, which
# means a package pulled in transitively (and later declared in
@@ -1116,7 +1117,7 @@ pkg-apply *groups:
# Top up missing packages in groups that are already ≥50% installed (never installs new groups)
pkg-fix:
- #!/bin/sh
+ #!/usr/bin/env dash
flatpaks=$(flatpak list --user --app --columns=application 2>/dev/null || true)
for file in meta/*.txt; do
group=$(basename "$file" .txt)
@@ -1146,7 +1147,7 @@ pkg-fix:
# Append one or more packages to a group list and install them (e.g. just pkg-add base ripgrep fd)
pkg-add group +pkgs:
- #!/bin/sh
+ #!/usr/bin/env dash
set -eu
file="meta/{{ group }}.txt"
if [ ! -f "$file" ]; then
@@ -1171,7 +1172,7 @@ pkg-add group +pkgs:
# Remove one or more packages from a group list (does NOT uninstall; the package may belong to other groups)
pkg-forget group +pkgs:
- #!/bin/sh
+ #!/usr/bin/env dash
set -eu
file="meta/{{ group }}.txt"
if [ ! -f "$file" ]; then
@@ -1180,7 +1181,8 @@ pkg-forget group +pkgs:
fi
for pkg in {{ pkgs }}; do
if grep -qxF "$pkg" "$file"; then
- sed -i "/^$(printf '%s' "$pkg" | sed 's/[]\/$*.^[]/\\&/g')\$/d" "$file"
+ awk -v target="$pkg" '$0 != target { print }' "$file" > "$file.tmp"
+ mv "$file.tmp" "$file"
echo "removed $pkg from {{ group }}.txt"
else
echo "$pkg not in {{ group }}.txt"
@@ -1208,7 +1210,7 @@ _install-hooks:
# new versions of bundle entries).
_flatpak-install:
- #!/bin/sh
+ #!/usr/bin/env dash
set -eu
[ -f meta/flatpak.txt ] || exit 0
flatpak remote-add --if-not-exists --user flathub \
@@ -1233,7 +1235,7 @@ _flatpak-install:
# Print packages from pacman groups that are ≥50% installed (adopted), one per line
_active-packages:
- #!/bin/sh
+ #!/usr/bin/env dash
for file in meta/*.txt; do
[ "$(basename "$file")" = "flatpak.txt" ] && continue
pkgs=$(sed -E 's/[[:space:]]*#.*$//; /^[[:space:]]*$/d' "$file")
diff --git a/meta/base.txt b/meta/base.txt
index 756f776..ac7a749 100644
--- a/meta/base.txt
+++ b/meta/base.txt
@@ -6,14 +6,13 @@
# the distro (man-db/man-pages files), the system runtime (sudo-rs,
# base/base-devel), and things needed pre-bootstrap or by other system
# packages transitively. User-leaf CLIs (chezmoi, paru, qrencode,
-# torsocks, lshw) now come from nix/host.nix.
+# torsocks, lshw, xdg-utils, syncthing) now come from nix/host.nix.
acpid
arch-audit
base
base-devel
btrfs-progs
cpupower
-dashbinsh
dosfstools
fwupd
iwd
@@ -143,7 +142,6 @@ brightnessctl
# pulled transitively by flatpak.
bubblewrap
libfido2
-perl-file-mimeinfo
qt5ct
qt6ct
xdg-user-dirs
@@ -155,10 +153,8 @@ arkenfox-user.js
# --- mail (host-side bits the org.mozilla.thunderbird flatpak depends on) ---
# protonmail-bridge now comes from nix/host.nix (the bridge binary + its
# repo-owned user unit dot_config/systemd/user/protonmail-bridge.service).
-# git send-email Perl prereqs (SMTP via local Bridge on 127.0.0.1:1025)
-perl-authen-sasl
-perl-mime-tools
-perl-net-smtp-ssl
+# git-send-email support is provided by nix/common.nix's git package, which
+# wraps git-send-email with the needed SMTP/SASL Perl libraries.
# (External Editor Revived's native-messaging host is installed via nix
# on the host — see nix/host.nix — so we don't pay the AUR variant's
# hard `thunderbird` dependency. The bridge into the TB flatpak is
@@ -170,7 +166,6 @@ perl-net-smtp-ssl
# Bitcoin wallet — sparrow-wallet — lives in meta/btc.txt.) ---
# --- desktop extras ---
-syncthing
udisks2
# Flatpak runtime (apps tracked in meta/flatpak.txt)
diff --git a/meta/btc.txt b/meta/btc.txt
index a468de1..096118c 100644
--- a/meta/btc.txt
+++ b/meta/btc.txt
@@ -1,5 +1,4 @@
bitbox-wallet-app-appimage
-python-bitbox02
-python-qdarkstyle
+bitbox-udev
sparrow-wallet
tor
diff --git a/nix/common.nix b/nix/common.nix
index 9c9e093..50d7f60 100644
--- a/nix/common.nix
+++ b/nix/common.nix
@@ -54,7 +54,9 @@
glow
# Git stack
- git
+ # Includes git-send-email: nixpkgs wraps it with the SMTP/SASL Perl deps
+ # it needs, so we don't carry distro Perl modules just for email support.
+ (git.override { sendEmailSupport = true; })
gh
delta
mergiraf
@@ -66,6 +68,15 @@
yq-go
# System
+ dash
+ # Prefer Rust uutils for the unprefixed replacements that pass repo-local
+ # usage checks. Keep GNU tar on the system PATH for now; uutils-tar still
+ # rejects common GNU tar invocations like `tar -czf`.
+ uutils-coreutils-noprefix
+ uutils-diffutils
+ uutils-findutils
+ uutils-procps
+ uutils-sed
htop
fastfetch
hyperfine
diff --git a/nix/flake.lock b/nix/flake.lock
index 25482b2..cdbca21 100644
--- a/nix/flake.lock
+++ b/nix/flake.lock
@@ -30,16 +30,16 @@
]
},
"locked": {
- "lastModified": 1779726825,
- "narHash": "sha256-RUkMrREjKDQrA+dA9+xZviGAxM5W1aVdyOr/bSYpHrE=",
+ "lastModified": 1780370888,
+ "narHash": "sha256-PRJj9RKTEf/sITycujP1c/BrvLJKMYXzcpwTsXNulXQ=",
"owner": "nix-community",
"repo": "home-manager",
- "rev": "b179bde238977f7d4454fc770b1a727eaf55111c",
+ "rev": "a7a415883195ffbd4dabec8f098f201e6eaaadf8",
"type": "github"
},
"original": {
"owner": "nix-community",
- "ref": "release-26.05",
+ "ref": "master",
"repo": "home-manager",
"type": "github"
}
@@ -69,11 +69,11 @@
},
"nixpkgs": {
"locked": {
- "lastModified": 1779560665,
- "narHash": "sha256-tpyBcxPpcQb8ukyNF7DoCwfSY3VPsxHoYwj00Cayv5o=",
+ "lastModified": 1780243769,
+ "narHash": "sha256-x5UQuRsH3MqI0U9afaXSNqzTPSeZlRLvFAav2Ux1pNw=",
"owner": "NixOS",
"repo": "nixpkgs",
- "rev": "64c08a7ca051951c8eae34e3e3cb1e202fe36786",
+ "rev": "331800de5053fcebacf6813adb5db9c9dca22a0c",
"type": "github"
},
"original": {
@@ -131,11 +131,11 @@
"utils": "utils"
},
"locked": {
- "lastModified": 1780096845,
- "narHash": "sha256-O3vJgv3HJtizMyjT9PLEL90iqXwRyKaFz0QcaABRQFQ=",
+ "lastModified": 1780345905,
+ "narHash": "sha256-4ERFyKR3O2HUfv3oRuUChoGnSdcdppFpCqrHticKi6A=",
"owner": "agavra",
"repo": "tuicr",
- "rev": "9abc01e8ad13ca9e1beb45d469572bdb0334892e",
+ "rev": "1f585175b59c20c2bfaa8a73ca572218ccfd93ff",
"type": "github"
},
"original": {
diff --git a/nix/flake.nix b/nix/flake.nix
index d82d9a4..f452228 100644
--- a/nix/flake.nix
+++ b/nix/flake.nix
@@ -4,12 +4,11 @@
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
home-manager = {
- # Pin to the release branch matching nixpkgs lib.version (the
- # `nixos-unstable` snapshot we follow here reports 26.05). Without
- # this, HM master races ahead one cycle and emits the
- # "mismatched versions" warning at every activation. Bump the
- # branch name in lockstep when nixpkgs lib.version rolls over.
- url = "github:nix-community/home-manager/release-26.05";
+ # Track the Home Manager branch whose release.json matches nixpkgs'
+ # lib.version. nixos-unstable currently reports 26.11pre-git, while
+ # home-manager's latest release branch is still 26.05, so master is the
+ # matching input until release-26.11 exists.
+ url = "github:nix-community/home-manager/master";
inputs.nixpkgs.follows = "nixpkgs";
};
# tuicr: TUI git-change reviewer. Upstream flake exposes
diff --git a/nix/host.nix b/nix/host.nix
index 0565f1b..dff9aef 100644
--- a/nix/host.nix
+++ b/nix/host.nix
@@ -117,6 +117,13 @@ in
lshw
yt-dlp
streamlink
+ xdg-utils # xdg-open, used by yazi/linkhandler/OPENER
+
+ # ── File sync ───────────────────────────────────────────────────────────────
+ # Package-only migration from pacman. The boot-time system service is the
+ # repo-owned syncthing@sommerfeld.service tracked in systemd-units/system.txt
+ # and backed by etc/systemd/system/syncthing@.service.
+ syncthing
# chezmoi & paru — both are pure user CLIs. `paru` wraps pacman+makepkg
# but doesn't link them; it just shells out. bootstrap.sh installs a
diff --git a/run_onchange_after_deploy-etc.sh.tmpl b/run_onchange_after_deploy-etc.sh.tmpl
index 5b60972..ba79130 100755
--- a/run_onchange_after_deploy-etc.sh.tmpl
+++ b/run_onchange_after_deploy-etc.sh.tmpl
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Deploy system-level configs from etc/ to /etc/.
# chezmoi re-runs this script whenever any file under etc/ changes.
# etc/ content hash: {{ output "sh" "-c" (printf "cd %q && find etc -type f ! -name .ignore -exec sha256sum {} + | LC_ALL=C sort" .chezmoi.sourceDir) | sha256sum }}
diff --git a/run_onchange_after_deploy-firefox.sh.tmpl b/run_onchange_after_deploy-firefox.sh.tmpl
index a917026..eaecb68 100755
--- a/run_onchange_after_deploy-firefox.sh.tmpl
+++ b/run_onchange_after_deploy-firefox.sh.tmpl
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Deploy Firefox/LibreWolf hardening overrides and custom CSS.
# chezmoi re-runs this script whenever any file under firefox/ changes.
# firefox/ content hash: {{ output "sh" "-c" (printf "cd %q && find firefox -type f -exec sha256sum {} + | LC_ALL=C sort" .chezmoi.sourceDir) | sha256sum }}
diff --git a/run_onchange_after_deploy-flatpak-overrides.sh.tmpl b/run_onchange_after_deploy-flatpak-overrides.sh.tmpl
index 8e827fa..44664cf 100644
--- a/run_onchange_after_deploy-flatpak-overrides.sh.tmpl
+++ b/run_onchange_after_deploy-flatpak-overrides.sh.tmpl
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Read-only host config bindings for flatpaks that should pick up our
# chezmoi-managed ~/.config/<app>/ rather than maintaining a separate
# in-sandbox copy. Idempotent; flatpak override merges entries.
diff --git a/run_onchange_after_deploy-pteid-pkcs11.sh.tmpl b/run_onchange_after_deploy-pteid-pkcs11.sh.tmpl
index 10ebcd2..4f57757 100644
--- a/run_onchange_after_deploy-pteid-pkcs11.sh.tmpl
+++ b/run_onchange_after_deploy-pteid-pkcs11.sh.tmpl
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Bridge the pt.gov.autenticacao flatpak's PKCS#11 module into the NSS
# database of every Mozilla-family flatpak we use, so cartão de cidadão
# authentication / S/MIME signing works despite cross-sandbox isolation.
diff --git a/run_onchange_after_deploy-tb-eer.sh.tmpl b/run_onchange_after_deploy-tb-eer.sh.tmpl
index 27f1fef..c4dabff 100644
--- a/run_onchange_after_deploy-tb-eer.sh.tmpl
+++ b/run_onchange_after_deploy-tb-eer.sh.tmpl
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Bridge the External Editor Revived native messaging host into the
# org.mozilla.thunderbird flatpak. The host binary stays installed via
# pacman (`external-editor-revived`); we relocate the manifest into the
diff --git a/run_onchange_after_deploy-thunderbird.sh.tmpl b/run_onchange_after_deploy-thunderbird.sh.tmpl
index 8837ab6..02820f2 100644
--- a/run_onchange_after_deploy-thunderbird.sh.tmpl
+++ b/run_onchange_after_deploy-thunderbird.sh.tmpl
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Deploy Thunderbird non-private configuration (user.js, optional chrome/).
# chezmoi re-runs this script whenever any file under thunderbird/ changes.
# thunderbird/ content hash: {{ output "sh" "-c" (printf "cd %q && find thunderbird -type f -exec sha256sum {} + | LC_ALL=C sort" .chezmoi.sourceDir) | sha256sum }}
diff --git a/run_onchange_after_install-copilot-node.sh b/run_onchange_after_install-copilot-node.sh
index 82c0254..9f3e72e 100755
--- a/run_onchange_after_install-copilot-node.sh
+++ b/run_onchange_after_install-copilot-node.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env dash
# Install a Node.js 24 (LTS) runtime under ~/.local/share/copilot-node/ for the
# exclusive use of copilot.lua / copilot-lsp inside neovim. System-wide nodejs
# (currently 26.x in Arch) is unaffected.
diff --git a/systemd-units/system.txt b/systemd-units/system.txt
index 582a508..19867f7 100644
--- a/systemd-units/system.txt
+++ b/systemd-units/system.txt
@@ -35,3 +35,6 @@ nix-daemon.socket
# --- libvirt (socket-activated; daemons spawn on first virsh/virt-manager
# connect, the .socket is what gets enabled) ---
libvirtd.socket
+
+# --- file sync (system template; binary comes from the user's nix profile) ---
+syncthing@sommerfeld.service