[Sync] adopt unified stow layout from the private repo

Mirrors the private dots tree at 900bdda: one shared base plus per-host
overlays, replacing the old flat .config/ layout (last synced 2026-06-28).

- packages: common/ gui/ wm/ lw/ fl/ + install.sh and bin/ tooling (dotsync,
  reconcile-hyde.sh)
- new README (layout, deploy order, HyDE dependency), plus ToDo.md and
  HYDE-UPDATE.md
- current HyDE waybar rig (layouts/, cava), pi agent extensions, claude/
  config, tmux, presenterm, aichat roles
- drops stale duplicates and generated cruft that should never have been
  tracked: the second top-level .pi/ copy, btop.log, zellij config.kdl.bak,
  fish_variables, nvim codecompanion.lua
- .pi/agent/auth.json is gitignored now; auth.json.example ships instead
- fl/ and wm/ hypr themes/ stay untracked (HyDE-generated per machine, per
  the root .gitignore)
This commit is contained in:
coja
2026-08-12 22:50:18 +02:00
parent f62cb40499
commit a700e23e0a
318 changed files with 12564 additions and 10772 deletions
Executable
+66
View File
@@ -0,0 +1,66 @@
#!/usr/bin/env bash
# dotsync — sync dotfiles with the least churn.
#
# Deployed configs are symlinks into this repo, so `git pull` makes edits LIVE instantly
# with no re-stow — meaning no symlink churn and no app reloads (kitty etc. keep their
# runtime state). Re-stowing (install.sh) is only needed when files are ADDED / REMOVED,
# to create or prune symlinks. dotsync does the minimum: pull, and re-link ONLY if the
# pull added/removed/renamed files.
#
# dotsync pull, then relink only if the file set changed
# dotsync -n preview incoming changes (fetch only; no pull, no relink)
set -uo pipefail
DOTS="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")/.." && pwd)"
cd "$DOTS" || exit 1
if [ "${1:-}" = "-n" ] || [ "${1:-}" = "--dry-run" ]; then
git fetch -q 2>/dev/null || { echo "fetch failed (offline?)"; exit 1; }
up="$(git rev-parse --abbrev-ref '@{u}' 2>/dev/null)" || { echo "no upstream set"; exit 1; }
# rev-list, not diff: a plain diff also fires when the LOCAL side is ahead, mislabelling
# your own unpushed commits as incoming. Count commits that exist only on the upstream.
n="$(git rev-list --count "HEAD..$up")"
if [ "$n" -eq 0 ]; then echo "already up to date with $up."; else
echo "incoming from $up ($n commit(s)):"; git --no-pager diff --stat "HEAD...$up"
fi
exit 0
fi
before="$(git rev-parse HEAD)"
if ! git pull --ff-only; then
echo "pull not fast-forward (local commits or conflicts) — commit/stash, then retry." >&2
exit 1
fi
after="$(git rev-parse HEAD)"
if [ "$before" = "$after" ]; then
echo "already up to date — nothing to sync."
exit 0
fi
# Services that read config ONCE at startup don't pick up pulled edits — nudge loudly.
# (Symlinked edits are live for everything else; these are the exceptions that bit us.)
if git diff --name-only "$before" "$after" | grep -q '\.config/llamacpp/' \
&& systemctl cat llama.service &>/dev/null; then
echo ""
echo "⚠⚠ llamacpp presets changed — the router reads them only at startup. Apply with:"
echo " sudo systemctl restart llama.service"
echo ""
fi
# A unit file is read from /etc, not through the stow symlink — needs daemon-reload as well.
if git diff --name-only "$before" "$after" | grep -q '\.config/whisper/' \
&& systemctl cat whisper.service &>/dev/null; then
echo ""
echo "⚠⚠ whisper unit changed — apply with:"
echo " sudo systemctl daemon-reload && sudo systemctl restart whisper.service"
echo ""
fi
# Modified files (M) are already live through the symlinks. Only Added/Deleted/Renamed
# need (un)linking, which is the only case that justifies the churny re-stow.
if git diff --name-status "$before" "$after" | grep -qE '^(A|D|R)'; then
echo "files added/removed/renamed — re-linking via install.sh (this may reload some apps)…"
exec "$DOTS/install.sh"
else
echo "edits only — already live through the symlinks; no re-stow, no reload needed."
fi
+174
View File
@@ -0,0 +1,174 @@
#!/usr/bin/env bash
# reconcile-hyde.sh — reconcile a HyDE update with your dots-tracked configs.
#
# HyDE's updater (`Scripts/install.sh -r`) overwrites every config listed in
# Scripts/restore_cfg.psv — including ~/.config/hypr/*. It backs the old ones up to
# ~/.config/cfg_backups and REPLACES your stow symlinks with real files (HyDE's new
# defaults). This tool, run ON THE GUI MACHINE right after that update, shows per file:
# your dots version vs HyDE's new one
# lets you keep / take / merge each, then removes the severed real files and re-runs
# install.sh so everything is symlinked back to the repo.
#
# ./bin/reconcile-hyde.sh [host] report only — safe, changes nothing (default)
# ./bin/reconcile-hyde.sh -i [host] interactive: decide each conflicting file
# ./bin/reconcile-hyde.sh --relink [host] skip decisions: back up severed files,
# then re-stow (repo versions win)
#
# host defaults to `hostname -s`. Commit your repo first so choices are reviewable/revertable.
set -uo pipefail
# Config subtrees where HyDE and your dots overlap. Add/remove as your setup needs.
SUBTREES=(.config/hypr .config/waybar)
# --- args ---
MODE=report
HOST=""
for a in "$@"; do
case "$a" in
-i|--interactive) MODE=interactive ;;
--relink) MODE=relink ;;
-h|--help) awk 'NR > 1 && !/^#/ { exit } NR > 1' "$0"; exit 0 ;;
-*) echo "unknown option: $a" >&2; exit 2 ;;
*) HOST="$a" ;;
esac
done
[ -z "$HOST" ] && HOST="$(hostname -s)"
skip_relink=() # files the user chose to skip during interactive reconcile
DOTS="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")/.." && pwd)" # repo root (script in bin/)
[ -x "$DOTS/install.sh" ] || { echo "error: $DOTS/install.sh not found — run from inside the dots repo" >&2; exit 1; }
# repo package search order: host overlay wins, then gui, then common
PKGS=("$HOST" gui common)
repo_src() { # repo_src <rel-path> -> print the repo file stow would link, or nothing
local rel="$1" p
for p in "${PKGS[@]}"; do
[ -f "$DOTS/$p/$rel" ] && { printf '%s\n' "$DOTS/$p/$rel"; return 0; }
done
return 1
}
echo "host=$HOST dots=$DOTS mode=$MODE"
if [ -n "$(git -C "$DOTS" status --porcelain 2>/dev/null)" ]; then
echo "note: $DOTS has uncommitted changes — commit first so reconcile choices are reviewable." >&2
fi
[ -d "$HOME/.config/cfg_backups" ] && echo "HyDE's pre-update backups are in ~/.config/cfg_backups"
echo
# --- classify every live file under the managed subtrees ---
linked=0; foreign=0
same=(); conflicts=(); new_files=()
for st in "${SUBTREES[@]}"; do
[ -d "$HOME/$st" ] || continue
while IFS= read -r -d '' live; do
rel="${live#"$HOME"/}"
if [ -L "$live" ]; then # still a symlink
tgt="$(readlink -f "$live" 2>/dev/null || true)"
case "$tgt" in
"$DOTS"/*) linked=$((linked+1)) ;; # intact -> HyDE didn't sever it
*) foreign=$((foreign+1)); echo " ? $rel -> symlink outside repo: $tgt" ;;
esac
continue
fi
# real file: HyDE overwrote (severed) it, or it is brand new
src="$(repo_src "$rel" || true)"
if [ -z "$src" ]; then
new_files+=("$rel")
elif diff -q "$src" "$live" >/dev/null 2>&1; then
same+=("$rel") # content == repo; just relink
else
conflicts+=("$rel") # HyDE's new content differs from yours
fi
done < <(find "$HOME/$st" \( -type f -o -type l \) -print0)
done
echo "== summary =="
echo " intact symlinks (untouched): $linked"
echo " severed but identical (relink): ${#same[@]}"
echo " severed & CHANGED (need decision): ${#conflicts[@]}"
echo " new HyDE files not tracked by dots: ${#new_files[@]}"
[ "$foreign" -gt 0 ] && echo " foreign symlinks flagged above: $foreign"
echo
if [ "$linked" -gt 0 ]; then
echo "For intact symlinks, check whether HyDE wrote THROUGH them into the repo:"
echo " git -C $DOTS diff -- '*/.config/hypr/*' '*/.config/waybar/*'"
echo
fi
if [ "${#new_files[@]}" -gt 0 ]; then
echo "New HyDE files (left as-is; add to a package + re-stow if you want them tracked):"
printf ' %s\n' "${new_files[@]}"
echo
fi
if [ "${#conflicts[@]}" -gt 0 ]; then
echo "Changed files (your dots version vs HyDE's new default):"
for rel in "${conflicts[@]}"; do
src="$(repo_src "$rel")"
printf ' %-45s %s changed lines\n' "$rel" "$(diff "$src" "$HOME/$rel" | grep -cE '^[<>]')"
done
echo
fi
# report-only ends here
if [ "$MODE" = report ]; then
if [ "${#conflicts[@]}" -gt 0 ]; then
echo "Re-run with -i to decide each changed file, or --relink to keep your repo versions wholesale."
elif [ "${#same[@]}" -gt 0 ]; then
echo "No content conflicts. Re-run with --relink to drop the severed files and re-symlink."
else
echo "Nothing to reconcile."
fi
exit 0
fi
# --- interactive: decide each changed file, writing the choice into the repo copy ---
if [ "$MODE" = interactive ] && [ "${#conflicts[@]}" -gt 0 ]; then
for rel in "${conflicts[@]}"; do
src="$(repo_src "$rel")"; live="$HOME/$rel"
echo "──────── $rel ────────"
echo " repo (yours): ${src#"$DOTS"/}"
diff "$src" "$live" | sed 's/^/ /' | head -60
echo " [k]eep yours (default) [t]ake HyDE's [m]erge in \$EDITOR -d [s]kip"
read -r -p " choice> " ans </dev/tty || ans=k
case "$ans" in
t|take) cp "$live" "$src"; echo " -> took HyDE's version into $src" ;;
m|merge) "${EDITOR:-nvim}" -d "$src" "$live" </dev/tty >/dev/tty 2>&1; echo " -> merged (saved $src)" ;;
s|skip) echo " -> skipped (left severed; not relinked)"; skip_relink+=("$rel") ;;
*) echo " -> kept your repo version" ;;
esac
done
echo
fi
# --- relink: back up severed files that the repo owns, remove them, re-stow ---
BK="$HOME/.config/hyde-reconcile-backup-$(date +%Y%m%d-%H%M%S)"
to_relink=()
for st in "${SUBTREES[@]}"; do
[ -d "$HOME/$st" ] || continue
while IFS= read -r -d '' live; do
[ -L "$live" ] && continue # only real (severed) files
rel="${live#"$HOME"/}"
repo_src "$rel" >/dev/null || continue # only files the repo can provide
for s in "${skip_relink[@]}"; do [ "$s" = "$rel" ] && continue 2; done
to_relink+=("$rel")
done < <(find "$HOME/$st" -type f -print0)
done
if [ "${#to_relink[@]}" -eq 0 ]; then
echo "nothing to relink."; exit 0
fi
echo "will back up + remove ${#to_relink[@]} severed file(s), then re-stow so they link to the repo:"
printf ' %s\n' "${to_relink[@]}"
read -r -p "proceed? [y/N] " go </dev/tty || go=n
case "$go" in y|Y|yes) ;; *) echo "aborted — nothing changed."; exit 0 ;; esac
for rel in "${to_relink[@]}"; do
mkdir -p "$BK/$(dirname "$rel")"
cp -a "$HOME/$rel" "$BK/$rel"
rm -f "$HOME/$rel"
done
echo "backed up to $BK; removed severed files. re-stowing…"
"$DOTS/install.sh" "$HOST"
echo
echo "done. verify a couple of links resolve into the repo, e.g.:"
echo " readlink ~/.config/hypr/keybindings.conf"