@sebastienrousseau/dotfiles 0.2.502 → 0.2.504

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (412) hide show
  1. package/CHANGELOG.md +109 -9
  2. package/LICENSE +21 -1283
  3. package/README.md +6 -4
  4. package/docs/CONFIG_STRATEGY.md +124 -0
  5. package/docs/COPYRIGHT +1 -1
  6. package/docs/GOVERNANCE.md +98 -0
  7. package/docs/MAINTAINERS.md +41 -0
  8. package/docs/OPENCODE.md +127 -0
  9. package/docs/README.md +2 -0
  10. package/docs/STRUCTURE.md +102 -0
  11. package/docs/adr/ADR-011-nushell-tier3-keep.md +2 -2
  12. package/docs/architecture/AI_COST_OPTIMIZATION.md +143 -0
  13. package/docs/architecture/REPO_LAYOUT.md +8 -8
  14. package/docs/archive/MILESTONE_v0.2.493.md +1 -1
  15. package/docs/index.md +2 -2
  16. package/docs/interop/POWERSHELL.md +1 -1
  17. package/docs/manual/00-introduction.md +1 -1
  18. package/docs/manual/01-concepts/02-trust-model.md +1 -1
  19. package/docs/manual/03-reference/02-config-files.md +2 -2
  20. package/docs/manual/_toc.yml +1 -1
  21. package/docs/manual/command-index.md +72 -59
  22. package/docs/operations/CI_COMPOSITES.md +2 -2
  23. package/docs/operations/COMPLETIONS.md +2 -2
  24. package/docs/operations/COVERAGE.md +5 -5
  25. package/docs/operations/HARD_AUDIT_2026.md +11 -11
  26. package/docs/operations/MAINTENANCE.md +3 -3
  27. package/docs/operations/MANIFEST.md +127 -0
  28. package/docs/operations/RELEASE_PIPELINE.md +130 -0
  29. package/docs/operations/RFC_v0_2_503_reorganization.md +280 -0
  30. package/docs/operations/ROADMAP_2026.md +6 -6
  31. package/docs/operations/ROADMAP_V0_2_503.md +134 -0
  32. package/docs/operations/TESTING.md +17 -0
  33. package/docs/operations/TRACEABILITY.md +6 -3
  34. package/docs/operations/VERSION_SYNC.md +4 -4
  35. package/docs/reference/POWERSHELL_PARITY.md +8 -7
  36. package/docs/schema/dot-env-v1.json +110 -0
  37. package/docs/security/CI_EGRESS_ALLOWLIST.md +1 -1
  38. package/docs/security/CI_PINNING.md +17 -9
  39. package/docs/security/DEPS_DEV_EXCEPTIONS.md +2 -2
  40. package/docs/security/FUZZING.md +114 -0
  41. package/docs/security/INSTALL_VERIFICATION.md +2 -2
  42. package/docs/security/POLICY_RELEASES.md +2 -2
  43. package/docs/security/SCORECARD.md +58 -3
  44. package/docs/security/SHELL_EXEMPTIONS.md +4 -4
  45. package/docs/security/VERIFY_RELEASE.md +201 -0
  46. package/install.sh +118 -5
  47. package/package.json +1 -1
  48. package/scripts/README.md +123 -0
  49. package/scripts/ci/check-copyright-headers.sh +4 -93
  50. package/scripts/ci/check-shell-preamble.sh +4 -103
  51. package/scripts/ci/guard-gitleaks-checkout.sh +4 -54
  52. package/scripts/diagnostics/a2a-conformance.sh +4 -4
  53. package/scripts/diagnostics/alias-governance.sh +1 -1
  54. package/scripts/diagnostics/aliases-cheatsheet.sh +2 -2
  55. package/scripts/diagnostics/benchmark.sh +5 -5
  56. package/scripts/diagnostics/conflicts.sh +2 -2
  57. package/scripts/diagnostics/doctor-unified.sh +3 -3
  58. package/scripts/diagnostics/doctor.sh +10 -10
  59. package/scripts/diagnostics/drift-dashboard.sh +2 -2
  60. package/scripts/diagnostics/health.sh +4 -4
  61. package/scripts/diagnostics/history-analysis.sh +2 -2
  62. package/scripts/diagnostics/mcp-doctor.sh +10 -7
  63. package/scripts/diagnostics/perf.sh +5 -5
  64. package/scripts/diagnostics/scorecard.sh +4 -4
  65. package/scripts/diagnostics/security-score.sh +25 -6
  66. package/scripts/diagnostics/smoke-test.sh +2 -2
  67. package/scripts/diagnostics/snapshot.sh +2 -2
  68. package/scripts/diagnostics/verify.sh +4 -4
  69. package/scripts/diagnostics/version-locks.sh +13 -3
  70. package/scripts/diagnostics/workstation-attestation.sh +14 -14
  71. package/scripts/dot/commands/agent.sh +8 -0
  72. package/scripts/dot/commands/agents.sh +14 -4
  73. package/scripts/dot/commands/ai.sh +156 -37
  74. package/scripts/dot/commands/appearance.sh +2 -2
  75. package/scripts/dot/commands/core.sh +2 -2
  76. package/scripts/dot/commands/diagnostics.sh +5 -5
  77. package/scripts/dot/commands/env-emit.sh +202 -0
  78. package/scripts/dot/commands/fleet.sh +22 -16
  79. package/scripts/dot/commands/init.sh +4 -4
  80. package/scripts/dot/commands/lint.sh +9 -4
  81. package/scripts/dot/commands/manual.sh +3 -3
  82. package/scripts/dot/commands/meta.sh +12 -6
  83. package/scripts/dot/commands/patterns.sh +2 -2
  84. package/scripts/dot/commands/registry.sh +4 -4
  85. package/scripts/dot/commands/restore.sh +4 -4
  86. package/scripts/dot/commands/secrets.sh +4 -3
  87. package/scripts/dot/commands/security.sh +2 -2
  88. package/scripts/dot/commands/tools.sh +13 -3
  89. package/scripts/dot/powershell/Dot.psm1 +199 -0
  90. package/scripts/fonts/install-nerd-fonts.sh +2 -2
  91. package/scripts/git-hooks/pre-commit-audit.sh +3 -3
  92. package/scripts/git-hooks/pre-push +13 -0
  93. package/scripts/ops/ai-setup.sh +1 -1
  94. package/scripts/ops/bundle.sh +3 -3
  95. package/scripts/ops/chaos.sh +2 -2
  96. package/scripts/ops/chezmoi-apply.sh +12 -6
  97. package/scripts/ops/heal.sh +4 -4
  98. package/scripts/ops/post-apply-repair.sh +2 -2
  99. package/scripts/ops/prewarm.sh +2 -2
  100. package/scripts/ops/release.sh +4 -4
  101. package/scripts/ops/rollback.sh +4 -4
  102. package/scripts/ops/setup.sh +2 -2
  103. package/scripts/qa/check-version-consistency.sh +123 -0
  104. package/scripts/qa/coverage-baseline.sh +1 -1
  105. package/scripts/qa/docs-coverage.sh +2 -2
  106. package/scripts/qa/powershell-contract.ps1 +1 -1
  107. package/scripts/qa/scorecard-snapshot.sh +127 -0
  108. package/scripts/security/backup.sh +2 -2
  109. package/scripts/security/dns-doh.sh +4 -4
  110. package/scripts/security/encryption-check.sh +4 -4
  111. package/scripts/security/enforce-policies.sh +2 -2
  112. package/scripts/security/firewall.sh +4 -4
  113. package/scripts/security/lock-screen.sh +4 -4
  114. package/scripts/security/manage-secrets.sh +2 -2
  115. package/scripts/security/ssh-cert.sh +2 -2
  116. package/scripts/security/telemetry-kill.sh +4 -4
  117. package/scripts/security/usb-safety.sh +4 -4
  118. package/scripts/theme/extract-heic-frames.sh +114 -0
  119. package/scripts/theme/rebuild-themes.sh +31 -2
  120. package/scripts/theme/switch.sh +13 -6
  121. package/scripts/theme/wallpaper-sync.sh +297 -93
  122. package/scripts/tuning/linux.sh +2 -2
  123. package/scripts/tuning/macos.sh +2 -2
  124. package/scripts/version-sync.sh +74 -10
  125. package/dot_config/.module-manifest.json +0 -69
  126. package/dot_config/ai/identity.md +0 -23
  127. package/dot_config/ai/patterns/architect.md +0 -16
  128. package/dot_config/ai/patterns/hardener.md +0 -15
  129. package/dot_config/ai/patterns/refactor.md +0 -15
  130. package/dot_config/aider/aider.conf.yml +0 -32
  131. package/dot_config/alacritty/alacritty.toml.tmpl +0 -55
  132. package/dot_config/ansible/ansible.cfg +0 -11
  133. package/dot_config/atuin/config.toml.tmpl +0 -47
  134. package/dot_config/bat/config +0 -23
  135. package/dot_config/brave-flags.conf.tmpl +0 -7
  136. package/dot_config/btop/btop.conf +0 -16
  137. package/dot_config/btop/themes/tokyonight.theme +0 -34
  138. package/dot_config/bun/bunfig.toml.tmpl +0 -33
  139. package/dot_config/claude/mcp_servers.json +0 -20
  140. package/dot_config/containers/containers.conf +0 -14
  141. package/dot_config/curl/dot_curlrc +0 -18
  142. package/dot_config/dlv/config.yml +0 -39
  143. package/dot_config/docker/config.json +0 -15
  144. package/dot_config/dotfiles/agent-card.json +0 -29
  145. package/dot_config/dotfiles/agent-profiles.json +0 -92
  146. package/dot_config/dotfiles/boot/README.md +0 -13
  147. package/dot_config/dotfiles/grub/README.md +0 -13
  148. package/dot_config/dotfiles/lock/README.md +0 -13
  149. package/dot_config/dotfiles/mcp-lock.json +0 -33
  150. package/dot_config/dotfiles/mcp-policy.json +0 -52
  151. package/dot_config/dotfiles/mcp-registry.json +0 -47
  152. package/dot_config/dotfiles/model-registry.json +0 -20
  153. package/dot_config/dotfiles/policy-bundles.json +0 -38
  154. package/dot_config/dotfiles/prompt-registry.json +0 -16
  155. package/dot_config/dotfiles/versions.env +0 -18
  156. package/dot_config/duf/duf.conf +0 -6
  157. package/dot_config/duti/defaults.duti +0 -5
  158. package/dot_config/emoji/emoji.txt +0 -34
  159. package/dot_config/environment.d/50-ssh-agent.conf +0 -2
  160. package/dot_config/environment.d/90-wayland.conf +0 -19
  161. package/dot_config/fastfetch/config.jsonc +0 -28
  162. package/dot_config/firefox/user.js.tmpl +0 -58
  163. package/dot_config/fish/completions/dot-theme-sync.fish.tmpl +0 -9
  164. package/dot_config/fish/completions/dot.fish.tmpl +0 -115
  165. package/dot_config/fish/conf.d/000-perf-cache.fish +0 -56
  166. package/dot_config/fish/conf.d/aliases.fish.tmpl +0 -77
  167. package/dot_config/fish/conf.d/direnv.fish +0 -4
  168. package/dot_config/fish/conf.d/env.fish.tmpl +0 -48
  169. package/dot_config/fish/conf.d/functions.fish.tmpl +0 -22
  170. package/dot_config/fish/conf.d/init.fish.tmpl +0 -172
  171. package/dot_config/fish/conf.d/mise-activate.fish +0 -5
  172. package/dot_config/fish/config.fish.tmpl +0 -44
  173. package/dot_config/fish/fish_plugins +0 -1
  174. package/dot_config/fish/functions/_.fish +0 -3
  175. package/dot_config/fish/functions/_cached_eval.fish +0 -131
  176. package/dot_config/fish/functions/_cached_eval_clear.fish +0 -17
  177. package/dot_config/fish/functions/als.fish +0 -46
  178. package/dot_config/fish/functions/bg-upgrade.fish +0 -7
  179. package/dot_config/fish/functions/c.fish +0 -3
  180. package/dot_config/fish/functions/cat.fish +0 -9
  181. package/dot_config/fish/functions/d.fish +0 -7
  182. package/dot_config/fish/functions/dot.fish +0 -34
  183. package/dot_config/fish/functions/h.fish +0 -3
  184. package/dot_config/fish/functions/l.fish +0 -7
  185. package/dot_config/fish/functions/la.fish +0 -7
  186. package/dot_config/fish/functions/ll.fish +0 -7
  187. package/dot_config/fish/functions/log_error.fish +0 -13
  188. package/dot_config/fish/functions/log_info.fish +0 -13
  189. package/dot_config/fish/functions/lr.fish +0 -7
  190. package/dot_config/fish/functions/lra.fish +0 -7
  191. package/dot_config/fish/functions/ls.fish +0 -7
  192. package/dot_config/fish/functions/lt.fish +0 -7
  193. package/dot_config/fish/functions/lta.fish +0 -7
  194. package/dot_config/fish/functions/notify-run.fish +0 -11
  195. package/dot_config/fish/functions/q.fish +0 -3
  196. package/dot_config/fish/functions/silent-run.fish +0 -7
  197. package/dot_config/fish/functions/yy.fish +0 -8
  198. package/dot_config/flatpak/flatpak.list +0 -4
  199. package/dot_config/fontconfig/fonts.conf.tmpl +0 -57
  200. package/dot_config/foot/foot.ini.tmpl +0 -33
  201. package/dot_config/fuzzel/fuzzel.ini.tmpl +0 -18
  202. package/dot_config/fzf/fzf.zsh +0 -48
  203. package/dot_config/gem/gemrc +0 -9
  204. package/dot_config/gh/config.yml +0 -12
  205. package/dot_config/ghostty/config.tmpl +0 -165
  206. package/dot_config/git/allowed_signers.tmpl +0 -18
  207. package/dot_config/git/attributes +0 -12
  208. package/dot_config/git/commit-template +0 -10
  209. package/dot_config/git/hooks/executable_commit-msg +0 -146
  210. package/dot_config/git/ignore +0 -27
  211. package/dot_config/gnupg/gpg-agent.conf +0 -11
  212. package/dot_config/go/golangci.yml +0 -118
  213. package/dot_config/go/gopls.json +0 -30
  214. package/dot_config/goose/config.yaml +0 -29
  215. package/dot_config/gtk-3.0/gtk.css.tmpl +0 -184
  216. package/dot_config/gtk-3.0/settings.ini.tmpl +0 -27
  217. package/dot_config/gtk-4.0/gtk.css.tmpl +0 -252
  218. package/dot_config/gtk-4.0/settings.ini.tmpl +0 -18
  219. package/dot_config/htop/htoprc +0 -20
  220. package/dot_config/inputrc +0 -2
  221. package/dot_config/ipython/profile_default/ipython_config.py +0 -19
  222. package/dot_config/just/justfile +0 -122
  223. package/dot_config/k9s/config.yaml +0 -65
  224. package/dot_config/k9s/skins/catppuccin-mocha.yaml +0 -116
  225. package/dot_config/kanshi/config.tmpl +0 -22
  226. package/dot_config/karabiner/karabiner.json +0 -14
  227. package/dot_config/kitty/kitty.conf.tmpl +0 -53
  228. package/dot_config/lazydocker/config.yml +0 -186
  229. package/dot_config/lazygit/config.yml +0 -35
  230. package/dot_config/mako/config +0 -47
  231. package/dot_config/mas/masapps.txt +0 -5
  232. package/dot_config/micro/settings.json +0 -3
  233. package/dot_config/mimeapps.list +0 -77
  234. package/dot_config/minikube/config.json +0 -13
  235. package/dot_config/mise/config.toml +0 -99
  236. package/dot_config/mongosh/mongoshrc.js +0 -68
  237. package/dot_config/mpv/input.conf +0 -47
  238. package/dot_config/mpv/mpv.conf +0 -47
  239. package/dot_config/mycli/myclirc +0 -67
  240. package/dot_config/nano/nanorc +0 -28
  241. package/dot_config/ncdu/config +0 -12
  242. package/dot_config/niri/config.kdl.tmpl +0 -327
  243. package/dot_config/nushell/aliases.nu +0 -18
  244. package/dot_config/nushell/cached_eval.nu +0 -80
  245. package/dot_config/nushell/completions.nu.tmpl +0 -52
  246. package/dot_config/nushell/config.nu.tmpl +0 -86
  247. package/dot_config/nushell/env.nu.tmpl +0 -102
  248. package/dot_config/nushell/functions.nu.tmpl +0 -17
  249. package/dot_config/nvim/init.lua +0 -18
  250. package/dot_config/nvim/lazy-lock.json +0 -58
  251. package/dot_config/nvim/lua/config/autocmds.lua +0 -107
  252. package/dot_config/nvim/lua/config/keymaps.lua +0 -92
  253. package/dot_config/nvim/lua/config/lazy.lua +0 -44
  254. package/dot_config/nvim/lua/config/options.lua +0 -49
  255. package/dot_config/nvim/lua/plugins/ai.lua +0 -75
  256. package/dot_config/nvim/lua/plugins/coding.lua +0 -216
  257. package/dot_config/nvim/lua/plugins/completion.lua +0 -60
  258. package/dot_config/nvim/lua/plugins/dap.lua +0 -412
  259. package/dot_config/nvim/lua/plugins/editor.lua +0 -55
  260. package/dot_config/nvim/lua/plugins/git.lua +0 -10
  261. package/dot_config/nvim/lua/plugins/lsp.lua +0 -156
  262. package/dot_config/nvim/lua/plugins/markdown.lua +0 -18
  263. package/dot_config/nvim/lua/plugins/rust.lua +0 -34
  264. package/dot_config/nvim/lua/plugins/sessions.lua +0 -33
  265. package/dot_config/nvim/lua/plugins/ui.lua +0 -509
  266. package/dot_config/paru/paru.conf +0 -10
  267. package/dot_config/pip/pip.conf.tmpl +0 -32
  268. package/dot_config/powershell/Microsoft.PowerShell_profile.ps1.tmpl +0 -81
  269. package/dot_config/pueue/pueue.yml +0 -34
  270. package/dot_config/pypoetry/config.toml +0 -6
  271. package/dot_config/pyrightconfig.json +0 -5
  272. package/dot_config/raycast/README.md +0 -13
  273. package/dot_config/redis/redisclirc +0 -41
  274. package/dot_config/ripgrep/ripgreprc +0 -21
  275. package/dot_config/shell/00-core-paths.sh.tmpl +0 -141
  276. package/dot_config/shell/05-core-safety.sh +0 -48
  277. package/dot_config/shell/10-secrets.sh +0 -41
  278. package/dot_config/shell/40-fzf-defaults.sh.tmpl +0 -17
  279. package/dot_config/shell/40-ls-colors.sh +0 -49
  280. package/dot_config/shell/50-logic-functions-core.sh.tmpl +0 -11
  281. package/dot_config/shell/50-logic-functions.sh.tmpl +0 -11
  282. package/dot_config/shell/51-logic-functions-extra.sh.tmpl +0 -65
  283. package/dot_config/shell/90-ux-aliases.sh.tmpl +0 -121
  284. package/dot_config/shell/91-ux-aliases-lazy.sh.tmpl +0 -55
  285. package/dot_config/shell/Brewfile +0 -207
  286. package/dot_config/shell/Brewfile.cask +0 -92
  287. package/dot_config/shell/Brewfile.cli +0 -127
  288. package/dot_config/shell/README.md +0 -284
  289. package/dot_config/shell/als_data.txt.tmpl +0 -65
  290. package/dot_config/shell/custom/auto_ls.zsh +0 -20
  291. package/dot_config/shell/custom/context_suggest.zsh +0 -68
  292. package/dot_config/shell/custom/error_analysis.zsh +0 -45
  293. package/dot_config/sops/dot_sops.yaml +0 -23
  294. package/dot_config/starship.toml.tmpl +0 -202
  295. package/dot_config/swaylock/config +0 -43
  296. package/dot_config/systemd/user/dotfiles-maintenance.service +0 -8
  297. package/dot_config/systemd/user/dotfiles-maintenance.timer +0 -11
  298. package/dot_config/systemd/user/pueued.service +0 -12
  299. package/dot_config/systemd/user/ssh-agent.service +0 -12
  300. package/dot_config/task/Taskfile.yml +0 -86
  301. package/dot_config/tflint/tflint.hcl +0 -9
  302. package/dot_config/tmux/tmux.conf.tmpl +0 -223
  303. package/dot_config/topgrade.toml.tmpl +0 -54
  304. package/dot_config/user-dirs.dirs +0 -10
  305. package/dot_config/vscode/extensions.txt +0 -11
  306. package/dot_config/vscode/settings.json.tmpl +0 -82
  307. package/dot_config/waybar/config.jsonc.tmpl +0 -90
  308. package/dot_config/waybar/style.css.tmpl +0 -211
  309. package/dot_config/wezterm/wezterm.lua.tmpl +0 -64
  310. package/dot_config/wget/wgetrc +0 -12
  311. package/dot_config/xdg-desktop-portal/niri-portals.conf +0 -5
  312. package/dot_config/yarn/yarnrc.yml +0 -36
  313. package/dot_config/yazi/keymap.toml +0 -67
  314. package/dot_config/yazi/theme.toml +0 -102
  315. package/dot_config/yazi/yazi.toml +0 -40
  316. package/dot_config/zathura/zathurarc +0 -52
  317. package/dot_config/zellij/config.kdl.tmpl +0 -79
  318. package/dot_config/zsh/dot_zprofile +0 -7
  319. package/dot_config/zsh/dot_zshenv +0 -5
  320. package/dot_config/zsh/dot_zshrc.tmpl +0 -688
  321. package/dot_config/zsh/rc.d/00-alias-shims.zsh +0 -99
  322. package/dot_config/zsh/rc.d/05-ssh-agent.zsh +0 -18
  323. package/dot_config/zsh/rc.d/10-env.zsh.tmpl +0 -28
  324. package/dot_config/zsh/rc.d/20-zinit.zsh +0 -65
  325. package/dot_config/zsh/rc.d/30-options.zsh.tmpl +0 -214
  326. package/dot_config/zsh/rc.d/40-bell.zsh +0 -20
  327. package/dot_config/zsh/rc.d/50-login-fortune.zsh +0 -9
  328. package/dot_config/zsh/rc.d/99-alias-wrapper.zsh +0 -32
  329. package/dot_local/bin/executable_ai-update +0 -195
  330. package/dot_local/bin/executable_ai_core +0 -152
  331. package/dot_local/bin/executable_antigravity +0 -11
  332. package/dot_local/bin/executable_b64 +0 -84
  333. package/dot_local/bin/executable_bm +0 -79
  334. package/dot_local/bin/executable_cb +0 -39
  335. package/dot_local/bin/executable_dot +0 -636
  336. package/dot_local/bin/executable_dot-ai +0 -36
  337. package/dot_local/bin/executable_dot-bootstrap +0 -76
  338. package/dot_local/bin/executable_dot-launch-or-focus +0 -52
  339. package/dot_local/bin/executable_dot-load-benchmark +0 -31
  340. package/dot_local/bin/executable_dot-load-benchmark-pty +0 -77
  341. package/dot_local/bin/executable_dot-theme-sync +0 -952
  342. package/dot_local/bin/executable_dot_completion +0 -57
  343. package/dot_local/bin/executable_dtags +0 -28
  344. package/dot_local/bin/executable_epoch +0 -67
  345. package/dot_local/bin/executable_extract +0 -41
  346. package/dot_local/bin/executable_gbd +0 -52
  347. package/dot_local/bin/executable_gd +0 -42
  348. package/dot_local/bin/executable_git-ai-commit +0 -175
  349. package/dot_local/bin/executable_git-ai-diff +0 -169
  350. package/dot_local/bin/executable_gl +0 -101
  351. package/dot_local/bin/executable_hash +0 -161
  352. package/dot_local/bin/executable_hashsum +0 -160
  353. package/dot_local/bin/executable_hex +0 -115
  354. package/dot_local/bin/executable_jsonv +0 -78
  355. package/dot_local/bin/executable_jwt +0 -94
  356. package/dot_local/bin/executable_kill-port +0 -75
  357. package/dot_local/bin/executable_lorem +0 -118
  358. package/dot_local/bin/executable_mkscript +0 -35
  359. package/dot_local/bin/executable_monitor +0 -56
  360. package/dot_local/bin/executable_myip +0 -51
  361. package/dot_local/bin/executable_notify +0 -24
  362. package/dot_local/bin/executable_open +0 -38
  363. package/dot_local/bin/executable_pw +0 -27
  364. package/dot_local/bin/executable_rec-start +0 -46
  365. package/dot_local/bin/executable_rec-stop +0 -35
  366. package/dot_local/bin/executable_regex +0 -132
  367. package/dot_local/bin/executable_start-niri +0 -8
  368. package/dot_local/bin/executable_tmux-sessionizer +0 -314
  369. package/dot_local/bin/executable_tour +0 -177
  370. package/dot_local/bin/executable_up +0 -23
  371. package/dot_local/bin/executable_update +0 -142
  372. package/dot_local/bin/executable_uuid +0 -87
  373. package/dot_local/bin/executable_win +0 -32
  374. package/dot_local/bin/executable_yamlv +0 -57
  375. package/dot_local/share/bash-completion/completions/dot +0 -72
  376. package/dot_local/share/icons/hicolor/128x128/apps/rousseau.png +0 -0
  377. package/dot_local/share/icons/hicolor/16x16/apps/rousseau.png +0 -0
  378. package/dot_local/share/icons/hicolor/24x24/apps/rousseau.png +0 -0
  379. package/dot_local/share/icons/hicolor/256x256/apps/rousseau.png +0 -0
  380. package/dot_local/share/icons/hicolor/32x32/apps/rousseau.png +0 -0
  381. package/dot_local/share/icons/hicolor/48x48/apps/rousseau.png +0 -0
  382. package/dot_local/share/icons/hicolor/512x512/apps/rousseau.png +0 -0
  383. package/dot_local/share/icons/hicolor/64x64/apps/rousseau.png +0 -0
  384. package/dot_local/share/icons/hicolor/96x96/apps/rousseau.png +0 -0
  385. package/dot_local/share/icons/hicolor/scalable/apps/rousseau.png +0 -0
  386. package/dot_local/share/man/man1/dot.1 +0 -149
  387. package/dot_local/share/mise/plugins/kiro-cli/bin/executable_download +0 -64
  388. package/dot_local/share/mise/plugins/kiro-cli/bin/executable_install +0 -18
  389. package/dot_local/share/mise/plugins/kiro-cli/bin/executable_list-all +0 -13
  390. package/dot_local/share/wayland-sessions/niri.desktop.tmpl +0 -6
  391. package/dot_local/share/zsh/completions/.keep +0 -0
  392. package/dot_local/share/zsh/completions/_dot +0 -287
  393. package/scripts/ci/check-dangerous-chmod.sh +0 -19
  394. package/scripts/ci/check-deps-dev.sh +0 -236
  395. package/scripts/ci/check-insecure-tls.sh +0 -61
  396. package/scripts/ci/check-regression-traceability.sh +0 -67
  397. package/scripts/ci/dot-cli-startup-bench.sh +0 -126
  398. package/scripts/ci/install-chezmoi-verified.sh +0 -67
  399. package/scripts/ci/lint-reusable-pins.sh +0 -78
  400. package/scripts/ci/run-coverage.sh +0 -451
  401. package/scripts/ci/validate-chezmoidata.sh +0 -25
  402. package/scripts/ci/validate-ci-config.sh +0 -224
  403. package/scripts/ci/windows-smoke-test.ps1 +0 -136
  404. package/scripts/docs/build-manual.sh +0 -883
  405. package/scripts/docs/check-manual.sh +0 -213
  406. package/scripts/dot/lib/bento.sh +0 -50
  407. package/scripts/dot/lib/log.sh +0 -200
  408. package/scripts/dot/lib/platform.sh +0 -112
  409. package/scripts/dot/lib/ui.sh +0 -650
  410. package/scripts/dot/lib/utils.sh +0 -377
  411. package/scripts/maintenance/check-updates.sh +0 -131
  412. package/scripts/release/package-policy-bundles.sh +0 -125
@@ -1,952 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Copyright (c) 2015-2026 Dotfiles. All rights reserved.
3
- ## dot-theme-sync — Fast theme switching with config regeneration + IPC reload.
4
- ##
5
- ## Sets the active theme in .chezmoidata.toml, regenerates config files via
6
- ## targeted chezmoi apply, then signals running applications to reload.
7
- ##
8
- ## # Usage
9
- ## dot-theme-sync # Regenerate configs + reload running apps
10
- ## dot-theme-sync macos-monterey-light # Set theme + regenerate + reload
11
- ## dot-theme-sync --full # Full chezmoi apply + reload
12
- ## dot-theme-sync --help # Show this help
13
- ##
14
- ## # Supported Applications
15
- ## Ghostty — chezmoi apply + runtime config reload
16
- ## Tmux — chezmoi apply + source-file reload
17
- ## Niri — screen transition
18
- ## Neovim — --remote-expr colorscheme switch (direct IPC, no file needed)
19
- ## Browsers — desktop color-scheme sync + Firefox content preference
20
-
21
- set -euo pipefail
22
-
23
- # =============================================================================
24
- # Constants & Colors
25
- # =============================================================================
26
-
27
- readonly RESET=$'\033[0m'
28
- readonly BOLD=$'\033[1m'
29
- readonly DIM=$'\033[2m'
30
- readonly GREEN=$'\033[32m'
31
- readonly YELLOW=$'\033[33m'
32
- readonly BLUE=$'\033[34m'
33
- readonly RED=$'\033[31m'
34
- readonly CYAN=$'\033[36m'
35
-
36
- # Platform detection (R10: declare and assign separately)
37
- PLATFORM="$(uname -s)"
38
- readonly PLATFORM
39
-
40
- # Portable sed -i (GNU vs BSD/macOS)
41
- _sed_i() {
42
- [[ $# -ge 2 ]] || return 1 # R5: validate args
43
- if [[ "$PLATFORM" == "Darwin" ]]; then
44
- sed -i '' "$@"
45
- else
46
- sed -i "$@"
47
- fi
48
- }
49
-
50
- # Timing — record start in nanoseconds (fallback to seconds * 1000)
51
- if date +%s%N &>/dev/null && [[ "$(date +%s%N)" != *N ]]; then
52
- START_NS=$(date +%s%N)
53
- _elapsed_ms() { echo $((($(date +%s%N) - START_NS) / 1000000)); }
54
- else
55
- START_S=$(date +%s)
56
- _elapsed_ms() { echo $((($(date +%s) - START_S) * 1000)); }
57
- fi
58
-
59
- # =============================================================================
60
- # Source Directory Resolution
61
- # =============================================================================
62
-
63
- resolve_source_dir() {
64
- if [[ -n "${CHEZMOI_SOURCE_DIR:-}" && -d "$CHEZMOI_SOURCE_DIR" ]]; then
65
- echo "$CHEZMOI_SOURCE_DIR"
66
- elif [[ -d "$HOME/.dotfiles" ]]; then
67
- echo "$HOME/.dotfiles"
68
- elif [[ -d "$HOME/.local/share/chezmoi" ]]; then
69
- echo "$HOME/.local/share/chezmoi"
70
- else
71
- echo ""
72
- fi
73
- }
74
-
75
- SRC_DIR="$(resolve_source_dir)"
76
- if [[ -z "$SRC_DIR" ]]; then
77
- printf '%s\n' "${RED}error${RESET}: dotfiles source directory not found"
78
- exit 1
79
- fi
80
-
81
- readonly DATA_FILE="$SRC_DIR/.chezmoidata.toml"
82
- readonly THEMES_FILE="$SRC_DIR/.chezmoidata/themes.toml"
83
- readonly CHEZMOI_CFG="${XDG_CONFIG_HOME:-$HOME/.config}/chezmoi/chezmoi.toml"
84
-
85
- # =============================================================================
86
- # Output Helpers
87
- # =============================================================================
88
-
89
- _ok() { printf ' %s✓%s %-12s %s%s%s\n' "$GREEN" "$RESET" "$1" "$DIM" "$2" "$RESET"; }
90
- _skip() { printf ' %s·%s %-12s %s%s%s\n' "$DIM" "$RESET" "$1" "$DIM" "$2" "$RESET"; }
91
- _err() { printf ' %s✗%s %-12s %s%s%s\n' "$RED" "$RESET" "$1" "$DIM" "$2" "$RESET"; }
92
- _info() { printf ' %s→%s %-12s %s%s%s\n' "$BLUE" "$RESET" "$1" "$DIM" "$2" "$RESET"; }
93
-
94
- join_lines() {
95
- local delimiter="$1"
96
- awk -v d="$delimiter" '
97
- NF {
98
- if (seen++) {
99
- printf "%s", d
100
- }
101
- printf "%s", $0
102
- }
103
- END {
104
- if (seen) {
105
- printf "\n"
106
- }
107
- }
108
- '
109
- }
110
-
111
- # =============================================================================
112
- # Theme Parsing
113
- # =============================================================================
114
-
115
- # Read the current theme from .chezmoidata.toml
116
- current_theme() {
117
- if [[ -f "$CHEZMOI_CFG" ]]; then
118
- local chezmoi_theme
119
- chezmoi_theme="$(awk -F'"' '/^theme =/ {print $2}' "$CHEZMOI_CFG" | head -n 1)"
120
- if [[ -n "$chezmoi_theme" ]]; then
121
- echo "$chezmoi_theme"
122
- return 0
123
- fi
124
- fi
125
- awk -F'"' '/^theme =/ {print $2}' "$DATA_FILE" | head -n 1
126
- }
127
-
128
- # Write a new theme into .chezmoidata.toml AND chezmoi.toml [data] section.
129
- # Both must be updated: chezmoi.toml [data] takes precedence over .chezmoidata.toml.
130
- write_theme() {
131
- local new_theme="${1:-}"
132
- # R5: validate input
133
- if [[ -z "$new_theme" ]]; then
134
- _err "Invalid" "theme name required"
135
- exit 1
136
- fi
137
- if [[ "$new_theme" =~ [^a-zA-Z0-9_-] ]]; then
138
- _err "Invalid" "theme name: $new_theme"
139
- exit 1
140
- fi
141
-
142
- # Update .chezmoidata.toml (source of truth for templates)
143
- local tmp_file
144
- tmp_file="$(umask 077 && mktemp)"
145
- if grep -q '^theme = ' "$DATA_FILE"; then
146
- sed "s/^theme = .*/theme = \"$new_theme\"/" "$DATA_FILE" >"$tmp_file"
147
- else
148
- cat "$DATA_FILE" >"$tmp_file"
149
- printf 'theme = "%s"\n' "$new_theme" >>"$tmp_file"
150
- fi
151
- # R7: check mv return, restore on failure
152
- if ! mv "$tmp_file" "$DATA_FILE"; then
153
- _err "Write" "failed to update $DATA_FILE"
154
- rm -f "$tmp_file"
155
- return 1
156
- fi
157
-
158
- # Update chezmoi.toml [data] section (overrides .chezmoidata.toml)
159
- if [[ -f "$CHEZMOI_CFG" ]] && grep -q '^theme = ' "$CHEZMOI_CFG"; then
160
- tmp_file="$(umask 077 && mktemp)"
161
- sed "s/^theme = .*/theme = \"$new_theme\"/" "$CHEZMOI_CFG" >"$tmp_file"
162
- if ! mv "$tmp_file" "$CHEZMOI_CFG"; then
163
- _err "Write" "failed to update $CHEZMOI_CFG"
164
- rm -f "$tmp_file"
165
- fi
166
- fi
167
- }
168
-
169
- sync_theme_state() {
170
- [[ -f "$DATA_FILE" ]] || return 0
171
- [[ -f "$CHEZMOI_CFG" ]] || return 0
172
- grep -q '^theme = ' "$CHEZMOI_CFG" || return 0
173
-
174
- local data_theme chezmoi_theme
175
- data_theme="$(awk -F'"' '/^theme =/ {print $2}' "$DATA_FILE" | head -n 1)"
176
- chezmoi_theme="$(awk -F'"' '/^theme =/ {print $2}' "$CHEZMOI_CFG" | head -n 1)"
177
-
178
- if [[ -n "$chezmoi_theme" && -n "$data_theme" && "$data_theme" != "$chezmoi_theme" ]]; then
179
- write_theme "$chezmoi_theme"
180
- _info "Theme" "synced data files to chezmoi override ($chezmoi_theme)"
181
- fi
182
- }
183
-
184
- # Extract a value from [themes.<name>.app] section in themes.toml
185
- # Usage: theme_app_value <theme> <key>
186
- theme_app_value() {
187
- local theme="$1" key="$2"
188
- if [[ ! -f "$THEMES_FILE" ]]; then
189
- return 1
190
- fi
191
- # Parse the TOML: find the [themes.<theme>.app] section and extract key
192
- awk -v section="[themes.${theme}.app]" -v key="$key" '
193
- BEGIN { in_section = 0 }
194
- /^\[/ { in_section = ($0 == section) ? 1 : 0; next }
195
- in_section && $0 ~ "^" key " *= *" {
196
- gsub(/^[^"]*"/, ""); gsub(/".*$/, ""); print; exit
197
- }
198
- ' "$THEMES_FILE"
199
- }
200
-
201
- # Extract a top-level value from [themes.<name>] section in themes.toml
202
- # Usage: theme_value <theme> <key>
203
- theme_value() {
204
- local theme="$1" key="$2"
205
- if [[ ! -f "$THEMES_FILE" ]]; then
206
- return 1
207
- fi
208
- awk -v section="[themes.${theme}]" -v key="$key" '
209
- BEGIN { in_section = 0 }
210
- /^\[/ { in_section = ($0 == section) ? 1 : 0; next }
211
- in_section && $0 ~ "^" key " *= *" {
212
- gsub(/^[^"]*"/, ""); gsub(/".*$/, ""); print; exit
213
- }
214
- ' "$THEMES_FILE"
215
- }
216
-
217
- # =============================================================================
218
- # Targeted Config Regeneration
219
- # =============================================================================
220
-
221
- # Regenerate only theme-dependent config files via chezmoi.
222
- # Much faster than a full apply — just renders the templates that use $t.
223
- apply_theme_configs() {
224
- if ! command -v chezmoi &>/dev/null; then
225
- _err "Chezmoi" "not installed"
226
- return 1
227
- fi
228
-
229
- local targets=(
230
- "$HOME/.config/ghostty/config"
231
- "$HOME/.config/tmux/tmux.conf"
232
- "$HOME/.config/alacritty/alacritty.toml"
233
- "$HOME/.config/kitty/kitty.conf"
234
- "$HOME/.config/wezterm/wezterm.lua"
235
- "$HOME/.config/firefox/user.js"
236
- "$HOME/.config/niri/config.kdl"
237
- "$HOME/.config/gtk-3.0/gtk.css"
238
- "$HOME/.config/gtk-3.0/settings.ini"
239
- "$HOME/.config/gtk-4.0/gtk.css"
240
- "$HOME/.config/gtk-4.0/settings.ini"
241
- "$HOME/.config/waybar/config.jsonc"
242
- "$HOME/.config/waybar/style.css"
243
- )
244
-
245
- local applied=()
246
- local target tmp_file
247
- for target in "${targets[@]}"; do
248
- [[ -f "$target" ]] || continue
249
-
250
- if chezmoi apply "$target" 2>/dev/null; then
251
- applied+=("${target##*/}")
252
- continue
253
- fi
254
-
255
- # Some local Niri setups keep ~/.config/niri/config.kdl outside direct
256
- # chezmoi management. Fall back to rendering the managed template so theme
257
- # switches still update active border colors and other palette values.
258
- if [[ "$target" == "$HOME/.config/niri/config.kdl" ]]; then
259
- local niri_template="$SRC_DIR/dot_config/niri/config.kdl.tmpl"
260
- if [[ -f "$niri_template" ]]; then
261
- tmp_file="$(umask 077 && mktemp)"
262
- if chezmoi execute-template <"$niri_template" >"$tmp_file" 2>/dev/null && mv "$tmp_file" "$target"; then
263
- applied+=("${target##*/}")
264
- continue
265
- fi
266
- rm -f "$tmp_file"
267
- fi
268
- fi
269
- done
270
-
271
- if [[ ${#applied[@]} -gt 0 ]]; then
272
- _ok "Chezmoi" "regenerated ${#applied[@]} configs"
273
- else
274
- _skip "Chezmoi" "no managed configs found"
275
- fi
276
- }
277
-
278
- sync_ghostty_macos_config() {
279
- [[ "$PLATFORM" == "Darwin" ]] || return 0
280
-
281
- local xdg_config="$HOME/.config/ghostty/config"
282
- local macos_config="$HOME/Library/Application Support/com.mitchellh.ghostty/config"
283
- local macos_dir
284
- macos_dir="$(dirname "$macos_config")"
285
-
286
- [[ -f "$xdg_config" ]] || return 0
287
- [[ -d "$macos_dir" ]] || return 0
288
-
289
- if [[ -f "$macos_config" ]] && cmp -s "$xdg_config" "$macos_config"; then
290
- return 0
291
- fi
292
-
293
- if cp "$xdg_config" "$macos_config" 2>/dev/null; then
294
- _ok "Ghostty" "mirrored config to macOS app support"
295
- else
296
- _skip "Ghostty" "macOS app support config could not be updated"
297
- fi
298
- }
299
-
300
- # =============================================================================
301
- # Application Reload Functions
302
- # =============================================================================
303
-
304
- # Track results for summary
305
- declare -a RELOADED=()
306
- declare -a SKIPPED=()
307
-
308
- reload_ghostty() {
309
- # Ghostty GTK exposes reload-config via DBus (org.gtk.Actions).
310
- # This is the most reliable method — SIGUSR1 isn't caught by all builds,
311
- # and chezmoi's atomic writes bypass inotify file watches.
312
- local dbus_name="com.mitchellh.ghostty"
313
- local dbus_path="/com/mitchellh/ghostty"
314
-
315
- if busctl --user call "${dbus_name}" "${dbus_path}" \
316
- org.gtk.Actions Activate "sava{sv}" "reload-config" 0 0 2>/dev/null; then
317
- RELOADED+=("ghostty")
318
- _ok "Ghostty" "DBus reload-config"
319
- return
320
- fi
321
-
322
- # Fallback: signal the main process directly.
323
- # Ghostty's documented runtime reload path maps to SIGUSR2.
324
- local main_pid
325
- # -o (oldest) is GNU pgrep only; fall back to first match.
326
- # On macOS app bundles can expose Ghostty under different process labels,
327
- # so match both the executable name and bundle path.
328
- main_pid="$(
329
- pgrep -x -o ghostty 2>/dev/null ||
330
- pgrep -x -o Ghostty 2>/dev/null ||
331
- pgrep -f -o '/Applications/Ghostty\.app/Contents/MacOS/ghostty' 2>/dev/null ||
332
- pgrep -f -o '/Applications/ghostty\.app/Contents/MacOS/ghostty' 2>/dev/null ||
333
- pgrep -f -o 'com\.mitchellh\.ghostty' 2>/dev/null ||
334
- pgrep -x ghostty 2>/dev/null | head -1 ||
335
- pgrep -x Ghostty 2>/dev/null | head -1 ||
336
- true
337
- )"
338
- if [[ -n "$main_pid" ]]; then
339
- # macOS: direct signal is the only reliable non-interactive path.
340
- if [[ "$(uname -s)" == "Darwin" ]]; then
341
- if kill -SIGUSR2 "$main_pid" 2>/dev/null; then
342
- RELOADED+=("ghostty")
343
- _ok "Ghostty" "SIGUSR2 → PID $main_pid"
344
- return
345
- fi
346
- fi
347
- # Linux: verify signal handler before sending
348
- if [[ -r "/proc/$main_pid/status" ]]; then
349
- local sigcgt
350
- sigcgt="$(awk '/^SigCgt:/{print $2}' "/proc/$main_pid/status" 2>/dev/null || true)"
351
- if [[ -n "$sigcgt" ]] && ((16#$sigcgt & 0x400)); then
352
- if kill -SIGUSR2 "$main_pid" 2>/dev/null; then
353
- RELOADED+=("ghostty")
354
- _ok "Ghostty" "SIGUSR2 → PID $main_pid"
355
- return
356
- fi
357
- fi
358
- fi
359
- fi
360
-
361
- SKIPPED+=("ghostty")
362
- _skip "Ghostty" "config regenerated but no runtime reload target was found"
363
- }
364
-
365
- reload_tmux() {
366
- if ! command -v tmux &>/dev/null; then
367
- SKIPPED+=("tmux")
368
- _skip "Tmux" "not installed"
369
- return
370
- fi
371
- if ! tmux list-sessions &>/dev/null; then
372
- SKIPPED+=("tmux")
373
- _skip "Tmux" "no active sessions"
374
- return
375
- fi
376
- local conf="$HOME/.config/tmux/tmux.conf"
377
- if [[ ! -f "$conf" ]]; then
378
- conf="$HOME/.tmux.conf"
379
- fi
380
- if [[ ! -f "$conf" ]]; then
381
- SKIPPED+=("tmux")
382
- _skip "Tmux" "config not found"
383
- return
384
- fi
385
- # source-file may return non-zero if plugins (TPM) aren't installed,
386
- # but the theme/colors still reload successfully — treat as success.
387
- local out
388
- out="$(tmux source-file "$conf" 2>&1)" || true
389
- RELOADED+=("tmux")
390
- if [[ -n "$out" ]]; then
391
- _ok "Tmux" "source-file (warnings: ${out##*: })"
392
- else
393
- _ok "Tmux" "source-file $conf"
394
- fi
395
- }
396
-
397
- reload_niri() {
398
- if ! command -v niri &>/dev/null; then
399
- SKIPPED+=("niri")
400
- _skip "Niri" "not installed"
401
- return
402
- fi
403
- if ! pgrep -x niri &>/dev/null; then
404
- SKIPPED+=("niri")
405
- _skip "Niri" "not running"
406
- return
407
- fi
408
- # Reload config (picks up new colors) then trigger visual transition
409
- niri msg action load-config-file 2>/dev/null || true
410
- if niri msg action do-screen-transition 2>/dev/null; then
411
- RELOADED+=("niri")
412
- _ok "Niri" "config reloaded + transition"
413
- else
414
- SKIPPED+=("niri")
415
- _skip "Niri" "IPC unavailable"
416
- fi
417
- }
418
-
419
- reload_desktop() {
420
- local theme="$1"
421
- local mode gtk_theme gtk_icon color_scheme
422
- mode="$(theme_value "$theme" "mode" 2>/dev/null || echo "dark")"
423
- gtk_theme="$(theme_app_value "$theme" "gtk_theme" 2>/dev/null || true)"
424
- gtk_icon="$(theme_app_value "$theme" "gtk_icon" 2>/dev/null || true)"
425
-
426
- # macOS desktop integration: apply dark/light appearance and accent color.
427
- if [[ "$(uname -s)" == "Darwin" ]]; then
428
- if ! command -v osascript &>/dev/null; then
429
- SKIPPED+=("desktop")
430
- _skip "Desktop" "osascript not available"
431
- return
432
- fi
433
-
434
- local dark_bool
435
- local accent="-1" # Graphite fallback
436
- local changed=0
437
-
438
- if [[ "$mode" == "light" ]]; then
439
- dark_bool="false"
440
- color_scheme="light"
441
- else
442
- dark_bool="true"
443
- color_scheme="dark"
444
- fi
445
-
446
- # Read macos_accent from themes.toml (set by extract-theme.py from wallpaper hue)
447
- local themes_file="$SRC_DIR/.chezmoidata/themes.toml"
448
- if [[ -f "$themes_file" ]]; then
449
- local toml_accent
450
- toml_accent="$(awk -v n="$theme" '
451
- $0 == "[themes." n "]" { found=1; next }
452
- /^\[/ { found=0 }
453
- found && /^macos_accent/ { sub(/.*= */, ""); print; exit }
454
- ' "$themes_file")"
455
- if [[ -n "$toml_accent" ]]; then
456
- accent="$toml_accent"
457
- fi
458
- fi
459
-
460
- if osascript -e "tell application \"System Events\" to tell appearance preferences to set dark mode to $dark_bool" >/dev/null 2>&1; then
461
- changed=1
462
- fi
463
-
464
- # Accent/highlight for consistency with selected theme family.
465
- # Map accent to matching highlight color (RGB + name)
466
- local highlight_color
467
- case "$accent" in
468
- -1) highlight_color="0.847059 0.847059 0.862745 Graphite" ;;
469
- 0) highlight_color="0.968627 0.831373 0.792157 Red" ;;
470
- 1) highlight_color="0.968627 0.890196 0.745098 Orange" ;;
471
- 2) highlight_color="1.000000 0.937255 0.690196 Yellow" ;;
472
- 3) highlight_color="0.752941 0.964706 0.678431 Green" ;;
473
- 4) highlight_color="0.698039 0.843137 1.000000 Blue" ;;
474
- 5) highlight_color="0.968627 0.831373 1.000000 Purple" ;;
475
- 6) highlight_color="1.000000 0.749020 0.823529 Pink" ;;
476
- *) highlight_color="0.698039 0.843137 1.000000 Blue" ;;
477
- esac
478
-
479
- if defaults write -g AppleAccentColor -int "$accent" >/dev/null 2>&1 &&
480
- defaults write -g AppleHighlightColor -string "$highlight_color" >/dev/null 2>&1; then
481
- changed=1
482
- fi
483
-
484
- if [[ $changed -gt 0 ]]; then
485
- # Force running apps to pick up the new accent/highlight preferences
486
- killall -HUP cfprefsd 2>/dev/null || true
487
- killall SystemUIServer 2>/dev/null || true
488
- killall Dock 2>/dev/null || true
489
- killall "System Settings" 2>/dev/null || true
490
- RELOADED+=("desktop")
491
- _ok "Desktop" "macOS ${color_scheme}, accent ${accent}"
492
- else
493
- SKIPPED+=("desktop")
494
- _skip "Desktop" "macOS appearance unchanged"
495
- fi
496
- return
497
- fi
498
-
499
- if ! command -v gsettings &>/dev/null; then
500
- SKIPPED+=("desktop")
501
- _skip "Desktop" "gsettings not available"
502
- return
503
- fi
504
-
505
- if [[ "$mode" == "light" ]]; then
506
- color_scheme="prefer-light"
507
- else
508
- color_scheme="prefer-dark"
509
- fi
510
-
511
- local changed=0
512
-
513
- # Set dark/light mode preference
514
- if gsettings set org.gnome.desktop.interface color-scheme "$color_scheme" 2>/dev/null; then
515
- changed=1
516
- fi
517
-
518
- # Set GTK theme
519
- if [[ -n "$gtk_theme" ]]; then
520
- gsettings set org.gnome.desktop.interface gtk-theme "$gtk_theme" 2>/dev/null && changed=1
521
- fi
522
-
523
- # Set icon theme
524
- if [[ -n "$gtk_icon" ]]; then
525
- gsettings set org.gnome.desktop.interface icon-theme "$gtk_icon" 2>/dev/null && changed=1
526
- fi
527
-
528
- # DMS (Dank Material Shell) — prefer dynamic theme colors generated from the
529
- # current wallpaper instead of forcing a stock palette in settings.
530
- if command -v dms &>/dev/null; then
531
- # DMS theme switch: write to settings.json in-place.
532
- # DMS FileView watches the file and triggers onLoaded → applyStoredTheme.
533
- # NOTE: mv (atomic write) breaks the inotify watch — must use sed -i.
534
- local dms_settings="${XDG_CONFIG_HOME:-$HOME/.config}/DankMaterialShell/settings.json"
535
- if [[ -f "$dms_settings" ]]; then
536
- _sed_i \
537
- -e 's/"currentThemeName": *"[^"]*"/"currentThemeName": "dynamic"/' \
538
- -e 's/"currentThemeCategory": *"[^"]*"/"currentThemeCategory": "dynamic"/' \
539
- "$dms_settings"
540
- changed=1
541
- fi
542
-
543
- # Keep DMS theme mode in automatic mode across restarts. The shell's
544
- # session state owns light/dark automation, so avoid forcing manual mode
545
- # here via `dms ipc theme light|dark`.
546
- local dms_session="${XDG_STATE_HOME:-$HOME/.local/state}/DankMaterialShell/session.json"
547
- if [[ -f "$dms_session" ]]; then
548
- _sed_i \
549
- -e 's/"themeModeAutoEnabled": *false/"themeModeAutoEnabled": true/' \
550
- -e 's/"themeModeAutoMode": *"[^"]*"/"themeModeAutoMode": "time"/' \
551
- "$dms_session"
552
- fi
553
- fi
554
-
555
- if [[ $changed -gt 0 ]]; then
556
- RELOADED+=("desktop")
557
- _ok "Desktop" "$color_scheme, ${gtk_theme:-default}"
558
- else
559
- SKIPPED+=("desktop")
560
- _skip "Desktop" "gsettings failed"
561
- fi
562
- }
563
-
564
- firefox_profile_roots() {
565
- if [[ "$PLATFORM" == "Darwin" ]]; then
566
- printf '%s\n' "$HOME/Library/Application Support/Firefox/Profiles"
567
- else
568
- printf '%s\n' "$HOME/.mozilla/firefox"
569
- fi
570
- }
571
-
572
- reload_browsers() {
573
- local theme="$1"
574
- local mode browser_scope
575
- mode="$(theme_value "$theme" "mode" 2>/dev/null || echo "dark")"
576
-
577
- if [[ "$PLATFORM" == "Darwin" ]]; then
578
- browser_scope="macOS appearance"
579
- else
580
- browser_scope="desktop color-scheme"
581
- fi
582
-
583
- local coordinated=()
584
- local managed_firefox="${XDG_CONFIG_HOME:-$HOME/.config}/firefox/user.js"
585
- local firefox_roots=()
586
- local firefox_profiles=()
587
- local root profile
588
-
589
- if [[ "$PLATFORM" == "Darwin" ]]; then
590
- [[ -d "/Applications/Safari.app" ]] && coordinated+=("Safari")
591
- [[ -d "/Applications/Google Chrome.app" ]] && coordinated+=("Chrome")
592
- [[ -d "/Applications/Microsoft Edge.app" ]] && coordinated+=("Edge")
593
- else
594
- command -v google-chrome &>/dev/null && coordinated+=("Chrome")
595
- command -v google-chrome-stable &>/dev/null && coordinated+=("Chrome")
596
- command -v chromium &>/dev/null && coordinated+=("Chromium")
597
- command -v chromium-browser &>/dev/null && coordinated+=("Chromium")
598
- command -v microsoft-edge &>/dev/null && coordinated+=("Edge")
599
- command -v microsoft-edge-stable &>/dev/null && coordinated+=("Edge")
600
- fi
601
-
602
- while IFS= read -r root; do
603
- [[ -d "$root" ]] && firefox_roots+=("$root")
604
- done < <(firefox_profile_roots)
605
-
606
- for root in "${firefox_roots[@]}"; do
607
- for profile in "$root"/*; do
608
- [[ -d "$profile" ]] || continue
609
- firefox_profiles+=("$profile")
610
- done
611
- done
612
-
613
- local synced_firefox_profiles=0
614
- if [[ -f "$managed_firefox" ]]; then
615
- for profile in "${firefox_profiles[@]}"; do
616
- if [[ -f "$profile/user.js" ]] && cmp -s "$managed_firefox" "$profile/user.js"; then
617
- synced_firefox_profiles=$((synced_firefox_profiles + 1))
618
- fi
619
- done
620
- fi
621
-
622
- local summary_parts=()
623
- if [[ ${#coordinated[@]} -gt 0 ]]; then
624
- local native
625
- native="$(
626
- printf '%s\n' "${coordinated[@]}" | awk '!seen[$0]++' | join_lines ", "
627
- )"
628
- summary_parts+=("${native} follow ${browser_scope}")
629
- fi
630
-
631
- if [[ -f "$managed_firefox" ]]; then
632
- if [[ $synced_firefox_profiles -gt 0 ]]; then
633
- summary_parts+=("Firefox content mode synced for ${synced_firefox_profiles} profile(s)")
634
- elif [[ ${#firefox_profiles[@]} -gt 0 ]]; then
635
- summary_parts+=("Firefox content mode ready; link ~/.config/firefox/user.js into a profile to enforce it")
636
- else
637
- summary_parts+=("Firefox content mode regenerated")
638
- fi
639
- fi
640
-
641
- if [[ ${#summary_parts[@]} -eq 0 ]]; then
642
- SKIPPED+=("browsers")
643
- _skip "Browsers" "no supported browsers detected"
644
- return
645
- fi
646
-
647
- local detail
648
- detail="$(
649
- printf '%s\n' "${summary_parts[@]}" | join_lines "; "
650
- )"
651
- RELOADED+=("browsers")
652
- _ok "Browsers" "${mode} via ${detail}"
653
- }
654
-
655
- reload_nvim() {
656
- local theme="$1"
657
- local nvim_colorscheme nvim_style
658
- nvim_colorscheme="$(theme_app_value "$theme" "nvim" 2>/dev/null || true)"
659
- nvim_style="$(theme_app_value "$theme" "nvim_style" 2>/dev/null || true)"
660
-
661
- if [[ -z "$nvim_colorscheme" ]]; then
662
- SKIPPED+=("nvim")
663
- _skip "Neovim" "no nvim colorscheme for theme '$theme'"
664
- return
665
- fi
666
-
667
- # Build the Lua expression for runtime colorscheme switching.
668
- # This mirrors the logic in dot_config/nvim/lua/plugins/ui.lua.
669
- local lua_cmd
670
- case "$nvim_colorscheme" in
671
- catppuccin)
672
- local flavour="${nvim_style:-mocha}"
673
- lua_cmd="require('catppuccin').setup({flavour='${flavour}'}) vim.cmd.colorscheme('catppuccin')"
674
- ;;
675
- tokyonight-*)
676
- lua_cmd="require('tokyonight').setup({style='${nvim_style:-night}'}) vim.cmd.colorscheme('${nvim_colorscheme}')"
677
- ;;
678
- kanagawa)
679
- local variant="${nvim_style:-wave}"
680
- lua_cmd="require('kanagawa').setup({theme='${variant}'}) vim.cmd.colorscheme('kanagawa')"
681
- ;;
682
- gruvbox)
683
- local bg="dark"
684
- [[ "$nvim_style" == "light" ]] && bg="light"
685
- lua_cmd="vim.o.background='${bg}' require('gruvbox').setup({contrast='hard'}) vim.cmd.colorscheme('gruvbox')"
686
- ;;
687
- everforest)
688
- local bg="dark"
689
- [[ "$nvim_style" == "light" ]] && bg="light"
690
- lua_cmd="vim.o.background='${bg}' vim.cmd.colorscheme('everforest')"
691
- ;;
692
- solarized)
693
- local bg="dark"
694
- [[ "$nvim_style" == "light" ]] && bg="light"
695
- lua_cmd="vim.o.background='${bg}' require('solarized').setup({}) vim.cmd.colorscheme('solarized')"
696
- ;;
697
- onedark)
698
- local style="dark"
699
- [[ "$nvim_style" == "light" ]] && style="light"
700
- lua_cmd="require('onedark').setup({style='${style}'}) vim.cmd.colorscheme('onedark')"
701
- ;;
702
- rose-pine*)
703
- lua_cmd="vim.cmd.colorscheme('${nvim_colorscheme}')"
704
- ;;
705
- dracula)
706
- lua_cmd="vim.cmd.colorscheme('dracula')"
707
- ;;
708
- nord)
709
- lua_cmd="require('nord').set()"
710
- ;;
711
- *)
712
- lua_cmd="vim.cmd.colorscheme('${nvim_colorscheme}')"
713
- ;;
714
- esac
715
-
716
- # Find all running nvim server sockets.
717
- # Neovim versions use different socket paths:
718
- # 0.9-: /tmp/nvimXXXXXX/0 (random suffix, no dot)
719
- # 0.10+: $XDG_RUNTIME_DIR/nvim.PID.0
720
- local sockets=()
721
- local runtime_dir="${XDG_RUNTIME_DIR:-/run/user/$(id -u)}"
722
-
723
- # Collect candidate sockets from known locations
724
- local sock
725
- for sock in /tmp/nvim*/0; do
726
- [[ -S "$sock" ]] && sockets+=("$sock")
727
- done
728
- for sock in /run/user/*/nvim.*.0; do
729
- [[ -S "$sock" ]] && sockets+=("$sock")
730
- done
731
- if [[ -d "$runtime_dir" ]]; then
732
- for sock in "$runtime_dir"/nvim.*.0; do
733
- [[ -S "$sock" ]] && sockets+=("$sock")
734
- done
735
- fi
736
-
737
- # Deduplicate sockets
738
- if [[ ${#sockets[@]} -gt 0 ]]; then
739
- local -A seen=()
740
- local unique_sockets=()
741
- local s
742
- for s in "${sockets[@]}"; do
743
- if [[ -z "${seen[$s]:-}" ]]; then
744
- seen[$s]=1
745
- unique_sockets+=("$s")
746
- fi
747
- done
748
- sockets=("${unique_sockets[@]}")
749
- fi
750
-
751
- if [[ ${#sockets[@]} -eq 0 ]]; then
752
- SKIPPED+=("nvim")
753
- _skip "Neovim" "no server sockets found"
754
- return
755
- fi
756
-
757
- local count=0
758
- local failed=0
759
- for sock in "${sockets[@]}"; do
760
- if nvim --server "$sock" --remote-expr "luaeval(\"(function() ${lua_cmd} return 'ok' end)()\")" &>/dev/null; then
761
- count=$((count + 1))
762
- else
763
- failed=$((failed + 1))
764
- fi
765
- done
766
-
767
- if [[ $count -gt 0 ]]; then
768
- RELOADED+=("nvim")
769
- _ok "Neovim" "${nvim_colorscheme} → ${count} instance(s)${failed:+, ${failed} failed}"
770
- else
771
- _err "Neovim" "all ${failed} instance(s) failed"
772
- fi
773
- }
774
-
775
- reload_wallpaper() {
776
- local script="$SRC_DIR/scripts/theme/wallpaper-sync.sh"
777
-
778
- if [[ ! -x "$script" ]] && [[ ! -f "$script" ]]; then
779
- SKIPPED+=("wallpaper")
780
- _skip "Wallpaper" "sync script not found"
781
- return
782
- fi
783
-
784
- local wp_output
785
- wp_output="$(bash "$script" 2>&1)" || true
786
-
787
- if echo "$wp_output" | grep -q "Applied via\|Applied wallpaper\|matched"; then
788
- RELOADED+=("wallpaper")
789
- _ok "Wallpaper" "matched active theme"
790
- elif echo "$wp_output" | grep -q "skipping\|not found\|no "; then
791
- SKIPPED+=("wallpaper")
792
- _skip "Wallpaper" "no custom wallpaper (add to ~/Pictures/Wallpapers/)"
793
- else
794
- SKIPPED+=("wallpaper")
795
- _skip "Wallpaper" "sync unavailable"
796
- fi
797
- }
798
-
799
- reload_dms() {
800
- if [[ "$PLATFORM" != "Linux" ]]; then
801
- SKIPPED+=("dms")
802
- _skip "DMS" "not Linux"
803
- return
804
- fi
805
-
806
- if ! command -v systemctl &>/dev/null; then
807
- SKIPPED+=("dms")
808
- _skip "DMS" "systemctl not available"
809
- return
810
- fi
811
-
812
- if ! systemctl --user is-active --quiet dms.service; then
813
- SKIPPED+=("dms")
814
- _skip "DMS" "service not active"
815
- return
816
- fi
817
-
818
- if systemctl --user restart dms.service >/dev/null 2>&1; then
819
- RELOADED+=("dms")
820
- _ok "DMS" "service restarted"
821
- else
822
- SKIPPED+=("dms")
823
- _skip "DMS" "restart failed"
824
- fi
825
- }
826
-
827
- # =============================================================================
828
- # Usage
829
- # =============================================================================
830
-
831
- usage() {
832
- printf '%s\n' "${BOLD}dot-theme-sync${RESET} — fast theme switching"
833
- echo ""
834
- printf '%s\n' "${BOLD}USAGE${RESET}"
835
- printf ' %s\n' "dot-theme-sync Regenerate configs + reload running apps"
836
- printf ' %s\n' "dot-theme-sync <theme-name> Set theme + regenerate + reload"
837
- printf ' %s\n' "dot-theme-sync --full Full chezmoi apply + reload"
838
- printf ' %s\n' "dot-theme-sync --help Show this help"
839
- echo ""
840
- printf '%s\n' "${BOLD}APPLICATIONS${RESET}"
841
- printf ' %s\n' "Ghostty chezmoi apply + runtime reload"
842
- printf ' %s\n' "Tmux chezmoi apply + source-file reload"
843
- printf ' %s\n' "Niri screen transition"
844
- printf ' %s\n' "Browsers desktop sync + Firefox content preference"
845
- printf ' %s\n' "Neovim remote-expr colorscheme switch (direct IPC)"
846
- }
847
-
848
- # =============================================================================
849
- # Main
850
- # =============================================================================
851
-
852
- main() {
853
- local do_full=false
854
- local new_theme=""
855
-
856
- # Parse arguments
857
- case "${1:-}" in
858
- --help | -h)
859
- usage
860
- exit 0
861
- ;;
862
- --full)
863
- do_full=true
864
- ;;
865
- "")
866
- # No arguments: use current theme
867
- ;;
868
- -*)
869
- printf '%s\n' "${RED}error${RESET}: unknown flag '$1'"
870
- usage
871
- exit 1
872
- ;;
873
- *)
874
- new_theme="$1"
875
- ;;
876
- esac
877
-
878
- # Header
879
- printf '%s\n' "${BOLD}${CYAN}dot-theme-sync${RESET}"
880
- echo ""
881
-
882
- # If a new theme was specified, write it to the data file
883
- if [[ -n "$new_theme" ]]; then
884
- write_theme "$new_theme"
885
- _info "Theme" "set to $new_theme"
886
- else
887
- sync_theme_state
888
- fi
889
-
890
- # Read the active theme
891
- local theme
892
- theme="$(current_theme)"
893
- if [[ -z "$theme" ]]; then
894
- _err "Theme" "no theme found in $DATA_FILE"
895
- exit 1
896
- fi
897
- _info "Theme" "$theme"
898
- echo ""
899
-
900
- # Regenerate config files with new theme data
901
- if [[ "$do_full" == true ]]; then
902
- _info "Chezmoi" "full apply..."
903
- if chezmoi apply --force 2>/dev/null || chezmoi apply; then
904
- _ok "Chezmoi" "full apply completed"
905
- else
906
- _err "Chezmoi" "apply failed"
907
- fi
908
- else
909
- apply_theme_configs
910
- fi
911
- sync_ghostty_macos_config
912
- echo ""
913
-
914
- # Signal running applications to reload
915
- reload_ghostty
916
- reload_tmux
917
- reload_niri
918
- reload_desktop "$theme"
919
- reload_wallpaper
920
- reload_dms
921
- reload_browsers "$theme"
922
- reload_nvim "$theme"
923
-
924
- # Summary
925
- echo ""
926
- local elapsed
927
- elapsed="$(_elapsed_ms)"
928
- local reloaded_count=${#RELOADED[@]}
929
- local skipped_count=${#SKIPPED[@]}
930
-
931
- if [[ $reloaded_count -gt 0 ]]; then
932
- local apps
933
- apps="$(
934
- IFS=', '
935
- echo "${RELOADED[*]}"
936
- )"
937
- printf '%s\n' "${GREEN}${BOLD}Done${RESET} ${DIM}in ${elapsed}ms${RESET} — reloaded ${BOLD}${apps}${RESET}"
938
- else
939
- printf '%s\n' "${YELLOW}${BOLD}Done${RESET} ${DIM}in ${elapsed}ms${RESET} — no running apps to reload"
940
- fi
941
-
942
- if [[ $skipped_count -gt 0 ]]; then
943
- local skips
944
- skips="$(
945
- IFS=', '
946
- echo "${SKIPPED[*]}"
947
- )"
948
- printf '%s\n' "${DIM}Skipped: ${skips}${RESET}"
949
- fi
950
- }
951
-
952
- main "$@"