@sebastienrousseau/dotfiles 0.2.481 → 0.2.500

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 (546) hide show
  1. package/CHANGELOG.md +122 -32
  2. package/LICENSE +1 -1
  3. package/README.md +211 -242
  4. package/docs/.vitepress/reports/localization-readability-audit.md +69 -0
  5. package/docs/AI.md +102 -0
  6. package/docs/COPYRIGHT +2 -2
  7. package/docs/NAMING_CONVENTIONS.md +95 -0
  8. package/docs/README.md +58 -249
  9. package/docs/adr/ADR-004-cli-architecture.md +2 -2
  10. package/docs/adr/ADR-006-shell-selection.md +2 -2
  11. package/docs/adr/ADR-007-multi-shell-parity.md +53 -0
  12. package/docs/adr/ADR-008-alias-system-architecture.md +85 -0
  13. package/docs/adr/README.md +2 -3
  14. package/docs/architecture/ARCHITECTURE.md +113 -0
  15. package/docs/architecture/INTEROP.md +36 -0
  16. package/docs/architecture/REPO_LAYOUT.md +237 -0
  17. package/docs/architecture/WALKTHROUGH.md +82 -0
  18. package/docs/architecture/fleet-deployment.md +73 -0
  19. package/docs/archive/EUXIS_2026_REVIEW.md +119 -0
  20. package/docs/archive/MILESTONE_v0.2.493.md +43 -0
  21. package/docs/{PLAN.md → archive/PLAN.md} +1 -1
  22. package/docs/guides/INSTALL.md +140 -0
  23. package/docs/{NEOVIM_IDE_GUIDE.md → guides/NEOVIM_IDE_GUIDE.md} +12 -12
  24. package/docs/guides/THEMING.md +222 -0
  25. package/docs/{TROUBLESHOOTING.md → guides/TROUBLESHOOTING.md} +36 -0
  26. package/docs/{WSL2_NIX_TROUBLESHOOTING.md → guides/WSL2_NIX_TROUBLESHOOTING.md} +8 -8
  27. package/docs/index.md +39 -0
  28. package/docs/interop/A2A.md +32 -0
  29. package/docs/manual/00-introduction.md +85 -0
  30. package/docs/manual/01-concepts/01-architecture.md +134 -0
  31. package/docs/manual/01-concepts/02-trust-model.md +178 -0
  32. package/docs/manual/01-concepts/03-theme-engine.md +182 -0
  33. package/docs/manual/01-concepts/04-fleet.md +142 -0
  34. package/docs/manual/01-concepts/05-self-healing.md +197 -0
  35. package/docs/manual/02-tutorials/01-first-install.md +192 -0
  36. package/docs/manual/02-tutorials/02-add-wallpaper.md +211 -0
  37. package/docs/manual/02-tutorials/03-create-profile.md +238 -0
  38. package/docs/manual/02-tutorials/04-encrypt-secret.md +275 -0
  39. package/docs/manual/02-tutorials/05-deploy-fleet.md +279 -0
  40. package/docs/manual/03-reference/01-dot-cli.md +413 -0
  41. package/docs/manual/03-reference/02-config-files.md +259 -0
  42. package/docs/manual/03-reference/03-environment.md +120 -0
  43. package/docs/manual/03-reference/04-templates.md +184 -0
  44. package/docs/manual/03-reference/05-feature-flags.md +118 -0
  45. package/docs/manual/04-cookbook/01-recipes.md +281 -0
  46. package/docs/manual/04-cookbook/02-troubleshooting.md +319 -0
  47. package/docs/manual/04-cookbook/03-faq.md +167 -0
  48. package/docs/manual/05-appendices/A-platform-matrix.md +97 -0
  49. package/docs/manual/05-appendices/B-security-checklist.md +78 -0
  50. package/docs/manual/05-appendices/C-glossary.md +36 -0
  51. package/docs/manual/05-appendices/D-bibliography.md +54 -0
  52. package/docs/manual/05-appendices/E-license.md +34 -0
  53. package/docs/manual/_toc.yml +58 -0
  54. package/docs/manual/command-index.md +58 -0
  55. package/docs/manual/concept-index.md +164 -0
  56. package/docs/operations/ATTESTATION.md +39 -0
  57. package/docs/operations/MAINTENANCE.md +59 -0
  58. package/docs/operations/MIGRATION.md +101 -0
  59. package/docs/operations/OPERATIONS.md +164 -0
  60. package/docs/operations/RELIABILITY.md +116 -0
  61. package/docs/{ROADMAP.md → operations/ROADMAP.md} +11 -11
  62. package/docs/operations/TESTING.md +195 -0
  63. package/docs/operations/TRACEABILITY.md +31 -0
  64. package/docs/operations/TRUSTED_AGENT_WORKSTATION.md +61 -0
  65. package/docs/operations/VERSION_SYNC.md +344 -0
  66. package/docs/{ALIASES.md → reference/ALIASES.md} +2 -6
  67. package/docs/reference/ALIASES_CHEATSHEET.md +28 -0
  68. package/docs/reference/ALIASES_DEPRECATIONS.md +9 -0
  69. package/docs/reference/FEATURES.md +62 -0
  70. package/docs/reference/FONTS.md +108 -0
  71. package/docs/reference/PROFILES.md +65 -0
  72. package/docs/{SCREENSHOTS.md → reference/SCREENSHOTS.md} +26 -25
  73. package/docs/reference/SCRIPTS.md +67 -0
  74. package/docs/reference/SUPPORT_MATRIX.md +74 -0
  75. package/docs/reference/THEMES.md +113 -0
  76. package/docs/reference/TOOLS.md +105 -0
  77. package/docs/reference/UTILS.md +151 -0
  78. package/docs/security/AI_ACT_COMPLIANCE.md +90 -0
  79. package/docs/security/AUTOMATION_SECRETS.md +22 -0
  80. package/docs/security/COMPLIANCE.md +453 -0
  81. package/docs/security/ENCRYPTION.md +52 -0
  82. package/docs/security/FMEA.md +155 -0
  83. package/docs/security/INCIDENT_RESPONSE.md +575 -0
  84. package/docs/security/KEYS.md +45 -0
  85. package/docs/security/MCP_POLICY.md +69 -0
  86. package/docs/security/POLICY_RELEASES.md +33 -0
  87. package/docs/security/README.md +24 -0
  88. package/docs/security/SECRETS.md +146 -0
  89. package/docs/security/SECURITY.md +41 -0
  90. package/docs/security/SECURITY_CHECKLIST.md +44 -0
  91. package/docs/security/SOUP_REGISTER.md +32 -0
  92. package/docs/security/THREAT_MODEL.md +120 -0
  93. package/docs/security/VERIFICATION_VALIDATION.md +224 -0
  94. package/docs/themes/README.md +3 -17
  95. package/docs/themes/VISUAL_INTEGRITY_REPORT.md +26 -0
  96. package/docs/themes/hero-shot.svg +78 -0
  97. package/dot_config/.module-manifest.json +69 -0
  98. package/dot_config/ai/identity.md +20 -0
  99. package/dot_config/ai/patterns/architect.md +14 -0
  100. package/dot_config/ai/patterns/hardener.md +13 -0
  101. package/dot_config/ai/patterns/refactor.md +13 -0
  102. package/dot_config/aider/aider.conf.yml +1 -1
  103. package/dot_config/alacritty/alacritty.toml.tmpl +41 -469
  104. package/dot_config/atuin/config.toml +18 -1
  105. package/dot_config/bat/config +16 -1
  106. package/dot_config/claude/mcp_servers.json +3 -32
  107. package/dot_config/dotfiles/agent-card.json +29 -0
  108. package/dot_config/dotfiles/agent-profiles.json +92 -0
  109. package/dot_config/dotfiles/boot/README.md +1 -1
  110. package/dot_config/dotfiles/grub/README.md +1 -1
  111. package/dot_config/dotfiles/lock/README.md +1 -1
  112. package/dot_config/dotfiles/mcp-lock.json +33 -0
  113. package/dot_config/dotfiles/mcp-policy.json +52 -0
  114. package/dot_config/dotfiles/mcp-registry.json +47 -0
  115. package/dot_config/dotfiles/model-registry.json +20 -0
  116. package/dot_config/dotfiles/policy-bundles.json +38 -0
  117. package/dot_config/dotfiles/prompt-registry.json +16 -0
  118. package/dot_config/dotfiles/versions.env +18 -0
  119. package/dot_config/environment.d/50-ssh-agent.conf +2 -0
  120. package/dot_config/environment.d/90-wayland.conf +19 -0
  121. package/dot_config/firefox/user.js.tmpl +58 -0
  122. package/dot_config/fish/completions/dot-theme-sync.fish.tmpl +9 -0
  123. package/dot_config/fish/completions/dot.fish.tmpl +115 -0
  124. package/dot_config/fish/conf.d/000-perf-cache.fish +56 -0
  125. package/dot_config/fish/conf.d/aliases.fish.tmpl +77 -0
  126. package/dot_config/fish/conf.d/env.fish.tmpl +48 -0
  127. package/dot_config/fish/conf.d/functions.fish.tmpl +22 -0
  128. package/dot_config/fish/conf.d/init.fish.tmpl +151 -0
  129. package/dot_config/fish/config.fish.tmpl +44 -0
  130. package/dot_config/fish/fish_plugins +1 -0
  131. package/dot_config/fish/functions/_.fish +3 -0
  132. package/dot_config/fish/functions/_cached_eval.fish +58 -0
  133. package/dot_config/fish/functions/als.fish +46 -0
  134. package/dot_config/fish/functions/bg-upgrade.fish +7 -0
  135. package/dot_config/fish/functions/c.fish +3 -0
  136. package/dot_config/fish/functions/cat.fish +9 -0
  137. package/dot_config/fish/functions/d.fish +7 -0
  138. package/dot_config/fish/functions/dot.fish +34 -0
  139. package/dot_config/fish/functions/h.fish +3 -0
  140. package/dot_config/fish/functions/l.fish +7 -0
  141. package/dot_config/fish/functions/la.fish +7 -0
  142. package/dot_config/fish/functions/ll.fish +7 -0
  143. package/dot_config/fish/functions/log_error.fish +13 -0
  144. package/dot_config/fish/functions/log_info.fish +13 -0
  145. package/dot_config/fish/functions/lr.fish +7 -0
  146. package/dot_config/fish/functions/lra.fish +7 -0
  147. package/dot_config/fish/functions/ls.fish +7 -0
  148. package/dot_config/fish/functions/lt.fish +7 -0
  149. package/dot_config/fish/functions/lta.fish +7 -0
  150. package/dot_config/fish/functions/notify-run.fish +11 -0
  151. package/dot_config/fish/functions/q.fish +3 -0
  152. package/dot_config/fish/functions/silent-run.fish +7 -0
  153. package/dot_config/fish/functions/yy.fish +8 -0
  154. package/dot_config/fontconfig/fonts.conf.tmpl +13 -0
  155. package/dot_config/foot/foot.ini.tmpl +33 -0
  156. package/dot_config/fuzzel/fuzzel.ini.tmpl +18 -0
  157. package/dot_config/fzf/fzf.zsh +48 -0
  158. package/dot_config/ghostty/config.tmpl +69 -565
  159. package/dot_config/git/allowed_signers.tmpl +18 -0
  160. package/dot_config/git/commit-template +10 -0
  161. package/dot_config/gnupg/{gpg-agent.conf.tmpl → gpg-agent.conf} +3 -3
  162. package/dot_config/goose/config.yaml +2 -2
  163. package/dot_config/gtk-3.0/gtk.css.tmpl +59 -180
  164. package/dot_config/gtk-3.0/settings.ini.tmpl +5 -44
  165. package/dot_config/gtk-4.0/gtk.css.tmpl +79 -136
  166. package/dot_config/gtk-4.0/settings.ini.tmpl +5 -8
  167. package/dot_config/ipython/profile_default/ipython_config.py +19 -0
  168. package/dot_config/just/justfile +18 -0
  169. package/dot_config/kanshi/config.tmpl +22 -0
  170. package/dot_config/kitty/kitty.conf.tmpl +44 -508
  171. package/dot_config/lazygit/config.yml +18 -6
  172. package/dot_config/mako/config +47 -0
  173. package/dot_config/micro/settings.json +3 -0
  174. package/dot_config/mimeapps.list +77 -0
  175. package/dot_config/mise/config.toml +63 -5
  176. package/dot_config/mongosh/mongoshrc.js +1 -0
  177. package/dot_config/mpv/input.conf +47 -0
  178. package/dot_config/mpv/mpv.conf +47 -0
  179. package/dot_config/niri/config.kdl.tmpl +327 -0
  180. package/dot_config/nushell/aliases.nu +18 -0
  181. package/dot_config/nushell/completions.nu.tmpl +52 -0
  182. package/dot_config/nushell/config.nu.tmpl +86 -0
  183. package/dot_config/nushell/env.nu.tmpl +94 -0
  184. package/dot_config/nushell/functions.nu.tmpl +17 -0
  185. package/dot_config/nvim/init.lua +14 -0
  186. package/dot_config/nvim/lazy-lock.json +45 -14
  187. package/dot_config/nvim/lua/config/autocmds.lua +45 -1
  188. package/dot_config/nvim/lua/config/keymaps.lua +13 -8
  189. package/dot_config/nvim/lua/config/lazy.lua +22 -12
  190. package/dot_config/nvim/lua/config/options.lua +1 -0
  191. package/dot_config/nvim/lua/plugins/ai.lua +75 -0
  192. package/dot_config/nvim/lua/plugins/coding.lua +11 -29
  193. package/dot_config/nvim/lua/plugins/completion.lua +60 -0
  194. package/dot_config/nvim/lua/plugins/dap.lua +215 -4
  195. package/dot_config/nvim/lua/plugins/editor.lua +6 -10
  196. package/dot_config/nvim/lua/plugins/git.lua +1 -0
  197. package/dot_config/nvim/lua/plugins/lsp.lua +16 -81
  198. package/dot_config/nvim/lua/plugins/markdown.lua +1 -0
  199. package/dot_config/nvim/lua/plugins/rust.lua +1 -0
  200. package/dot_config/nvim/lua/plugins/sessions.lua +1 -0
  201. package/dot_config/nvim/lua/plugins/ui.lua +23 -51
  202. package/dot_config/paru/paru.conf +10 -0
  203. package/dot_config/powershell/Microsoft.PowerShell_profile.ps1.tmpl +81 -0
  204. package/dot_config/pueue/pueue.yml +34 -0
  205. package/dot_config/raycast/README.md +1 -1
  206. package/dot_config/ripgrep/ripgreprc +21 -0
  207. package/dot_config/shell/00-core-paths.sh.tmpl +62 -24
  208. package/dot_config/shell/05-core-safety.sh +47 -0
  209. package/dot_config/shell/10-secrets.sh +40 -0
  210. package/dot_config/shell/40-fzf-defaults.sh.tmpl +16 -0
  211. package/dot_config/shell/40-ls-colors.sh +48 -0
  212. package/dot_config/shell/50-logic-functions-core.sh.tmpl +10 -0
  213. package/dot_config/shell/51-logic-functions-extra.sh.tmpl +64 -0
  214. package/dot_config/shell/90-ux-aliases.sh.tmpl +90 -5
  215. package/dot_config/shell/91-ux-aliases-lazy.sh.tmpl +33 -2
  216. package/dot_config/shell/Brewfile.cli +8 -0
  217. package/dot_config/shell/README.md +9 -9
  218. package/dot_config/shell/als_data.txt.tmpl +65 -0
  219. package/dot_config/shell/custom/auto_ls.zsh +20 -0
  220. package/dot_config/shell/custom/context_suggest.zsh +50 -50
  221. package/dot_config/shell/custom/error_analysis.zsh +29 -29
  222. package/dot_config/starship.toml.tmpl +85 -7
  223. package/dot_config/swaylock/config +43 -0
  224. package/dot_config/systemd/user/dotfiles-maintenance.service +8 -0
  225. package/dot_config/systemd/user/dotfiles-maintenance.timer +11 -0
  226. package/dot_config/systemd/user/pueued.service +12 -0
  227. package/dot_config/systemd/user/ssh-agent.service +12 -0
  228. package/dot_config/tmux/tmux.conf.tmpl +80 -38
  229. package/dot_config/topgrade.toml.tmpl +54 -0
  230. package/dot_config/user-dirs.dirs +9 -0
  231. package/dot_config/vscode/settings.json.tmpl +9 -50
  232. package/dot_config/waybar/config.jsonc.tmpl +90 -0
  233. package/dot_config/waybar/style.css.tmpl +211 -0
  234. package/dot_config/wezterm/wezterm.lua.tmpl +31 -203
  235. package/dot_config/xdg-desktop-portal/niri-portals.conf +5 -0
  236. package/dot_config/yazi/keymap.toml +67 -0
  237. package/dot_config/yazi/theme.toml +102 -0
  238. package/dot_config/zathura/zathurarc +52 -0
  239. package/dot_config/zellij/{config.kdl → config.kdl.tmpl} +1 -1
  240. package/dot_config/zsh/dot_zprofile +1 -7
  241. package/dot_config/zsh/dot_zshenv +2 -3
  242. package/dot_config/zsh/dot_zshrc.tmpl +368 -69
  243. package/dot_config/zsh/rc.d/00-alias-shims.zsh +77 -0
  244. package/dot_config/zsh/rc.d/05-ssh-agent.zsh +17 -4
  245. package/dot_config/zsh/rc.d/10-env.zsh.tmpl +4 -4
  246. package/dot_config/zsh/rc.d/20-zinit.zsh +65 -0
  247. package/dot_config/zsh/rc.d/30-options.zsh.tmpl +101 -30
  248. package/dot_config/zsh/rc.d/99-alias-wrapper.zsh +32 -0
  249. package/dot_local/bin/__pycache__/executable_dot-load-benchmark-ptycpython-312.pyc +0 -0
  250. package/dot_local/bin/executable_ai-update +195 -0
  251. package/dot_local/bin/executable_ai_core +113 -91
  252. package/dot_local/bin/executable_antigravity +11 -0
  253. package/dot_local/bin/executable_b64 +61 -36
  254. package/dot_local/bin/executable_bm +77 -0
  255. package/dot_local/bin/executable_cb +39 -0
  256. package/dot_local/bin/executable_dot +543 -132
  257. package/dot_local/bin/executable_dot-ai +36 -0
  258. package/dot_local/bin/executable_dot-bootstrap +77 -0
  259. package/dot_local/bin/executable_dot-launch-or-focus +52 -0
  260. package/dot_local/bin/executable_dot-load-benchmark +31 -0
  261. package/dot_local/bin/executable_dot-load-benchmark-pty +77 -0
  262. package/dot_local/bin/executable_dot-theme-sync +952 -0
  263. package/dot_local/bin/executable_dot_completion +2 -0
  264. package/dot_local/bin/executable_dtags +28 -0
  265. package/dot_local/bin/executable_epoch +43 -38
  266. package/dot_local/bin/executable_extract +32 -99
  267. package/dot_local/bin/executable_gbd +52 -0
  268. package/dot_local/bin/executable_gd +42 -0
  269. package/dot_local/bin/executable_git-ai-commit +35 -20
  270. package/dot_local/bin/executable_git-ai-diff +33 -18
  271. package/dot_local/bin/executable_gl +101 -0
  272. package/dot_local/bin/executable_hash +56 -18
  273. package/dot_local/bin/executable_hashsum +160 -0
  274. package/dot_local/bin/executable_hex +44 -8
  275. package/dot_local/bin/executable_jsonv +34 -10
  276. package/dot_local/bin/executable_jwt +22 -6
  277. package/dot_local/bin/executable_kill-port +18 -2
  278. package/dot_local/bin/executable_lorem +21 -6
  279. package/dot_local/bin/executable_mkscript +35 -0
  280. package/dot_local/bin/executable_monitor +56 -0
  281. package/dot_local/bin/{executable_ip → executable_myip} +16 -2
  282. package/dot_local/bin/executable_notify +22 -0
  283. package/dot_local/bin/executable_open +36 -0
  284. package/dot_local/bin/executable_pw +27 -0
  285. package/dot_local/bin/executable_rec-start +46 -0
  286. package/dot_local/bin/executable_rec-stop +35 -0
  287. package/dot_local/bin/executable_regex +49 -13
  288. package/dot_local/bin/executable_start-niri +8 -0
  289. package/dot_local/bin/executable_tmux-sessionizer +276 -149
  290. package/dot_local/bin/executable_tour +112 -74
  291. package/dot_local/bin/executable_up +21 -0
  292. package/dot_local/bin/executable_update +45 -11
  293. package/dot_local/bin/executable_uuid +37 -7
  294. package/dot_local/bin/executable_win +32 -0
  295. package/dot_local/bin/executable_yamlv +25 -7
  296. package/dot_local/share/bash-completion/completions/dot +62 -44
  297. package/dot_local/share/icons/hicolor/128x128/apps/rousseau.png +0 -0
  298. package/dot_local/share/icons/hicolor/16x16/apps/rousseau.png +0 -0
  299. package/dot_local/share/icons/hicolor/24x24/apps/rousseau.png +0 -0
  300. package/dot_local/share/icons/hicolor/256x256/apps/rousseau.png +0 -0
  301. package/dot_local/share/icons/hicolor/32x32/apps/rousseau.png +0 -0
  302. package/dot_local/share/icons/hicolor/48x48/apps/rousseau.png +0 -0
  303. package/dot_local/share/icons/hicolor/512x512/apps/rousseau.png +0 -0
  304. package/dot_local/share/icons/hicolor/64x64/apps/rousseau.png +0 -0
  305. package/dot_local/share/icons/hicolor/96x96/apps/rousseau.png +0 -0
  306. package/dot_local/share/icons/hicolor/scalable/apps/rousseau.png +0 -0
  307. package/dot_local/share/man/man1/dot.1 +149 -0
  308. package/dot_local/share/mise/plugins/kiro-cli/bin/executable_download +64 -0
  309. package/dot_local/share/mise/plugins/kiro-cli/bin/executable_install +18 -0
  310. package/dot_local/share/mise/plugins/kiro-cli/bin/executable_list-all +13 -0
  311. package/dot_local/share/wayland-sessions/niri.desktop.tmpl +6 -0
  312. package/dot_local/share/zsh/completions/_dot +283 -0
  313. package/install.sh +297 -210
  314. package/package.json +17 -5
  315. package/scripts/ci/check-copyright-headers.sh +96 -0
  316. package/scripts/ci/guard-gitleaks-checkout.sh +57 -0
  317. package/scripts/ci/install-chezmoi-verified.sh +64 -0
  318. package/scripts/ci/validate-ci-config.sh +41 -39
  319. package/scripts/demo/record.sh +3 -2
  320. package/scripts/diagnostics/a2a-conformance.sh +162 -0
  321. package/scripts/diagnostics/alias-governance.sh +137 -0
  322. package/scripts/diagnostics/aliases-cheatsheet.sh +73 -0
  323. package/scripts/diagnostics/aliases-manifest.sh +31 -0
  324. package/scripts/diagnostics/benchmark.sh +209 -29
  325. package/scripts/diagnostics/conflicts.sh +72 -0
  326. package/scripts/diagnostics/doctor-unified.sh +38 -0
  327. package/scripts/diagnostics/doctor.sh +491 -65
  328. package/scripts/diagnostics/drift-dashboard.sh +17 -6
  329. package/scripts/diagnostics/health.sh +351 -110
  330. package/scripts/diagnostics/history-analysis.sh +12 -4
  331. package/scripts/diagnostics/mcp-doctor.sh +575 -0
  332. package/scripts/diagnostics/perf.sh +225 -0
  333. package/scripts/diagnostics/scorecard.sh +118 -0
  334. package/scripts/diagnostics/secret-governance.sh +58 -0
  335. package/scripts/diagnostics/security-score.sh +139 -93
  336. package/scripts/diagnostics/smoke-test.sh +87 -0
  337. package/scripts/diagnostics/snapshot.sh +89 -0
  338. package/scripts/diagnostics/verify.sh +107 -0
  339. package/scripts/diagnostics/verify_state.sh +2 -2
  340. package/scripts/diagnostics/version-locks.sh +79 -0
  341. package/scripts/diagnostics/workstation-attestation.sh +181 -0
  342. package/scripts/docs/build-manual.sh +883 -0
  343. package/scripts/docs/check-manual.sh +213 -0
  344. package/scripts/dot/commands/agent.sh +465 -0
  345. package/scripts/dot/commands/ai.sh +416 -0
  346. package/scripts/dot/commands/aliases.sh +250 -0
  347. package/scripts/dot/commands/appearance.sh +21 -4
  348. package/scripts/dot/commands/core.sh +59 -4
  349. package/scripts/dot/commands/diagnostics.sh +132 -3
  350. package/scripts/dot/commands/fleet.sh +399 -0
  351. package/scripts/dot/commands/lint.sh +177 -0
  352. package/scripts/dot/commands/manual.sh +168 -0
  353. package/scripts/dot/commands/meta.sh +148 -17
  354. package/scripts/dot/commands/patterns.sh +54 -0
  355. package/scripts/dot/commands/restore.sh +57 -35
  356. package/scripts/dot/commands/secrets.sh +151 -9
  357. package/scripts/dot/commands/security.sh +3 -0
  358. package/scripts/dot/commands/tools.sh +268 -27
  359. package/scripts/dot/data/alias-deprecations.tsv +2 -0
  360. package/scripts/dot/lib/bento.sh +49 -0
  361. package/scripts/dot/lib/log.sh +194 -0
  362. package/scripts/dot/lib/platform.sh +98 -0
  363. package/scripts/dot/lib/ui.sh +507 -0
  364. package/scripts/dot/lib/utils.sh +318 -18
  365. package/scripts/fonts/install-nerd-fonts.sh +19 -10
  366. package/scripts/fonts/patch-fonts.sh +1 -0
  367. package/scripts/git-hooks/install.sh +11 -0
  368. package/scripts/git-hooks/pre-commit +12 -0
  369. package/scripts/git-hooks/pre-commit-audit.sh +145 -0
  370. package/scripts/git-hooks/pre-push +29 -0
  371. package/scripts/git-hooks/prepare-commit-msg +29 -0
  372. package/scripts/lib/secrets_provider.sh +158 -0
  373. package/scripts/maintenance/check-updates.sh +131 -0
  374. package/scripts/ops/ai-setup.sh +55 -0
  375. package/scripts/ops/bundle.sh +77 -0
  376. package/scripts/ops/chaos.sh +49 -0
  377. package/scripts/ops/chezmoi-apply.sh +245 -17
  378. package/scripts/ops/chezmoi-diff.sh +1 -0
  379. package/scripts/ops/chezmoi-remove.sh +2 -0
  380. package/scripts/ops/chezmoi-update.sh +34 -2
  381. package/scripts/ops/heal-chezmoi.sh +51 -0
  382. package/scripts/ops/heal-system.sh +128 -0
  383. package/scripts/ops/heal-tools.sh +340 -0
  384. package/scripts/ops/heal.sh +98 -342
  385. package/scripts/ops/post-apply-repair.sh +106 -0
  386. package/scripts/ops/prewarm.sh +127 -0
  387. package/scripts/ops/release.sh +252 -0
  388. package/scripts/ops/rollback.sh +86 -28
  389. package/scripts/ops/setup.sh +137 -0
  390. package/scripts/ops/teleport.sh +2 -1
  391. package/scripts/qa/coverage-baseline.sh +60 -0
  392. package/scripts/qa/docs-coverage.sh +111 -0
  393. package/scripts/qa/reliability-audit.sh +138 -0
  394. package/scripts/qa/traceability-coverage.sh +116 -0
  395. package/scripts/qa/validate-examples.sh +26 -0
  396. package/scripts/qa/wsl-contract.sh +11 -0
  397. package/scripts/release/package-policy-bundles.sh +125 -0
  398. package/scripts/secrets/age-init.sh +1 -0
  399. package/scripts/secrets/create-secrets-file.sh +1 -0
  400. package/scripts/secrets/encrypt-ssh-key.sh +1 -0
  401. package/scripts/security/backup.sh +44 -4
  402. package/scripts/security/dns-doh.sh +36 -14
  403. package/scripts/security/encryption-check.sh +27 -12
  404. package/scripts/security/enforce-policies.sh +11 -16
  405. package/scripts/security/firewall.sh +76 -20
  406. package/scripts/security/lock-configs.sh +2 -2
  407. package/scripts/security/lock-screen.sh +40 -18
  408. package/scripts/security/manage-secrets.sh +42 -29
  409. package/scripts/security/ssh-cert.sh +203 -0
  410. package/scripts/security/telemetry-kill.sh +40 -18
  411. package/scripts/security/usb-safety.sh +37 -15
  412. package/scripts/theme/apply-gnome-theme.sh +87 -56
  413. package/scripts/theme/extract-theme.py +677 -0
  414. package/scripts/theme/install-boot-logo.sh +1 -0
  415. package/scripts/theme/install-catppuccin-themes.sh +57 -33
  416. package/scripts/theme/install-cursors.sh +1 -0
  417. package/scripts/theme/install-file-icons.sh +1 -0
  418. package/scripts/theme/install-grub-theme.sh +11 -1
  419. package/scripts/theme/install-lock-icon.sh +1 -0
  420. package/scripts/theme/merge-wallpaper.sh +141 -0
  421. package/scripts/theme/rebuild-themes.sh +309 -0
  422. package/scripts/theme/switch.sh +308 -137
  423. package/scripts/theme/wallpaper-rotate.sh +66 -12
  424. package/scripts/theme/wallpaper-sync.sh +386 -31
  425. package/scripts/tools/cmatrix.sh +1 -0
  426. package/scripts/tools/detect-collisions.py +1 -1
  427. package/scripts/tools/emoji-picker.sh +4 -1
  428. package/scripts/tools/figlet-banner.sh +1 -0
  429. package/scripts/tools/log-rotate.sh +2 -1
  430. package/scripts/tools/lolcat-wrap.sh +1 -0
  431. package/scripts/tools/pipes.sh +1 -0
  432. package/scripts/tuning/linux.sh +23 -13
  433. package/scripts/tuning/macos.sh +13 -4
  434. package/scripts/uninstall.sh +85 -0
  435. package/scripts/version-sync.sh +487 -0
  436. package/templates/chezmoi-data/geekom-a9.toml.example +21 -0
  437. package/templates/chezmoi-data/mac-m1.toml.example +16 -0
  438. package/templates/chezmoi-data/mac-t2-linux.toml.example +21 -0
  439. package/templates/chezmoi-data/surface-pro-7p.toml.example +21 -0
  440. package/templates/projects/go/.github/workflows/ci.yml +31 -0
  441. package/templates/projects/go/README.md +1 -1
  442. package/templates/projects/go/cmd/__PROJECT_NAME__/main.go +1 -0
  443. package/templates/projects/go/go.sum +0 -0
  444. package/templates/projects/molecule/README.md +1 -1
  445. package/templates/projects/node/.github/workflows/ci.yml +30 -0
  446. package/templates/projects/node/README.md +1 -1
  447. package/templates/projects/node/package-lock.json +12 -0
  448. package/templates/projects/node/src/index.js +1 -0
  449. package/templates/projects/packer/README.md +1 -1
  450. package/templates/projects/python/.github/workflows/ci.yml +34 -0
  451. package/templates/projects/python/README.md +1 -1
  452. package/templates/projects/python/src/__PROJECT_NAME__/__init__.py +1 -0
  453. package/templates/projects/python/tests/test_basic.py +1 -0
  454. package/docs/ARCHITECTURE.md +0 -229
  455. package/docs/COMPLIANCE.md +0 -47
  456. package/docs/FEATURES.md +0 -166
  457. package/docs/FONTS.md +0 -147
  458. package/docs/INSTALL.md +0 -119
  459. package/docs/KEYS.md +0 -40
  460. package/docs/OPERATIONS.md +0 -130
  461. package/docs/PR_DESCRIPTION.md +0 -149
  462. package/docs/SECRETS.md +0 -76
  463. package/docs/SECURITY.md +0 -30
  464. package/docs/SECURITY_CHECKLIST.md +0 -25
  465. package/docs/TASK.md +0 -99
  466. package/docs/TESTING.md +0 -190
  467. package/docs/TOOLS.md +0 -146
  468. package/docs/UTILS.md +0 -105
  469. package/docs/WALKTHROUGH.md +0 -165
  470. package/dot_config/clippy.toml +0 -55
  471. package/dot_config/dotfiles/versions.env.tmpl +0 -19
  472. package/dot_config/firefox/user.js +0 -8
  473. package/dot_config/git/config.tmpl +0 -77
  474. package/dot_config/go/aliases.sh +0 -61
  475. package/dot_config/go/env.sh +0 -24
  476. package/dot_config/ice/README.md +0 -13
  477. package/dot_config/ipython/profile_default/ipython_config.py.tmpl +0 -5
  478. package/dot_config/lsd/config.yaml +0 -19
  479. package/dot_config/nvim/snippets/all.lua +0 -9
  480. package/dot_config/nvim/snippets/python.lua +0 -16
  481. package/dot_config/shell/00-container-detect.sh +0 -53
  482. package/dot_config/shell/05-core-safety.sh.tmpl +0 -13
  483. package/dot_config/shell/40-ls-colors.sh.tmpl +0 -31
  484. package/dot_config/shell/90-theme-switch.sh +0 -70
  485. package/dot_config/topgrade/topgrade.toml.tmpl +0 -42
  486. package/dot_config/waybar/style.css +0 -8
  487. package/dot_config/zsh/rc.d/20-zinit.zsh.tmpl +0 -22
  488. package/dot_local/bin/executable_zig-install +0 -89
  489. package/dot_local/bin/voice_ops +0 -7
  490. package/scripts/ops/health-check.sh +0 -380
  491. package/scripts/tests/README.md +0 -241
  492. package/scripts/tests/benchmark.sh +0 -91
  493. package/scripts/tests/framework/assertions.sh +0 -283
  494. package/scripts/tests/framework/mocks.sh +0 -201
  495. package/scripts/tests/framework/test_runner.sh +0 -189
  496. package/scripts/tests/integration/test_install.sh +0 -237
  497. package/scripts/tests/performance/benchmark_runner.sh +0 -156
  498. package/scripts/tests/performance/regression_check.sh +0 -73
  499. package/scripts/tests/performance/stress_test.sh +0 -65
  500. package/scripts/tests/test-aliases.sh +0 -25
  501. package/scripts/tests/test-docker.sh +0 -48
  502. package/scripts/tests/unit/test_ai_aliases.sh +0 -158
  503. package/scripts/tests/unit/test_ai_cli_checks.sh +0 -47
  504. package/scripts/tests/unit/test_backup.sh +0 -227
  505. package/scripts/tests/unit/test_case_functions.sh +0 -238
  506. package/scripts/tests/unit/test_cd_aliases.sh +0 -367
  507. package/scripts/tests/unit/test_dot_cli.sh +0 -217
  508. package/scripts/tests/unit/test_encode64.sh +0 -67
  509. package/scripts/tests/unit/test_environment.sh +0 -78
  510. package/scripts/tests/unit/test_extract.sh +0 -163
  511. package/scripts/tests/unit/test_framework_edge_cases.sh +0 -113
  512. package/scripts/tests/unit/test_genpass.sh +0 -298
  513. package/scripts/tests/unit/test_install_edge_cases.sh +0 -167
  514. package/scripts/tests/unit/test_installers.sh +0 -172
  515. package/scripts/tests/unit/test_keygen.sh +0 -68
  516. package/scripts/tests/unit/test_logging.sh +0 -96
  517. package/scripts/tests/unit/test_os_detection_comprehensive.sh +0 -388
  518. package/scripts/tests/unit/test_package_managers_comprehensive.sh +0 -321
  519. package/scripts/tests/unit/test_prependpath.sh +0 -66
  520. package/scripts/tests/unit/test_prependpath_refactored.sh +0 -89
  521. package/scripts/tests/unit/test_rd.sh +0 -230
  522. package/scripts/tests/unit/test_security_fixes.sh +0 -130
  523. package/scripts/tests/unit/test_security_scripts.sh +0 -87
  524. package/scripts/tests/unit/test_template_validation.sh +0 -238
  525. package/scripts/tests/unit/test_utility_functions.sh +0 -144
  526. package/scripts/tests/unit/test_wave1_alias_split.sh +0 -132
  527. package/scripts/tests/unit/test_wave1_ci_pinning.sh +0 -61
  528. package/scripts/tests/unit/test_wave1_gitleaks_config.sh +0 -52
  529. package/scripts/tests/unit/test_wave1_heal_fixes.sh +0 -97
  530. package/scripts/tests/unit/test_wave1_install_gpg.sh +0 -35
  531. package/scripts/tests/unit/test_wave1_zshenv_path.sh +0 -89
  532. package/scripts/tests/unit/test_wave1_zshrc_lazy_hook.sh +0 -115
  533. package/scripts/tests/unit/test_wave2_dot_new_guard.sh +0 -75
  534. package/scripts/tests/unit/test_zipf.sh +0 -76
  535. /package/docs/{LEGACY_ROADMAP.md → archive/LEGACY_ROADMAP.md} +0 -0
  536. /package/docs/{REPO_AUDIT.md → archive/REPO_AUDIT.md} +0 -0
  537. /package/docs/{KEY_ROTATION.md → security/KEY_ROTATION.md} +0 -0
  538. /package/dot_config/ansible/{ansible.cfg.tmpl → ansible.cfg} +0 -0
  539. /package/dot_config/docker/{config.json.tmpl → config.json} +0 -0
  540. /package/dot_config/k9s/{config.yaml.tmpl → config.yaml} +0 -0
  541. /package/dot_config/pypoetry/{config.toml.tmpl → config.toml} +0 -0
  542. /package/dot_config/{pyrightconfig.json.tmpl → pyrightconfig.json} +0 -0
  543. /package/dot_config/tflint/{tflint.hcl.tmpl → tflint.hcl} +0 -0
  544. /package/dot_config/yarn/{yarnrc.yml.tmpl → yarnrc.yml} +0 -0
  545. /package/dot_config/zsh/rc.d/{40-bell.zsh.tmpl → 40-bell.zsh} +0 -0
  546. /package/dot_config/zsh/rc.d/{50-login-fortune.zsh.tmpl → 50-login-fortune.zsh} +0 -0
@@ -1,38 +1,62 @@
1
- #!/bin/bash
2
- # Catppuccin GNOME Theme Installation Script
3
- # Installs Catppuccin GTK themes, icon themes, and shell themes
4
-
5
- set -e
1
+ #!/usr/bin/env bash
2
+ # Copyright (c) 2015-2026 Dotfiles. All rights reserved.
3
+ ## Catppuccin Theme Installer Install Catppuccin themes for GNOME.
4
+ ##
5
+ ## Downloads and installs GTK themes, icon themes, cursor themes,
6
+ ## GNOME Shell themes, and wallpapers from Catppuccin repositories.
7
+ ##
8
+ ## # Requirements
9
+ ## - git: For cloning theme repositories
10
+ ## - curl: For downloading assets
11
+ ## - gnome-tweaks (optional): For applying themes
12
+ ## - gnome-extensions (optional): For shell themes
13
+ ##
14
+ ## # Usage
15
+ ## install-catppuccin-themes.sh # Install all components
16
+ ## install-catppuccin-themes.sh gtk # GTK themes only
17
+ ## install-catppuccin-themes.sh icons # Icon themes only
18
+ ## install-catppuccin-themes.sh cursors # Cursor themes only
19
+ ## install-catppuccin-themes.sh shell # GNOME Shell themes only
20
+ ## install-catppuccin-themes.sh wallpapers # Wallpapers only
21
+ ## install-catppuccin-themes.sh refresh # Refresh theme cache
22
+ ##
23
+ ## # Platform Notes
24
+ ## - Linux/GNOME: Full support
25
+ ## - Other DEs: GTK themes may work, shell themes require GNOME
26
+
27
+ set -euo pipefail
6
28
 
7
29
  THEME_DIR="$HOME/.themes"
8
30
  ICON_DIR="$HOME/.icons"
9
- TEMP_DIR="/tmp/catppuccin-install"
10
-
11
- # Colors for output
12
- RED='\033[0;31m'
13
- GREEN='\033[0;32m'
14
- YELLOW='\033[1;33m'
15
- BLUE='\033[0;34m'
16
- NC='\033[0m' # No Color
31
+ TEMP_DIR="$(umask 077 && mktemp -d)"
32
+
33
+ # Colors for output (respect NO_COLOR: https://no-color.org)
34
+ if [[ -z "${NO_COLOR:-}" ]] && [[ -t 1 ]]; then
35
+ RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m'
36
+ BLUE='\033[0;34m' NC='\033[0m'
37
+ else
38
+ RED='' GREEN='' YELLOW='' BLUE='' NC=''
39
+ fi
17
40
 
18
41
  log() {
19
- echo -e "${BLUE}[INFO]${NC} $1"
42
+ printf '%b\n' "${BLUE}[INFO]${NC} $1"
20
43
  }
21
44
 
22
45
  warn() {
23
- echo -e "${YELLOW}[WARN]${NC} $1"
46
+ printf '%b\n' "${YELLOW}[WARN]${NC} $1"
24
47
  }
25
48
 
26
49
  error() {
27
- echo -e "${RED}[ERROR]${NC} $1"
50
+ printf '%b\n' "${RED}[ERROR]${NC} $1"
28
51
  }
29
52
 
30
53
  success() {
31
- echo -e "${GREEN}[SUCCESS]${NC} $1"
54
+ printf '%b\n' "${GREEN}[SUCCESS]${NC} $1"
32
55
  }
33
56
 
34
57
  # Create directories
35
- mkdir -p "$THEME_DIR" "$ICON_DIR" "$TEMP_DIR"
58
+ mkdir -p "$THEME_DIR" "$ICON_DIR"
59
+ trap 'rm -rf "$TEMP_DIR"' EXIT
36
60
 
37
61
  # Check if git is available
38
62
  if ! command -v git &>/dev/null; then
@@ -44,15 +68,15 @@ fi
44
68
  install_gtk_themes() {
45
69
  log "Installing Catppuccin GTK themes..."
46
70
 
47
- cd "$TEMP_DIR"
71
+ cd "$TEMP_DIR" || return 1
48
72
 
49
73
  if [ ! -d "catppuccin-gtk" ]; then
50
74
  git clone https://github.com/catppuccin/gtk.git catppuccin-gtk
51
75
  else
52
- cd catppuccin-gtk && git pull && cd ..
76
+ git -C catppuccin-gtk pull
53
77
  fi
54
78
 
55
- cd catppuccin-gtk
79
+ cd catppuccin-gtk || return 1
56
80
 
57
81
  # Install all variants
58
82
  for variant in Latte Frappe Macchiato Mocha; do
@@ -79,15 +103,15 @@ install_gtk_themes() {
79
103
  install_papirus_icons() {
80
104
  log "Installing Papirus icon themes..."
81
105
 
82
- cd "$TEMP_DIR"
106
+ cd "$TEMP_DIR" || return 1
83
107
 
84
108
  if [ ! -d "papirus-icon-theme" ]; then
85
109
  git clone https://github.com/PapirusDevelopmentTeam/papirus-icon-theme.git
86
110
  else
87
- cd papirus-icon-theme && git pull && cd ..
111
+ git -C papirus-icon-theme pull
88
112
  fi
89
113
 
90
- cd papirus-icon-theme
114
+ cd papirus-icon-theme || return 1
91
115
 
92
116
  # Install Papirus variants
93
117
  for variant in Papirus Papirus-Dark Papirus-Light; do
@@ -103,15 +127,15 @@ install_papirus_icons() {
103
127
  install_catppuccin_cursors() {
104
128
  log "Installing Catppuccin cursor themes..."
105
129
 
106
- cd "$TEMP_DIR"
130
+ cd "$TEMP_DIR" || return 1
107
131
 
108
132
  if [ ! -d "catppuccin-cursors" ]; then
109
133
  git clone https://github.com/catppuccin/cursors.git catppuccin-cursors
110
134
  else
111
- cd catppuccin-cursors && git pull && cd ..
135
+ git -C catppuccin-cursors pull
112
136
  fi
113
137
 
114
- cd catppuccin-cursors
138
+ cd catppuccin-cursors || return 1
115
139
 
116
140
  # Install cursor themes for each variant
117
141
  for variant in Catppuccin-Latte-* Catppuccin-Frappe-* Catppuccin-Macchiato-* Catppuccin-Mocha-*; do
@@ -135,15 +159,15 @@ install_shell_themes() {
135
159
  fi
136
160
  fi
137
161
 
138
- cd "$TEMP_DIR"
162
+ cd "$TEMP_DIR" || return 1
139
163
 
140
164
  if [ ! -d "catppuccin-gnome-shell" ]; then
141
165
  git clone https://github.com/catppuccin/gnome.git catppuccin-gnome-shell
142
166
  else
143
- cd catppuccin-gnome-shell && git pull && cd ..
167
+ git -C catppuccin-gnome-shell pull
144
168
  fi
145
169
 
146
- cd catppuccin-gnome-shell
170
+ cd catppuccin-gnome-shell || return 1
147
171
 
148
172
  # Install shell themes (use explicit names for portability)
149
173
  for variant in Latte Frappe Macchiato Mocha; do
@@ -175,15 +199,15 @@ install_wallpapers() {
175
199
  mkdir -p "$wallpaper_dir"
176
200
  fi
177
201
 
178
- cd "$TEMP_DIR"
202
+ cd "$TEMP_DIR" || return 1
179
203
 
180
204
  if [ ! -d "catppuccin-wallpapers" ]; then
181
205
  git clone https://github.com/catppuccin/wallpapers.git catppuccin-wallpapers
182
206
  else
183
- cd catppuccin-wallpapers && git pull && cd ..
207
+ git -C catppuccin-wallpapers pull
184
208
  fi
185
209
 
186
- cd catppuccin-wallpapers
210
+ cd catppuccin-wallpapers || return 1
187
211
 
188
212
  # Copy wallpapers
189
213
  for variant in latte frappe macchiato mocha; do
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env bash
2
+ # Copyright (c) 2015-2026 Dotfiles. All rights reserved.
2
3
  set -euo pipefail
3
4
 
4
5
  THEME="${DOTFILES_CURSOR_THEME:-Bibata-Modern-Ice}"
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env bash
2
+ # Copyright (c) 2015-2026 Dotfiles. All rights reserved.
2
3
  set -euo pipefail
3
4
 
4
5
  THEME="${DOTFILES_ICON_THEME:-Papirus}"
@@ -1,6 +1,16 @@
1
1
  #!/usr/bin/env bash
2
+ # Copyright (c) 2015-2026 Dotfiles. All rights reserved.
2
3
  set -euo pipefail
3
4
 
5
+ # Cross-platform sed in-place (BSD vs GNU)
6
+ sed_in_place() {
7
+ if sed --version >/dev/null 2>&1; then
8
+ sed -i "$@" # GNU
9
+ else
10
+ sed -i '' "$@" # BSD (macOS)
11
+ fi
12
+ }
13
+
4
14
  THEME_SRC="${DOTFILES_GRUB_THEME_DIR:-$HOME/.config/dotfiles/grub/theme}"
5
15
  THEME_NAME="${DOTFILES_GRUB_THEME_NAME:-dotfiles}"
6
16
  APPLY=0
@@ -37,7 +47,7 @@ mkdir -p "$THEME_DST"
37
47
  cp -R "$THEME_SRC/." "$THEME_DST"
38
48
 
39
49
  if grep -q '^GRUB_THEME=' /etc/default/grub; then
40
- sed -i.bak "s|^GRUB_THEME=.*|GRUB_THEME=\"$THEME_DST/theme.txt\"|" /etc/default/grub
50
+ sed_in_place "s|^GRUB_THEME=.*|GRUB_THEME=\"$THEME_DST/theme.txt\"|" /etc/default/grub
41
51
  else
42
52
  echo "GRUB_THEME=\"$THEME_DST/theme.txt\"" >>/etc/default/grub
43
53
  fi
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env bash
2
+ # Copyright (c) 2015-2026 Dotfiles. All rights reserved.
2
3
  set -euo pipefail
3
4
 
4
5
  icon_path="${DOTFILES_LOCK_ICON:-$HOME/.config/dotfiles/lock/icon.png}"
@@ -0,0 +1,141 @@
1
+ #!/usr/bin/env bash
2
+ # Copyright (c) 2015-2026 Dotfiles. All rights reserved.
3
+ # merge-wallpaper.sh — Merge dark+light wallpapers into a single dynamic HEIC.
4
+ #
5
+ # Creates an Apple-compatible dynamic HEIC with appearance metadata so macOS
6
+ # automatically shows the correct variant based on Light/Dark mode.
7
+ #
8
+ # Usage:
9
+ # bash merge-wallpaper.sh # Merge all pairs in ~/Pictures/Wallpapers/
10
+ # bash merge-wallpaper.sh <family> # Merge a specific family (e.g. macos-tahoe)
11
+ # bash merge-wallpaper.sh --dry-run # Show what would be merged
12
+ set -euo pipefail
13
+
14
+ WALLPAPER_DIR="${DOTFILES_WALLPAPER_DIR:-$HOME/Pictures/Wallpapers}"
15
+ DRY_RUN=false
16
+ TARGET=""
17
+
18
+ for arg in "$@"; do
19
+ case "$arg" in
20
+ --dry-run) DRY_RUN=true ;;
21
+ --help | -h)
22
+ echo "Usage: merge-wallpaper.sh [--dry-run] [family-name]"
23
+ echo ""
24
+ echo "Merges *-dark.heic + *-light.heic into a single dynamic HEIC"
25
+ echo "that switches appearance automatically on macOS."
26
+ exit 0
27
+ ;;
28
+ *) TARGET="$arg" ;;
29
+ esac
30
+ done
31
+
32
+ if ! command -v heif-enc &>/dev/null; then
33
+ echo "Error: heif-enc required (brew install libheif)" >&2
34
+ exit 1
35
+ fi
36
+
37
+ if ! command -v magick &>/dev/null; then
38
+ echo "Error: ImageMagick (magick) required" >&2
39
+ exit 1
40
+ fi
41
+
42
+ # Generate the Apple desktop appearance XMP metadata.
43
+ # Format: bplist with {l: 0, d: 1} meaning image 0 = light, image 1 = dark.
44
+ generate_xmp() {
45
+ local apr_b64="YnBsaXN0MDDSAQIDBFFsUWQQABABCA0PERMAAAAAAAABAQAAAAAAAAAFAAAAAAAAAAAAAAAAAAAAFQ=="
46
+ cat <<XMPEOF
47
+ <?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
48
+ <x:xmpmeta xmlns:x="adobe:ns:meta/" x:xmptk="dotfiles">
49
+ <rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
50
+ <rdf:Description rdf:about=""
51
+ xmlns:apple_desktop="http://ns.apple.com/namespace/1.0/"
52
+ apple_desktop:apr="${apr_b64}"/>
53
+ </rdf:RDF>
54
+ </x:xmpmeta>
55
+ <?xpacket end="w"?>
56
+ XMPEOF
57
+ }
58
+
59
+ merge_pair() {
60
+ local family="$1"
61
+ local dark_file=""
62
+ local light_file=""
63
+
64
+ # Find dark and light files
65
+ for ext in heic jpg png; do
66
+ [[ -z "$dark_file" && -f "$WALLPAPER_DIR/${family}-dark.${ext}" ]] && dark_file="$WALLPAPER_DIR/${family}-dark.${ext}"
67
+ [[ -z "$light_file" && -f "$WALLPAPER_DIR/${family}-light.${ext}" ]] && light_file="$WALLPAPER_DIR/${family}-light.${ext}"
68
+ done
69
+
70
+ if [[ -z "$dark_file" || -z "$light_file" ]]; then
71
+ echo " ✗ $family — missing dark or light variant"
72
+ return 1
73
+ fi
74
+
75
+ local output="$WALLPAPER_DIR/${family}.heic"
76
+
77
+ if [[ "$DRY_RUN" == "true" ]]; then
78
+ echo " ○ $family — would merge $(basename "$light_file") + $(basename "$dark_file") → $(basename "$output")"
79
+ return 0
80
+ fi
81
+
82
+ local tmpdir
83
+ tmpdir="$(mktemp -d)"
84
+ trap "rm -rf '$tmpdir'" RETURN
85
+
86
+ # Convert both to JPEG for heif-enc input (it handles JPEG best)
87
+ magick "$light_file" -quality 95 "$tmpdir/light.jpg" 2>/dev/null
88
+ magick "$dark_file" -quality 95 "$tmpdir/dark.jpg" 2>/dev/null
89
+
90
+ # Generate XMP metadata file
91
+ generate_xmp >"$tmpdir/xmp.xml"
92
+
93
+ # Encode as multi-image HEIC: image 0 = light (primary), image 1 = dark
94
+ if heif-enc \
95
+ -q 90 \
96
+ "$tmpdir/light.jpg" \
97
+ "$tmpdir/dark.jpg" \
98
+ -o "$tmpdir/merged.heic" 2>/dev/null; then
99
+
100
+ # Inject Apple desktop appearance XMP
101
+ if command -v exiftool &>/dev/null; then
102
+ exiftool -overwrite_original -XMP="<=$tmpdir/xmp.xml" "$tmpdir/merged.heic" 2>/dev/null || true
103
+ fi
104
+
105
+ # Replace the pair with the merged file
106
+ mv "$tmpdir/merged.heic" "$output"
107
+ rm -f "$dark_file" "$light_file"
108
+ echo " ✓ $family — merged → $(basename "$output")"
109
+ return 0
110
+ else
111
+ echo " ✗ $family — heif-enc failed"
112
+ return 1
113
+ fi
114
+ }
115
+
116
+ echo "Dynamic wallpaper merger"
117
+ echo ""
118
+
119
+ if [[ -n "$TARGET" ]]; then
120
+ merge_pair "$TARGET"
121
+ else
122
+ # Find all families with dark+light pairs
123
+ merged=0
124
+ failed=0
125
+ for dark_file in "$WALLPAPER_DIR"/*-dark.heic "$WALLPAPER_DIR"/*-dark.jpg "$WALLPAPER_DIR"/*-dark.png; do
126
+ [[ -f "$dark_file" ]] || continue
127
+ base="$(basename "$dark_file")"
128
+ family="${base%-dark.*}"
129
+ if merge_pair "$family"; then
130
+ merged=$((merged + 1))
131
+ else
132
+ failed=$((failed + 1))
133
+ fi
134
+ done
135
+ echo ""
136
+ echo "Done: $merged merged, $failed failed"
137
+ if [[ "$DRY_RUN" != "true" && $merged -gt 0 ]]; then
138
+ echo ""
139
+ echo "Run 'dot theme rebuild --force' to regenerate themes for merged wallpapers."
140
+ fi
141
+ fi
@@ -0,0 +1,309 @@
1
+ #!/usr/bin/env bash
2
+ # Copyright (c) 2015-2026 Dotfiles. All rights reserved.
3
+ # rebuild-themes.sh — Discover wallpapers and generate themes.toml dynamically.
4
+ #
5
+ # Scans system wallpaper directories and ~/Pictures/Wallpapers/ for images,
6
+ # extracts dominant colors via extract-theme.py, and assembles themes.toml.
7
+ # Custom wallpapers override system wallpapers with the same name.
8
+ #
9
+ # Usage:
10
+ # bash rebuild-themes.sh # Rebuild themes.toml
11
+ # bash rebuild-themes.sh --force # Force regeneration (ignore cache)
12
+ # bash rebuild-themes.sh --list # List discovered wallpapers without rebuilding
13
+ set -euo pipefail
14
+
15
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
16
+ EXTRACT_SCRIPT="$SCRIPT_DIR/extract-theme.py"
17
+ DOTFILES_DIR="${HOME}/.dotfiles"
18
+ THEMES_FILE="$DOTFILES_DIR/.chezmoidata/themes.toml"
19
+ CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/dotfiles/themes"
20
+ CUSTOM_DIR="${DOTFILES_WALLPAPER_DIR:-$HOME/Pictures/Wallpapers}"
21
+
22
+ FORCE=false
23
+ LIST_ONLY=false
24
+
25
+ for arg in "$@"; do
26
+ case "$arg" in
27
+ --force) FORCE=true ;;
28
+ --list) LIST_ONLY=true ;;
29
+ esac
30
+ done
31
+
32
+ # ---------------------------------------------------------------------------
33
+ # Discover wallpapers from all sources
34
+ # ---------------------------------------------------------------------------
35
+
36
+ declare -A WALLPAPERS # name -> path (custom overrides system)
37
+ declare -A WP_SOURCE # name -> "system" | "custom"
38
+
39
+ discover_macos_system() {
40
+ local sys_dir="/System/Library/Desktop Pictures"
41
+ [[ -d "$sys_dir" ]] || return 0
42
+
43
+ # Register top-level system wallpapers (will be deduped later if thumbnails have dark/light)
44
+ local file name
45
+ for file in "$sys_dir"/*.heic; do
46
+ [[ -f "$file" ]] || continue
47
+ name="$(basename "$file" .heic)"
48
+ name="$(echo "$name" | tr '[:upper:]' '[:lower:]' | tr ' ' '-')"
49
+ name="${name//[^a-z0-9-]/}"
50
+ WALLPAPERS["$name"]="$file"
51
+ WP_SOURCE["$name"]="system"
52
+ done
53
+
54
+ # Also check .thumbnails for wallpapers with Dark/Light variants
55
+ local thumb_dir="$sys_dir/.thumbnails"
56
+ if [[ -d "$thumb_dir" ]]; then
57
+ # First pass: register all thumbnails
58
+ for file in "$thumb_dir"/*.heic; do
59
+ [[ -f "$file" ]] || continue
60
+ local base
61
+ base="$(basename "$file" .heic)"
62
+ name="$(echo "$base" | tr '[:upper:]' '[:lower:]' | tr ' ' '-')"
63
+ name="${name//[^a-z0-9-]/}"
64
+ if [[ -z "${WALLPAPERS[$name]+x}" ]]; then
65
+ WALLPAPERS["$name"]="$file"
66
+ WP_SOURCE["$name"]="system"
67
+ fi
68
+ done
69
+
70
+ # Second pass: remove base wallpapers that have explicit dark/light variants
71
+ # e.g. if "big-sur-graphic-dark" exists, remove "big-sur-graphic"
72
+ local check_name
73
+ for name in "${!WALLPAPERS[@]}"; do
74
+ if [[ "${name}" != *-dark && "${name}" != *-light ]]; then
75
+ check_name="${name}-dark"
76
+ if [[ -n "${WALLPAPERS[$check_name]+x}" ]]; then
77
+ unset "WALLPAPERS[$name]"
78
+ unset "WP_SOURCE[$name]"
79
+ continue
80
+ fi
81
+ check_name="${name}-light"
82
+ if [[ -n "${WALLPAPERS[$check_name]+x}" ]]; then
83
+ unset "WALLPAPERS[$name]"
84
+ unset "WP_SOURCE[$name]"
85
+ fi
86
+ fi
87
+ done
88
+ fi
89
+ }
90
+
91
+ discover_linux_system() {
92
+ local dirs=(
93
+ /usr/share/backgrounds
94
+ /usr/share/wallpapers
95
+ )
96
+
97
+ local dir file name
98
+ for dir in "${dirs[@]}"; do
99
+ [[ -d "$dir" ]] || continue
100
+ while IFS= read -r file; do
101
+ name="$(basename "$file")"
102
+ name="${name%.*}"
103
+ name="$(echo "$name" | tr '[:upper:]' '[:lower:]' | tr ' ' '-')"
104
+ name="${name//[^a-z0-9-]/}"
105
+ # Avoid duplicates — first found wins for system
106
+ if [[ -z "${WALLPAPERS[$name]+x}" ]]; then
107
+ WALLPAPERS["$name"]="$file"
108
+ WP_SOURCE["$name"]="system"
109
+ fi
110
+ done < <(find "$dir" -maxdepth 3 -type f \( -name "*.jpg" -o -name "*.png" -o -name "*.heic" \) 2>/dev/null | sort)
111
+ done
112
+ }
113
+
114
+ discover_custom() {
115
+ [[ -d "$CUSTOM_DIR" ]] || return 0
116
+
117
+ local file name frame_count
118
+ for file in "$CUSTOM_DIR"/*.heic "$CUSTOM_DIR"/*.jpg "$CUSTOM_DIR"/*.png; do
119
+ [[ -f "$file" ]] || continue
120
+ name="$(basename "$file")"
121
+ name="${name%.*}"
122
+
123
+ # Check if this is a dynamic HEIC (multi-frame = light+dark in one file)
124
+ if [[ "${file##*.}" == "heic" ]]; then
125
+ frame_count="$(magick identify "$file" 2>/dev/null | wc -l | tr -d ' ')"
126
+ if [[ "$frame_count" -ge 2 && "$name" != *-dark && "$name" != *-light ]]; then
127
+ # Dynamic HEIC: register as both dark and light
128
+ WALLPAPERS["${name}-light"]="${file}[0]"
129
+ WP_SOURCE["${name}-light"]="custom"
130
+ WALLPAPERS["${name}-dark"]="${file}[1]"
131
+ WP_SOURCE["${name}-dark"]="custom"
132
+ # Store the original file path for wallpaper-sync
133
+ WALLPAPERS["${name}"]="$file"
134
+ WP_SOURCE["${name}"]="custom-dynamic"
135
+ continue
136
+ fi
137
+ fi
138
+
139
+ WALLPAPERS["$name"]="$file"
140
+ WP_SOURCE["$name"]="custom"
141
+ done
142
+ }
143
+
144
+ # Remove dynamic base entries (keep only the -dark/-light variants for theme gen)
145
+ cleanup_dynamic_entries() {
146
+ for name in "${!WP_SOURCE[@]}"; do
147
+ if [[ "${WP_SOURCE[$name]}" == "custom-dynamic" ]]; then
148
+ unset "WALLPAPERS[$name]"
149
+ unset "WP_SOURCE[$name]"
150
+ fi
151
+ done
152
+ }
153
+
154
+ # Discover in order: system first, custom overrides
155
+ case "$(uname -s)" in
156
+ Darwin) discover_macos_system ;;
157
+ Linux) discover_linux_system ;;
158
+ esac
159
+ discover_custom
160
+ cleanup_dynamic_entries
161
+
162
+ # ---------------------------------------------------------------------------
163
+ # List mode
164
+ # ---------------------------------------------------------------------------
165
+
166
+ if [[ "$LIST_ONLY" == "true" ]]; then
167
+ printf '%-40s %-8s %s\n' "NAME" "SOURCE" "PATH"
168
+ printf '%-40s %-8s %s\n' "----" "------" "----"
169
+ for name in $(printf '%s\n' "${!WALLPAPERS[@]}" | sort); do
170
+ printf '%-40s %-8s %s\n' "$name" "${WP_SOURCE[$name]}" "${WALLPAPERS[$name]}"
171
+ done
172
+ echo ""
173
+ echo "Total: ${#WALLPAPERS[@]} wallpapers"
174
+ exit 0
175
+ fi
176
+
177
+ # ---------------------------------------------------------------------------
178
+ # Check dependencies
179
+ # ---------------------------------------------------------------------------
180
+
181
+ if [[ ! -f "$EXTRACT_SCRIPT" ]]; then
182
+ echo "Error: extract-theme.py not found at $EXTRACT_SCRIPT" >&2
183
+ exit 1
184
+ fi
185
+
186
+ if ! command -v python3 &>/dev/null; then
187
+ echo "Error: python3 required" >&2
188
+ exit 1
189
+ fi
190
+
191
+ if ! command -v magick &>/dev/null; then
192
+ echo "Error: ImageMagick (magick) required" >&2
193
+ exit 1
194
+ fi
195
+
196
+ mkdir -p "$CACHE_DIR"
197
+
198
+ # Clean orphaned cache files (wallpapers that no longer exist)
199
+ for cache_file in "$CACHE_DIR"/*.toml; do
200
+ [[ -f "$cache_file" ]] || continue
201
+ cached_name="$(basename "$cache_file" .toml)"
202
+ if [[ -z "${WALLPAPERS[$cached_name]+x}" ]]; then
203
+ rm -f "$cache_file"
204
+ fi
205
+ done
206
+
207
+ # ---------------------------------------------------------------------------
208
+ # Generate themes
209
+ # ---------------------------------------------------------------------------
210
+
211
+ sys_count=0
212
+ cust_count=0
213
+ for name in "${!WP_SOURCE[@]}"; do
214
+ case "${WP_SOURCE[$name]}" in
215
+ system) sys_count=$((sys_count + 1)) ;;
216
+ custom) cust_count=$((cust_count + 1)) ;;
217
+ esac
218
+ done
219
+ echo "Discovering wallpapers..."
220
+ echo " Found: $sys_count system, $cust_count custom (${#WALLPAPERS[@]} total)"
221
+ echo ""
222
+
223
+ GENERATED=0
224
+ CACHED=0
225
+ FAILED=0
226
+
227
+ echo "Generating themes..."
228
+
229
+ # Build work list (skip cached)
230
+ WORK=()
231
+ for name in $(printf '%s\n' "${!WALLPAPERS[@]}" | sort); do
232
+ [[ -n "${WALLPAPERS[$name]+x}" ]] || continue
233
+ wp_path="${WALLPAPERS[$name]}"
234
+ cache_file="$CACHE_DIR/${name}.toml"
235
+
236
+ if [[ "$FORCE" != "true" && -f "$cache_file" && "$cache_file" -nt "$wp_path" ]]; then
237
+ CACHED=$((CACHED + 1))
238
+ continue
239
+ fi
240
+ WORK+=("$name")
241
+ done
242
+
243
+ # Process in parallel (up to 4 jobs)
244
+ JOBS=4
245
+ TOTAL_WORK=${#WORK[@]}
246
+ if [[ $TOTAL_WORK -gt 0 ]]; then
247
+ echo " Processing $TOTAL_WORK wallpapers ($JOBS parallel jobs)..."
248
+ for name in "${WORK[@]}"; do
249
+ wp_path="${WALLPAPERS[$name]}"
250
+ cache_file="$CACHE_DIR/${name}.toml"
251
+ source_type="${WP_SOURCE[$name]}"
252
+
253
+ (
254
+ if python3 "$EXTRACT_SCRIPT" "$wp_path" --name "$name" --source "$source_type" >"$cache_file" 2>/dev/null; then
255
+ printf " %-40s [%s] ✓\n" "$name" "$source_type"
256
+ else
257
+ rm -f "$cache_file"
258
+ printf " %-40s [%s] ✗\n" "$name" "$source_type"
259
+ fi
260
+ ) &
261
+
262
+ # Limit parallel jobs
263
+ while [[ $(jobs -r | wc -l) -ge $JOBS ]]; do
264
+ wait -n 2>/dev/null || true
265
+ done
266
+ done
267
+ wait
268
+ fi
269
+
270
+ # Count results
271
+ GENERATED=$(find "$CACHE_DIR" -name "*.toml" -newer "$0" 2>/dev/null | wc -l | tr -d ' ')
272
+ FAILED=$((TOTAL_WORK - GENERATED))
273
+ echo ""
274
+ echo "Results: $TOTAL_WORK processed, $CACHED cached, $FAILED failed"
275
+
276
+ # ---------------------------------------------------------------------------
277
+ # Assemble themes.toml
278
+ # ---------------------------------------------------------------------------
279
+
280
+ echo ""
281
+ echo "Assembling themes.toml..."
282
+
283
+ {
284
+ cat <<'HEADER'
285
+ # ============================================================================
286
+ # Theme Manifest — Auto-generated from wallpaper dominant colors
287
+ # ============================================================================
288
+ # Generated by: scripts/theme/rebuild-themes.sh
289
+ # Algorithm: K-Means clustering in CIELAB color space
290
+ # Do not edit manually — run `dot theme rebuild` to regenerate.
291
+ #
292
+ # Sources:
293
+ # System: /System/Library/Desktop Pictures/ (macOS)
294
+ # /usr/share/backgrounds/ (Linux)
295
+ # Custom: ~/Pictures/Wallpapers/
296
+
297
+ HEADER
298
+
299
+ for cache_file in "$CACHE_DIR"/*.toml; do
300
+ [[ -f "$cache_file" ]] || continue
301
+ echo ""
302
+ cat "$cache_file"
303
+ done
304
+ } >"$THEMES_FILE"
305
+
306
+ theme_count=$(grep -c '^\[themes\.' "$THEMES_FILE" | head -1)
307
+ echo " Written: $THEMES_FILE ($theme_count theme sections)"
308
+ echo ""
309
+ echo "Done. Run 'dot theme list' to see available themes."