@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,28 +1,49 @@
1
1
  #!/usr/bin/env bash
2
+ # Copyright (c) 2015-2026 Dotfiles. All rights reserved.
2
3
  # Dotfiles Health Check Dashboard
3
- # Usage: dot health [--verbose|-v] [--json]
4
+ # Usage: dot health [--verbose|-v] [--json|-j] [--fix|-f] [--force|-F]
4
5
 
5
6
  set -euo pipefail
6
7
 
7
- # Colors
8
- RED='\033[0;31m'
9
- GREEN='\033[0;32m'
10
- YELLOW='\033[1;33m'
11
- BLUE='\033[0;34m'
12
- CYAN='\033[0;36m'
13
- GRAY='\033[0;90m'
14
- NC='\033[0m'
8
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
9
+ # shellcheck source=../dot/lib/ui.sh
10
+ # shellcheck disable=SC1091
11
+ source "$SCRIPT_DIR/../dot/lib/ui.sh"
12
+ # shellcheck source=../dot/lib/log.sh
13
+ # shellcheck disable=SC1091
14
+ source "$SCRIPT_DIR/../dot/lib/log.sh"
15
+
16
+ # Portable has_command (self-contained; no dependency on utils.sh)
17
+ has_command() { command -v "$1" >/dev/null 2>&1; }
18
+
19
+ # Colors (fallback when gum is unavailable; respect NO_COLOR)
20
+ if [[ -z "${NO_COLOR:-}" ]] && [[ -t 1 ]]; then
21
+ RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m'
22
+ BLUE='\033[0;34m' CYAN='\033[0;36m' GRAY='\033[0;90m' NC='\033[0m'
23
+ else
24
+ RED='' GREEN='' YELLOW='' BLUE='' CYAN='' GRAY='' NC=''
25
+ fi
15
26
 
16
27
  # Parse arguments (VERBOSE exported for potential use by sourced scripts)
17
28
  export VERBOSE=false
18
29
  JSON_OUTPUT=false
30
+ APPLY_FIX=false
31
+ FORCE_FIX=false
19
32
  while [[ $# -gt 0 ]]; do
20
33
  case "$1" in
21
34
  --verbose | -v)
22
35
  VERBOSE=true
23
36
  shift
24
37
  ;;
25
- --json)
38
+ --fix | -f)
39
+ APPLY_FIX=true
40
+ shift
41
+ ;;
42
+ --force | -F)
43
+ FORCE_FIX=true
44
+ shift
45
+ ;;
46
+ --json | -j)
26
47
  JSON_OUTPUT=true
27
48
  shift
28
49
  ;;
@@ -30,12 +51,45 @@ while [[ $# -gt 0 ]]; do
30
51
  esac
31
52
  done
32
53
 
54
+ reset_stats() {
55
+ TOTAL_CHECKS=0
56
+ PASSED_CHECKS=0
57
+ WARNINGS=0
58
+ FAILURES=0
59
+ }
60
+
33
61
  # Health check results
34
- declare -A RESULTS
35
62
  TOTAL_CHECKS=0
36
63
  PASSED_CHECKS=0
37
64
  WARNINGS=0
38
65
  FAILURES=0
66
+ declare -a RESULTS=()
67
+ ui_init
68
+ use_ui="$UI_ENABLED"
69
+
70
+ header() {
71
+ local text="$1"
72
+ if $JSON_OUTPUT; then
73
+ return
74
+ fi
75
+ if [[ "$use_ui" = "1" ]]; then
76
+ ui_header "$text"
77
+ else
78
+ printf '%b\n' "${CYAN}${text}${NC}"
79
+ fi
80
+ }
81
+
82
+ section() {
83
+ local text="$1"
84
+ if $JSON_OUTPUT; then
85
+ return
86
+ fi
87
+ if [[ "$use_ui" = "1" ]]; then
88
+ ui_section "$text"
89
+ else
90
+ printf '%b\n' "\n${BLUE}▸ $text${NC}"
91
+ fi
92
+ }
39
93
 
40
94
  check() {
41
95
  local name="$1"
@@ -44,33 +98,48 @@ check() {
44
98
 
45
99
  TOTAL_CHECKS=$((TOTAL_CHECKS + 1))
46
100
 
101
+ # Collect structured result for JSON output (escape quotes for valid JSON)
102
+ local _j_name="${name//\"/\\\"}"
103
+ local _j_status="${status//\"/\\\"}"
104
+ local _j_message="${message//\"/\\\"}"
105
+ RESULTS+=("{\"check\":\"${_j_name}\",\"status\":\"${_j_status}\",\"message\":\"${_j_message}\"}")
106
+
47
107
  case "$status" in
48
108
  pass)
49
109
  PASSED_CHECKS=$((PASSED_CHECKS + 1))
50
110
  # shellcheck disable=SC2034
51
- RESULTS["$name"]="pass"
52
111
  if ! $JSON_OUTPUT; then
53
- printf "${GREEN}✓${NC} %-35s ${GREEN}OK${NC}\n" "$name"
112
+ if [[ "$use_ui" = "1" ]]; then
113
+ ui_ok "$name"
114
+ else
115
+ printf "${GREEN}✓${NC} %-35s ${GREEN}OK${NC}\n" "$name"
116
+ fi
54
117
  fi
55
118
  ;;
56
119
  warn)
57
120
  WARNINGS=$((WARNINGS + 1))
58
121
  # shellcheck disable=SC2034
59
- RESULTS["$name"]="warn"
60
122
  if ! $JSON_OUTPUT; then
61
- printf "${YELLOW}⚠${NC} %-35s ${YELLOW}WARNING${NC}"
62
- [[ -n "$message" ]] && printf " ${GRAY}%s${NC}" "$message"
63
- printf "\n"
123
+ if [[ "$use_ui" = "1" ]]; then
124
+ ui_warn "$name" "$message"
125
+ else
126
+ printf "${YELLOW}⚠${NC} %-35s ${YELLOW}WARNING${NC}"
127
+ [[ -n "$message" ]] && printf " ${GRAY}%s${NC}" "$message"
128
+ printf "\n"
129
+ fi
64
130
  fi
65
131
  ;;
66
132
  fail)
67
133
  FAILURES=$((FAILURES + 1))
68
134
  # shellcheck disable=SC2034
69
- RESULTS["$name"]="fail"
70
135
  if ! $JSON_OUTPUT; then
71
- printf "${RED}✗${NC} %-35s ${RED}FAILED${NC}"
72
- [[ -n "$message" ]] && printf " ${GRAY}%s${NC}" "$message"
73
- printf "\n"
136
+ if [[ "$use_ui" = "1" ]]; then
137
+ ui_err "$name" "$message"
138
+ else
139
+ printf "${RED}✗${NC} %-35s ${RED}FAILED${NC}"
140
+ [[ -n "$message" ]] && printf " ${GRAY}%s${NC}" "$message"
141
+ printf "\n"
142
+ fi
74
143
  fi
75
144
  ;;
76
145
  esac
@@ -78,28 +147,32 @@ check() {
78
147
 
79
148
  print_header() {
80
149
  if ! $JSON_OUTPUT; then
81
- echo -e "\n${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
82
- echo -e "${CYAN} Dotfiles Health Dashboard${NC}"
83
- echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}\n"
150
+ echo ""
151
+ ui_dot_banner "Diagnostics"
152
+ header "Dotfiles Health Dashboard"
153
+ echo ""
84
154
  fi
85
155
  }
86
156
 
87
157
  check_section() {
88
158
  if ! $JSON_OUTPUT; then
89
- echo -e "\n${BLUE}▸ $1${NC}"
90
- echo "───────────────────────────────────────────────"
159
+ echo ""
160
+ section "$1"
161
+ if [[ "$use_ui" = "1" ]]; then
162
+ :
163
+ else
164
+ echo "───────────────────────────────────────────────"
165
+ fi
91
166
  fi
92
167
  }
93
168
 
94
- # === Core Checks ===
95
- run_checks() {
96
- # --- Dotfiles Core ---
169
+ # === Focused check sub-functions ===
170
+
171
+ check_dotfiles_core() {
97
172
  check_section "Dotfiles Core"
98
173
 
99
- # Chezmoi
100
- if command -v chezmoi >/dev/null 2>&1; then
174
+ if has_command chezmoi; then
101
175
  check "Chezmoi installed" "pass"
102
- # Check if source dir exists
103
176
  if [[ -d "${HOME}/.local/share/chezmoi" ]] || [[ -d "${HOME}/.dotfiles" ]]; then
104
177
  check "Chezmoi source directory" "pass"
105
178
  else
@@ -109,8 +182,7 @@ run_checks() {
109
182
  check "Chezmoi installed" "fail" "Not installed"
110
183
  fi
111
184
 
112
- # Git
113
- if command -v git >/dev/null 2>&1; then
185
+ if has_command git; then
114
186
  check "Git installed" "pass"
115
187
  if git config user.email >/dev/null 2>&1; then
116
188
  check "Git user configured" "pass"
@@ -120,41 +192,42 @@ run_checks() {
120
192
  else
121
193
  check "Git installed" "fail"
122
194
  fi
195
+ }
123
196
 
124
- # --- Shell ---
197
+ check_shell_env() {
125
198
  check_section "Shell Environment"
199
+ local current_shell="${SHELL##*/}"
126
200
 
127
- # Zsh
128
- if command -v zsh >/dev/null 2>&1; then
201
+ if has_command zsh; then
129
202
  check "Zsh installed" "pass"
130
- if [[ "$SHELL" == *"zsh"* ]]; then
131
- check "Zsh is default shell" "pass"
203
+ if [[ "$current_shell" =~ ^(zsh|fish|bash|nu|nushell)$ ]]; then
204
+ check "Active shell" "pass" "$current_shell"
132
205
  else
133
- check "Zsh is default shell" "warn" "Current: $SHELL"
206
+ check "Active shell" "warn" "Current: $SHELL"
134
207
  fi
135
208
  else
136
209
  check "Zsh installed" "fail"
137
210
  fi
138
211
 
139
- # Zinit
140
212
  if [[ -d "${ZINIT_HOME:-$HOME/.local/share/zinit}" ]]; then
141
213
  check "Zinit plugin manager" "pass"
142
- else
214
+ elif [[ "$current_shell" == "zsh" ]]; then
143
215
  check "Zinit plugin manager" "warn" "Not found"
216
+ else
217
+ check "Zinit plugin manager" "pass" "Not required for $current_shell"
144
218
  fi
145
219
 
146
- # Starship
147
- if command -v starship >/dev/null 2>&1; then
220
+ if has_command starship; then
148
221
  check "Starship prompt" "pass"
149
222
  else
150
223
  check "Starship prompt" "warn" "Not installed"
151
224
  fi
225
+ }
152
226
 
153
- # --- Development Tools ---
227
+ check_dev_tools() {
154
228
  check_section "Development Tools"
155
229
 
156
- # Node.js
157
- if command -v node >/dev/null 2>&1; then
230
+ if has_command node; then
158
231
  local node_version
159
232
  node_version=$(node --version 2>/dev/null)
160
233
  check "Node.js ($node_version)" "pass"
@@ -162,15 +235,15 @@ run_checks() {
162
235
  check "Node.js" "warn" "Not installed"
163
236
  fi
164
237
 
165
- # fnm
166
- if command -v fnm >/dev/null 2>&1; then
238
+ if has_command fnm; then
167
239
  check "fnm (Node version manager)" "pass"
240
+ elif has_command mise && has_command node; then
241
+ check "Node version manager" "pass" "mise"
168
242
  else
169
243
  check "fnm" "warn" "Not installed"
170
244
  fi
171
245
 
172
- # Python
173
- if command -v python3 >/dev/null 2>&1; then
246
+ if has_command python3; then
174
247
  local py_version
175
248
  py_version=$(python3 --version 2>/dev/null | cut -d' ' -f2)
176
249
  check "Python ($py_version)" "pass"
@@ -178,38 +251,38 @@ run_checks() {
178
251
  check "Python" "warn" "Not installed"
179
252
  fi
180
253
 
181
- # Rust
182
- if command -v rustc >/dev/null 2>&1; then
254
+ if has_command rustc; then
183
255
  check "Rust toolchain" "pass"
184
256
  else
185
257
  check "Rust toolchain" "warn" "Not installed"
186
258
  fi
187
259
 
188
- # Go
189
- if command -v go >/dev/null 2>&1; then
260
+ if has_command go; then
190
261
  check "Go" "pass"
191
262
  else
192
263
  check "Go" "warn" "Not installed"
193
264
  fi
265
+ }
194
266
 
195
- # --- CLI Tools ---
267
+ check_cli_tools() {
196
268
  check_section "CLI Tools"
197
269
 
198
270
  local tools=("fzf" "ripgrep:rg" "fd" "bat" "eza" "zoxide" "atuin" "delta" "jq" "yq" "sops" "mise" "just" "zellij" "hyperfine")
199
271
  for tool in "${tools[@]}"; do
200
272
  local name="${tool%%:*}"
201
273
  local cmd="${tool##*:}"
202
- if command -v "$cmd" >/dev/null 2>&1; then
274
+ if has_command "$cmd"; then
203
275
  check "$name" "pass"
204
276
  else
205
277
  check "$name" "warn" "Not installed"
206
278
  fi
207
279
  done
280
+ }
208
281
 
209
- # --- Editors ---
282
+ check_editors() {
210
283
  check_section "Editors"
211
284
 
212
- if command -v nvim >/dev/null 2>&1; then
285
+ if has_command nvim; then
213
286
  check "Neovim" "pass"
214
287
  if [[ -d "${XDG_DATA_HOME:-$HOME/.local/share}/nvim/lazy" ]]; then
215
288
  check "Neovim plugins (lazy.nvim)" "pass"
@@ -219,37 +292,42 @@ run_checks() {
219
292
  else
220
293
  check "Neovim" "warn" "Not installed"
221
294
  fi
295
+ }
222
296
 
223
- # --- Terminal ---
297
+ check_terminal() {
224
298
  check_section "Terminal"
225
299
 
226
- if command -v ghostty >/dev/null 2>&1 || [[ -d "/Applications/Ghostty.app" ]]; then
300
+ if has_command ghostty || [[ -d "/Applications/Ghostty.app" ]]; then
227
301
  check "Ghostty terminal" "pass"
228
302
  else
229
303
  check "Ghostty terminal" "warn" "Not installed"
230
304
  fi
231
305
 
232
- # Fonts - check both Linux and macOS font locations
233
306
  local font_found=false
234
- if fc-list 2>/dev/null | grep -qi "JetBrains"; then
235
- font_found=true
236
- elif [[ -d "$HOME/Library/Fonts" ]] && compgen -G "$HOME/Library/Fonts/"*[Jj]et[Bb]rains* >/dev/null 2>&1; then
307
+ if command -v fc-list >/dev/null 2>&1; then
308
+ local fc_list_output=""
309
+ fc_list_output="$(fc-list 2>/dev/null || true)"
310
+ if [[ "$fc_list_output" == *"Nerd Font"* ]]; then
311
+ font_found=true
312
+ fi
313
+ fi
314
+ if [[ "$font_found" != true ]] && [[ -d "$HOME/Library/Fonts" ]] && compgen -G "$HOME/Library/Fonts/"'*Nerd*' >/dev/null 2>&1; then
237
315
  font_found=true
238
- elif [[ -d "$HOME/.local/share/fonts" ]] && compgen -G "$HOME/.local/share/fonts/"*[Jj]et[Bb]rains* >/dev/null 2>&1; then
316
+ elif [[ "$font_found" != true ]] && [[ -d "$HOME/.local/share/fonts" ]] && compgen -G "$HOME/.local/share/fonts/"'*Nerd*' >/dev/null 2>&1; then
239
317
  font_found=true
240
318
  fi
241
319
 
242
320
  if $font_found; then
243
- check "JetBrains Mono Nerd Font" "pass"
321
+ check "Nerd Font available" "pass"
244
322
  else
245
- check "JetBrains Mono Nerd Font" "warn" "Not installed"
323
+ check "Nerd Font available" "warn" "Not installed"
246
324
  fi
325
+ }
247
326
 
248
- # --- Security ---
327
+ check_security() {
249
328
  check_section "Security"
250
329
 
251
- # Age encryption
252
- if command -v age >/dev/null 2>&1; then
330
+ if has_command age; then
253
331
  check "Age encryption" "pass"
254
332
  if [[ -f "${HOME}/.config/chezmoi/key.txt" ]]; then
255
333
  check "Age key configured" "pass"
@@ -260,16 +338,34 @@ run_checks() {
260
338
  check "Age encryption" "warn" "Not installed"
261
339
  fi
262
340
 
263
- # SSH
264
341
  if [[ -f "${HOME}/.ssh/id_ed25519" ]] || [[ -f "${HOME}/.ssh/id_rsa" ]]; then
265
342
  check "SSH keys present" "pass"
266
343
  else
267
344
  check "SSH keys present" "warn" "No keys found"
268
345
  fi
269
346
 
270
- # GPG
271
- if command -v gpg >/dev/null 2>&1; then
272
- if gpg --list-secret-keys 2>/dev/null | grep -q sec; then
347
+ # Check SSH key permissions
348
+ for key in "$HOME/.ssh/id_ed25519" "$HOME/.ssh/id_rsa" "$HOME/.ssh/id_ed25519_sk"; do
349
+ if [[ -f "$key" ]]; then
350
+ local perms
351
+ perms=$(stat -c '%a' "$key" 2>/dev/null || stat -f '%Lp' "$key" 2>/dev/null)
352
+ if [[ "$perms" != "600" && "$perms" != "400" ]]; then
353
+ check "SSH key perms (${key##*/})" "warn" "mode $perms (should be 600)"
354
+ else
355
+ check "SSH key perms (${key##*/})" "pass"
356
+ fi
357
+ fi
358
+ done
359
+
360
+ if has_command gpg; then
361
+ local signing_format signing_key allowed_signers
362
+ signing_format="$(git config --global gpg.format 2>/dev/null || true)"
363
+ signing_key="$(git config --global user.signingkey 2>/dev/null || true)"
364
+ allowed_signers="$(git config --global gpg.ssh.allowedSignersFile 2>/dev/null || echo "$HOME/.config/git/allowed_signers")"
365
+
366
+ if [[ "$signing_format" == "ssh" ]] && [[ -n "$signing_key" ]] && [[ -f "${signing_key/#\~/$HOME}" ]] && [[ -f "${allowed_signers/#\~/$HOME}" ]]; then
367
+ check "Git signing" "pass" "ssh"
368
+ elif gpg --list-secret-keys 2>/dev/null | grep -q sec; then
273
369
  check "GPG keys" "pass"
274
370
  else
275
371
  check "GPG keys" "warn" "No secret keys"
@@ -277,17 +373,15 @@ run_checks() {
277
373
  else
278
374
  check "GPG" "warn" "Not installed"
279
375
  fi
376
+ }
280
377
 
281
- # --- Performance ---
378
+ check_performance() {
282
379
  check_section "Performance"
283
380
 
284
- # Shell startup time
285
- if command -v zsh >/dev/null 2>&1; then
381
+ if has_command zsh; then
286
382
  local startup_time
287
383
  startup_time=$({ time zsh -i -c exit; } 2>&1 | grep real | awk '{print $2}' | sed 's/[ms]//g')
288
- # Try to parse the time (handle different formats)
289
384
  if [[ -n "$startup_time" ]]; then
290
- # Simple check - if startup mentions 0m0, it's under 1 second
291
385
  check "Shell startup time" "pass"
292
386
  else
293
387
  check "Shell startup time" "warn" "Could not measure"
@@ -295,62 +389,209 @@ run_checks() {
295
389
  fi
296
390
  }
297
391
 
392
+ check_config_directories() {
393
+ check_section "Config Directories"
394
+
395
+ local config_dirs=(
396
+ "$HOME/.config/shell"
397
+ "$HOME/.config/nvim"
398
+ "$HOME/.config/git"
399
+ )
400
+ local found=0 total=${#config_dirs[@]}
401
+
402
+ for dir in "${config_dirs[@]}"; do
403
+ if [[ -d "$dir" ]]; then
404
+ check "Config: ${dir##*/}" "pass"
405
+ found=$((found + 1))
406
+ else
407
+ check "Config: ${dir##*/}" "warn" "Not found"
408
+ fi
409
+ done
410
+
411
+ if [[ $found -eq $total ]]; then
412
+ check "Config directories" "pass"
413
+ elif [[ $found -gt 0 ]]; then
414
+ check "Config directories" "warn" "$found/$total present"
415
+ else
416
+ check "Config directories" "fail" "None found"
417
+ fi
418
+ }
419
+
420
+ check_sync_status() {
421
+ check_section "Sync Status"
422
+
423
+ # Chezmoi status
424
+ if has_command chezmoi; then
425
+ local status_output
426
+ status_output=$(chezmoi status 2>/dev/null || echo "")
427
+ if [[ -z "$status_output" ]]; then
428
+ check "Chezmoi sync" "pass"
429
+ else
430
+ local changes
431
+ changes=$(printf '%s\n' "$status_output" | wc -l | tr -d ' ')
432
+ check "Chezmoi sync" "warn" "$changes file(s) out of sync"
433
+ fi
434
+ else
435
+ check "Chezmoi sync" "warn" "Not installed, skipped"
436
+ fi
437
+
438
+ # Git status
439
+ local dotfiles_dir="${HOME}/.dotfiles"
440
+ if [[ -d "$dotfiles_dir/.git" ]]; then
441
+ local git_status=""
442
+ git_status=$(git -C "$dotfiles_dir" status --porcelain 2>/dev/null || echo "")
443
+ if [[ -z "$git_status" ]]; then
444
+ check "Git working tree" "pass"
445
+ else
446
+ local changes
447
+ changes=$(printf '%s\n' "$git_status" | wc -l | tr -d ' ')
448
+ check "Git working tree" "pass" "$changes local change(s)"
449
+ fi
450
+ else
451
+ check "Git working tree" "warn" "Not a git repo"
452
+ fi
453
+ }
454
+
455
+ # === Orchestrator ===
456
+ run_checks() {
457
+ check_dotfiles_core
458
+ check_shell_env
459
+ check_dev_tools
460
+ check_cli_tools
461
+ check_editors
462
+ check_terminal
463
+ check_security
464
+ check_config_directories
465
+ check_sync_status
466
+ check_performance
467
+ }
468
+
298
469
  print_summary() {
470
+ local score=$((PASSED_CHECKS * 100 / TOTAL_CHECKS))
471
+
299
472
  if $JSON_OUTPUT; then
300
- echo "{"
301
- echo " \"total\": $TOTAL_CHECKS,"
302
- echo " \"passed\": $PASSED_CHECKS,"
303
- echo " \"warnings\": $WARNINGS,"
304
- echo " \"failures\": $FAILURES,"
305
- echo " \"score\": $((PASSED_CHECKS * 100 / TOTAL_CHECKS))"
306
- echo "}"
473
+ printf '{\n'
474
+ printf ' "total": %d,\n' "$TOTAL_CHECKS"
475
+ printf ' "passed": %d,\n' "$PASSED_CHECKS"
476
+ printf ' "warnings": %d,\n' "$WARNINGS"
477
+ printf ' "failures": %d,\n' "$FAILURES"
478
+ printf ' "score": %d,\n' "$score"
479
+ printf ' "results": [\n'
480
+ local i=0
481
+ for result in "${RESULTS[@]}"; do
482
+ if [[ $i -gt 0 ]]; then
483
+ printf ',\n'
484
+ fi
485
+ printf ' %s' "$result"
486
+ i=$((i + 1))
487
+ done
488
+ printf '\n ]\n'
489
+ printf '}\n'
490
+ dot_log info "health_complete" "score=$score" "total=$TOTAL_CHECKS"
491
+ dot_metric "health_score" "$score" "percent"
307
492
  return
308
493
  fi
309
494
 
310
- local score=$((PASSED_CHECKS * 100 / TOTAL_CHECKS))
311
-
312
- echo -e "\n${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
313
- echo -e "${CYAN} Summary${NC}"
314
- echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}\n"
495
+ echo ""
496
+ header "Summary"
497
+ echo ""
315
498
 
316
- echo -e " Total checks: ${TOTAL_CHECKS}"
317
- echo -e " ${GREEN}Passed:${NC} ${PASSED_CHECKS}"
318
- echo -e " ${YELLOW}Warnings:${NC} ${WARNINGS}"
319
- echo -e " ${RED}Failures:${NC} ${FAILURES}"
499
+ if [[ "$use_ui" = "1" ]]; then
500
+ printf " %-12s %s\n" "Total checks:" "${TOTAL_CHECKS}"
501
+ printf " %-12s %s\n" "Passed:" "$(gum style --foreground 2 "$PASSED_CHECKS")"
502
+ printf " %-12s %s\n" "Warnings:" "$(gum style --foreground 3 "$WARNINGS")"
503
+ printf " %-12s %s\n" "Failures:" "$(gum style --foreground 1 "$FAILURES")"
504
+ else
505
+ printf '%b\n' " Total checks: ${TOTAL_CHECKS}"
506
+ printf '%b\n' " ${GREEN}Passed:${NC} ${PASSED_CHECKS}"
507
+ printf '%b\n' " ${YELLOW}Warnings:${NC} ${WARNINGS}"
508
+ printf '%b\n' " ${RED}Failures:${NC} ${FAILURES}"
509
+ fi
320
510
  echo ""
321
511
 
322
512
  # Health score bar
323
513
  local bar_width=30
324
514
  local filled=$((score * bar_width / 100))
325
515
  local empty=$((bar_width - filled))
516
+ local filled_bar="" empty_bar="" i
517
+
518
+ for ((i = 0; i < filled; i++)); do
519
+ filled_bar+="${_GL_BAR_FILL}"
520
+ done
521
+ for ((i = 0; i < empty; i++)); do
522
+ empty_bar+="${_GL_BAR_EMPTY}"
523
+ done
326
524
 
327
- printf " Health Score: ["
328
- if [[ $score -ge 80 ]]; then
329
- printf '%s' "${GREEN}"
330
- elif [[ $score -ge 60 ]]; then
331
- printf '%s' "${YELLOW}"
525
+ if [[ "$use_ui" = "1" ]]; then
526
+ local bar_color
527
+ if [[ $score -ge 80 ]]; then
528
+ bar_color=2
529
+ elif [[ $score -ge 60 ]]; then
530
+ bar_color=3
531
+ else
532
+ bar_color=1
533
+ fi
534
+ printf " Health Score: [%s%s] %s%%\n\n" \
535
+ "$(gum style --foreground "$bar_color" "$filled_bar")" \
536
+ "$empty_bar" \
537
+ "$score"
332
538
  else
333
- printf '%s' "${RED}"
539
+ printf " Health Score: ["
540
+ if [[ $score -ge 80 ]]; then
541
+ printf '%s' "${GREEN}"
542
+ elif [[ $score -ge 60 ]]; then
543
+ printf '%s' "${YELLOW}"
544
+ else
545
+ printf '%s' "${RED}"
546
+ fi
547
+ printf '%s' "$filled_bar"
548
+ printf '%s' "${NC}"
549
+ printf '%s' "$empty_bar"
550
+ printf "] %s%%\n\n" "${score}"
334
551
  fi
335
- printf "%${filled}s" | tr ' ' '█'
336
- printf '%s' "${NC}"
337
- printf "%${empty}s" | tr ' ' '░'
338
- printf "] %s%%\n\n" "${score}"
339
552
 
340
553
  if [[ $score -ge 90 ]]; then
341
- echo -e " ${GREEN}⚡ Excellent! Your dotfiles are in great shape.${NC}"
554
+ printf '%b\n' " ${GREEN}⚡ Excellent! Your dotfiles are in great shape.${NC}"
342
555
  elif [[ $score -ge 70 ]]; then
343
- echo -e " ${GREEN}✓ Good! Minor improvements possible.${NC}"
556
+ printf '%b\n' " ${GREEN}✓ Good! Minor improvements possible.${NC}"
344
557
  elif [[ $score -ge 50 ]]; then
345
- echo -e " ${YELLOW}⚠ Fair. Consider addressing warnings.${NC}"
558
+ printf '%b\n' " ${YELLOW}⚠ Fair. Consider addressing warnings.${NC}"
346
559
  else
347
- echo -e " ${RED}✗ Needs attention. Multiple issues found.${NC}"
560
+ printf '%b\n' " ${RED}✗ Needs attention. Multiple issues found.${NC}"
348
561
  fi
349
562
 
350
563
  echo ""
564
+ if [[ $WARNINGS -gt 0 || $FAILURES -gt 0 ]]; then
565
+ printf '%b\n' " ${CYAN}Tip:${NC} Run 'dot health --fix' to auto-repair common issues."
566
+ echo ""
567
+ fi
568
+
569
+ dot_log info "health_complete" "score=$score" "total=$TOTAL_CHECKS"
570
+ dot_metric "health_score" "$score" "percent"
351
571
  }
352
572
 
353
573
  # Main
574
+ export DOT_COMMAND="health"
354
575
  print_header
355
576
  run_checks
577
+ if $APPLY_FIX; then
578
+ if ! $JSON_OUTPUT; then
579
+ header "Auto-Remediation"
580
+ echo ""
581
+ fi
582
+ heal_script="$SCRIPT_DIR/../ops/heal.sh"
583
+ if [[ -f "$heal_script" ]]; then
584
+ if $FORCE_FIX; then
585
+ bash "$heal_script" --force || true
586
+ else
587
+ bash "$heal_script" || true
588
+ fi
589
+ else
590
+ if ! $JSON_OUTPUT; then
591
+ printf '%b\n' "${YELLOW}⚠${NC} heal.sh not found, skipping auto-fix."
592
+ fi
593
+ fi
594
+ reset_stats
595
+ run_checks
596
+ fi
356
597
  print_summary