@sebastienrousseau/dotfiles 0.2.520 → 0.2.522

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 (323) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/LICENSE-APACHE +190 -0
  3. package/LICENSE-MIT +21 -0
  4. package/README.md +43 -37
  5. package/install.sh +76 -10
  6. package/package.json +7 -7
  7. package/tools/README.md +49 -0
  8. package/tools/ci/install-chezmoi-verified.sh +68 -0
  9. package/docs/.vitepress/reports/localization-readability-audit.md +0 -73
  10. package/docs/AI.md +0 -179
  11. package/docs/ARCHITECTURE.md +0 -117
  12. package/docs/CNAME +0 -1
  13. package/docs/CONFIG_STRATEGY.md +0 -124
  14. package/docs/COPYRIGHT +0 -7
  15. package/docs/ECOSYSTEM.md +0 -220
  16. package/docs/GOLD-STANDARD-AUDIT.md +0 -352
  17. package/docs/GOVERNANCE.md +0 -98
  18. package/docs/MAINTAINERS.md +0 -41
  19. package/docs/MINIMUM-TOOLCHAIN.md +0 -100
  20. package/docs/NAMING_CONVENTIONS.md +0 -102
  21. package/docs/OPENCODE.md +0 -127
  22. package/docs/README.md +0 -84
  23. package/docs/STRUCTURE.md +0 -102
  24. package/docs/adr/ADR-001-ci-cd-pipeline.md +0 -118
  25. package/docs/adr/ADR-002-shell-performance.md +0 -130
  26. package/docs/adr/ADR-003-security-first.md +0 -158
  27. package/docs/adr/ADR-004-cli-architecture.md +0 -171
  28. package/docs/adr/ADR-005-chezmoi-choice.md +0 -99
  29. package/docs/adr/ADR-006-shell-selection.md +0 -124
  30. package/docs/adr/ADR-007-multi-shell-parity.md +0 -62
  31. package/docs/adr/ADR-008-alias-system-architecture.md +0 -95
  32. package/docs/adr/ADR-009-wallpaper-driven-theming.md +0 -131
  33. package/docs/adr/ADR-010-starship-transient-prompt.md +0 -144
  34. package/docs/adr/ADR-011-nushell-tier3-keep.md +0 -144
  35. package/docs/adr/ADR-012-ai-fleet-local-proxy.md +0 -79
  36. package/docs/adr/README.md +0 -40
  37. package/docs/architecture/AI_COST_OPTIMIZATION.md +0 -144
  38. package/docs/architecture/ARCHITECTURE.md +0 -20
  39. package/docs/architecture/INTEROP.md +0 -44
  40. package/docs/architecture/REPO_LAYOUT.md +0 -241
  41. package/docs/architecture/WALKTHROUGH.md +0 -86
  42. package/docs/architecture/fleet-deployment.md +0 -77
  43. package/docs/archive/EUXIS_2026_REVIEW.md +0 -127
  44. package/docs/archive/LEGACY_ROADMAP.md +0 -6
  45. package/docs/archive/MILESTONE_v0.2.493.md +0 -47
  46. package/docs/archive/PLAN.md +0 -199
  47. package/docs/archive/REPO_AUDIT.md +0 -31
  48. package/docs/articles/.pages +0 -6
  49. package/docs/articles/2026-07-05-custom-mkdocs-material-dark-theme.md +0 -216
  50. package/docs/articles/2026-07-05-fish-startup-abbr.md +0 -153
  51. package/docs/articles/2026-07-05-master-to-main-rename-runbook.md +0 -128
  52. package/docs/articles/index.md +0 -36
  53. package/docs/guides/INSTALL.md +0 -144
  54. package/docs/guides/MACOS_ICLOUD_SYMLINKS.md +0 -121
  55. package/docs/guides/NEOVIM_IDE_GUIDE.md +0 -61
  56. package/docs/guides/THEMING.md +0 -230
  57. package/docs/guides/TROUBLESHOOTING.md +0 -176
  58. package/docs/guides/WSL2_NIX_TROUBLESHOOTING.md +0 -792
  59. package/docs/index.md +0 -132
  60. package/docs/interop/A2A.md +0 -39
  61. package/docs/interop/POWERSHELL.md +0 -102
  62. package/docs/manual/00-introduction.md +0 -89
  63. package/docs/manual/01-concepts/01-architecture.md +0 -138
  64. package/docs/manual/01-concepts/02-trust-model.md +0 -183
  65. package/docs/manual/01-concepts/03-theme-engine.md +0 -186
  66. package/docs/manual/01-concepts/04-fleet.md +0 -148
  67. package/docs/manual/01-concepts/05-self-healing.md +0 -204
  68. package/docs/manual/02-tutorials/01-first-install.md +0 -197
  69. package/docs/manual/02-tutorials/02-add-wallpaper.md +0 -216
  70. package/docs/manual/02-tutorials/03-create-profile.md +0 -244
  71. package/docs/manual/02-tutorials/04-encrypt-secret.md +0 -281
  72. package/docs/manual/02-tutorials/05-deploy-fleet.md +0 -283
  73. package/docs/manual/03-reference/01-dot-cli.md +0 -475
  74. package/docs/manual/03-reference/02-config-files.md +0 -265
  75. package/docs/manual/03-reference/03-environment.md +0 -124
  76. package/docs/manual/03-reference/04-templates.md +0 -190
  77. package/docs/manual/03-reference/05-feature-flags.md +0 -187
  78. package/docs/manual/04-cookbook/01-recipes.md +0 -285
  79. package/docs/manual/04-cookbook/02-troubleshooting.md +0 -351
  80. package/docs/manual/04-cookbook/03-faq.md +0 -175
  81. package/docs/manual/05-appendices/A-platform-matrix.md +0 -101
  82. package/docs/manual/05-appendices/B-security-checklist.md +0 -85
  83. package/docs/manual/05-appendices/C-glossary.md +0 -40
  84. package/docs/manual/05-appendices/D-bibliography.md +0 -58
  85. package/docs/manual/05-appendices/E-license.md +0 -38
  86. package/docs/manual/_toc.yml +0 -58
  87. package/docs/manual/command-index.md +0 -175
  88. package/docs/manual/concept-index.md +0 -170
  89. package/docs/manual/index.md +0 -66
  90. package/docs/migration/README.md +0 -81
  91. package/docs/migration/from-bare-git-repo.md +0 -156
  92. package/docs/migration/from-gnu-stow.md +0 -165
  93. package/docs/migration/from-plain-chezmoi.md +0 -148
  94. package/docs/migration/from-yadm.md +0 -187
  95. package/docs/operations/ARCHITECTURE_ROADMAP.md +0 -7
  96. package/docs/operations/ATTESTATION.md +0 -44
  97. package/docs/operations/CI_CADENCE.md +0 -107
  98. package/docs/operations/CI_COMPOSITES.md +0 -156
  99. package/docs/operations/COMPLETIONS.md +0 -123
  100. package/docs/operations/COVERAGE.md +0 -204
  101. package/docs/operations/DRIFT.md +0 -107
  102. package/docs/operations/HARD_AUDIT_2026.md +0 -631
  103. package/docs/operations/MAINTENANCE.md +0 -63
  104. package/docs/operations/MANIFEST.md +0 -127
  105. package/docs/operations/MIGRATION.md +0 -109
  106. package/docs/operations/OPERATIONS.md +0 -188
  107. package/docs/operations/PERFORMANCE.md +0 -133
  108. package/docs/operations/PERFORMANCE_BUDGETS.md +0 -196
  109. package/docs/operations/REGISTRY.md +0 -90
  110. package/docs/operations/RELEASE_PIPELINE.md +0 -128
  111. package/docs/operations/RELIABILITY.md +0 -122
  112. package/docs/operations/RFC_v0_2_503_reorganization.md +0 -280
  113. package/docs/operations/ROADMAP.md +0 -10
  114. package/docs/operations/ROADMAP_2026.md +0 -7
  115. package/docs/operations/ROADMAP_V0_2_503.md +0 -10
  116. package/docs/operations/TESTING.md +0 -216
  117. package/docs/operations/TRACEABILITY.md +0 -44
  118. package/docs/operations/TRUSTED_AGENT_WORKSTATION.md +0 -65
  119. package/docs/operations/VERSION_SYNC.md +0 -393
  120. package/docs/packaging.md +0 -222
  121. package/docs/reference/ALIASES.md +0 -131
  122. package/docs/reference/ALIASES_CHEATSHEET.md +0 -32
  123. package/docs/reference/ALIASES_DEPRECATIONS.md +0 -13
  124. package/docs/reference/FEATURE-MATRIX.md +0 -646
  125. package/docs/reference/FEATURES.md +0 -66
  126. package/docs/reference/FONTS.md +0 -112
  127. package/docs/reference/POWERSHELL_PARITY.md +0 -82
  128. package/docs/reference/PROFILES.md +0 -69
  129. package/docs/reference/SCREENSHOTS.md +0 -121
  130. package/docs/reference/SCRIPTS.md +0 -71
  131. package/docs/reference/SUPPORT_MATRIX.md +0 -80
  132. package/docs/reference/THEMES.md +0 -117
  133. package/docs/reference/TOOLS.md +0 -110
  134. package/docs/reference/UTILS.md +0 -243
  135. package/docs/registry.json +0 -6
  136. package/docs/schema/dot-env-v1.json +0 -110
  137. package/docs/schema/dot-registry-v1.json +0 -33
  138. package/docs/security/AI_ACT_COMPLIANCE.md +0 -94
  139. package/docs/security/AUDIT_BYPASS.md +0 -103
  140. package/docs/security/AUTOMATION_SECRETS.md +0 -26
  141. package/docs/security/CI_EGRESS_ALLOWLIST.md +0 -127
  142. package/docs/security/CI_PINNING.md +0 -129
  143. package/docs/security/COMMIT_SIGNING.md +0 -138
  144. package/docs/security/COMPLIANCE.md +0 -458
  145. package/docs/security/DEPS_DEV_EXCEPTIONS.md +0 -86
  146. package/docs/security/DISCLOSURE.md +0 -130
  147. package/docs/security/ENCRYPTION.md +0 -57
  148. package/docs/security/FMEA.md +0 -159
  149. package/docs/security/FUZZING.md +0 -209
  150. package/docs/security/HISTORY_FILTERING.md +0 -132
  151. package/docs/security/INCIDENT_RESPONSE.md +0 -579
  152. package/docs/security/INSTALL_VERIFICATION.md +0 -122
  153. package/docs/security/KEYS.md +0 -49
  154. package/docs/security/KEY_ROTATION.md +0 -303
  155. package/docs/security/MCP_POLICY.md +0 -78
  156. package/docs/security/POLICY_RELEASES.md +0 -37
  157. package/docs/security/README.md +0 -28
  158. package/docs/security/SCORECARD.md +0 -195
  159. package/docs/security/SECRETS.md +0 -158
  160. package/docs/security/SECURITY.md +0 -45
  161. package/docs/security/SECURITY_CHECKLIST.md +0 -55
  162. package/docs/security/SHELL_EXEMPTIONS.md +0 -145
  163. package/docs/security/SOUP_REGISTER.md +0 -36
  164. package/docs/security/THREAT_MODEL.md +0 -130
  165. package/docs/security/VERIFICATION_VALIDATION.md +0 -228
  166. package/docs/security/VERIFY_RELEASE.md +0 -201
  167. package/docs/security/security-pubkey.asc +0 -15
  168. package/docs/stylesheets/extra.css +0 -444
  169. package/docs/themes/README.md +0 -10
  170. package/docs/themes/VISUAL_INTEGRITY_REPORT.md +0 -30
  171. package/docs/themes/hero-shot.svg +0 -78
  172. package/scripts/README.md +0 -123
  173. package/scripts/ci/check-copyright-headers.sh +0 -8
  174. package/scripts/ci/check-shell-preamble.sh +0 -8
  175. package/scripts/ci/guard-gitleaks-checkout.sh +0 -8
  176. package/scripts/demo/record.sh +0 -43
  177. package/scripts/diagnostics/a2a-conformance.sh +0 -163
  178. package/scripts/diagnostics/alias-governance.sh +0 -165
  179. package/scripts/diagnostics/aliases-cheatsheet.sh +0 -74
  180. package/scripts/diagnostics/aliases-manifest.sh +0 -77
  181. package/scripts/diagnostics/attest-verify.sh +0 -147
  182. package/scripts/diagnostics/benchmark.sh +0 -408
  183. package/scripts/diagnostics/conflicts.sh +0 -73
  184. package/scripts/diagnostics/doctor-unified.sh +0 -43
  185. package/scripts/diagnostics/doctor.sh +0 -797
  186. package/scripts/diagnostics/drift-dashboard.sh +0 -203
  187. package/scripts/diagnostics/health.sh +0 -656
  188. package/scripts/diagnostics/history-analysis.sh +0 -86
  189. package/scripts/diagnostics/mcp-doctor.sh +0 -582
  190. package/scripts/diagnostics/perf.sh +0 -453
  191. package/scripts/diagnostics/scorecard.sh +0 -120
  192. package/scripts/diagnostics/secret-governance.sh +0 -65
  193. package/scripts/diagnostics/security-score.sh +0 -467
  194. package/scripts/diagnostics/smoke-test.sh +0 -88
  195. package/scripts/diagnostics/snapshot.sh +0 -90
  196. package/scripts/diagnostics/verify.sh +0 -108
  197. package/scripts/diagnostics/verify_state.sh +0 -73
  198. package/scripts/diagnostics/version-locks.sh +0 -94
  199. package/scripts/diagnostics/workstation-attestation.sh +0 -212
  200. package/scripts/dot/commands/agent.sh +0 -535
  201. package/scripts/dot/commands/agents.sh +0 -352
  202. package/scripts/dot/commands/ai.sh +0 -600
  203. package/scripts/dot/commands/aliases.sh +0 -277
  204. package/scripts/dot/commands/appearance.sh +0 -110
  205. package/scripts/dot/commands/completion.sh +0 -171
  206. package/scripts/dot/commands/core.sh +0 -217
  207. package/scripts/dot/commands/diagnostics.sh +0 -265
  208. package/scripts/dot/commands/env-emit.sh +0 -203
  209. package/scripts/dot/commands/fleet.sh +0 -711
  210. package/scripts/dot/commands/init.sh +0 -185
  211. package/scripts/dot/commands/lint.sh +0 -208
  212. package/scripts/dot/commands/manual.sh +0 -169
  213. package/scripts/dot/commands/meta.sh +0 -438
  214. package/scripts/dot/commands/patterns.sh +0 -55
  215. package/scripts/dot/commands/registry.sh +0 -455
  216. package/scripts/dot/commands/restore.sh +0 -232
  217. package/scripts/dot/commands/secrets.sh +0 -296
  218. package/scripts/dot/commands/security.sh +0 -102
  219. package/scripts/dot/commands/tools.sh +0 -570
  220. package/scripts/dot/data/alias-deprecations.tsv +0 -2
  221. package/scripts/dot/powershell/Dot.psm1 +0 -319
  222. package/scripts/fonts/install-nerd-fonts.sh +0 -75
  223. package/scripts/fonts/patch-fonts.sh +0 -36
  224. package/scripts/git-hooks/install.sh +0 -12
  225. package/scripts/git-hooks/pre-commit +0 -12
  226. package/scripts/git-hooks/pre-commit-audit.sh +0 -146
  227. package/scripts/git-hooks/pre-push +0 -105
  228. package/scripts/git-hooks/prepare-commit-msg +0 -29
  229. package/scripts/lib/secrets_provider.sh +0 -200
  230. package/scripts/nvim/headless-upgrade.lua +0 -81
  231. package/scripts/ops/ai-setup.sh +0 -71
  232. package/scripts/ops/bundle.sh +0 -104
  233. package/scripts/ops/chaos.sh +0 -50
  234. package/scripts/ops/chezmoi-apply.sh +0 -333
  235. package/scripts/ops/chezmoi-diff.sh +0 -16
  236. package/scripts/ops/chezmoi-remove.sh +0 -46
  237. package/scripts/ops/chezmoi-update.sh +0 -67
  238. package/scripts/ops/heal-chezmoi.sh +0 -87
  239. package/scripts/ops/heal-system.sh +0 -129
  240. package/scripts/ops/heal-tools.sh +0 -297
  241. package/scripts/ops/heal.sh +0 -223
  242. package/scripts/ops/post-apply-repair.sh +0 -107
  243. package/scripts/ops/prewarm.sh +0 -128
  244. package/scripts/ops/release.sh +0 -262
  245. package/scripts/ops/rollback.sh +0 -613
  246. package/scripts/ops/setup.sh +0 -138
  247. package/scripts/ops/teleport.sh +0 -34
  248. package/scripts/qa/check-feature-matrix.sh +0 -296
  249. package/scripts/qa/check-version-consistency.sh +0 -12
  250. package/scripts/qa/coverage-baseline.sh +0 -61
  251. package/scripts/qa/docs-coverage.sh +0 -118
  252. package/scripts/qa/examples-coverage.sh +0 -94
  253. package/scripts/qa/powershell-contract.ps1 +0 -95
  254. package/scripts/qa/reliability-audit.sh +0 -139
  255. package/scripts/qa/scorecard-snapshot.sh +0 -128
  256. package/scripts/qa/traceability-coverage.sh +0 -124
  257. package/scripts/qa/validate-examples.sh +0 -90
  258. package/scripts/qa/wsl-contract.sh +0 -12
  259. package/scripts/secrets/age-init.sh +0 -82
  260. package/scripts/secrets/create-secrets-file.sh +0 -46
  261. package/scripts/secrets/encrypt-ssh-key.sh +0 -44
  262. package/scripts/security/backup.sh +0 -58
  263. package/scripts/security/check-disclosure-key-expiry.sh +0 -111
  264. package/scripts/security/dns-doh.sh +0 -52
  265. package/scripts/security/encryption-check.sh +0 -55
  266. package/scripts/security/enforce-policies.sh +0 -552
  267. package/scripts/security/firewall.sh +0 -91
  268. package/scripts/security/lock-configs.sh +0 -67
  269. package/scripts/security/lock-screen.sh +0 -56
  270. package/scripts/security/manage-secrets.sh +0 -429
  271. package/scripts/security/ssh-cert.sh +0 -204
  272. package/scripts/security/telemetry-kill.sh +0 -51
  273. package/scripts/security/usb-safety.sh +0 -52
  274. package/scripts/theme/apply-gnome-theme.sh +0 -333
  275. package/scripts/theme/extract-heic-frames.sh +0 -115
  276. package/scripts/theme/extract-theme.py +0 -1020
  277. package/scripts/theme/install-boot-logo.sh +0 -63
  278. package/scripts/theme/install-catppuccin-themes.sh +0 -371
  279. package/scripts/theme/install-cursors.sh +0 -26
  280. package/scripts/theme/install-file-icons.sh +0 -27
  281. package/scripts/theme/install-grub-theme.sh +0 -62
  282. package/scripts/theme/install-lock-icon.sh +0 -31
  283. package/scripts/theme/merge-wallpaper.sh +0 -146
  284. package/scripts/theme/rebuild-themes.sh +0 -603
  285. package/scripts/theme/switch.sh +0 -476
  286. package/scripts/theme/wallpaper-rotate.sh +0 -137
  287. package/scripts/theme/wallpaper-sync.sh +0 -690
  288. package/scripts/tools/cmatrix.sh +0 -22
  289. package/scripts/tools/detect-collisions.py +0 -103
  290. package/scripts/tools/emoji-picker.sh +0 -49
  291. package/scripts/tools/figlet-banner.sh +0 -19
  292. package/scripts/tools/log-rotate.sh +0 -31
  293. package/scripts/tools/lolcat-wrap.sh +0 -20
  294. package/scripts/tools/pipes.sh +0 -49
  295. package/scripts/tuning/linux.sh +0 -186
  296. package/scripts/tuning/macos.sh +0 -56
  297. package/scripts/uninstall.sh +0 -86
  298. package/scripts/verify-release-versions +0 -156
  299. package/scripts/version-sync.sh +0 -714
  300. package/templates/chezmoi-data/geekom-a9.toml.example +0 -21
  301. package/templates/chezmoi-data/mac-m1.toml.example +0 -16
  302. package/templates/chezmoi-data/mac-t2-linux.toml.example +0 -21
  303. package/templates/chezmoi-data/surface-pro-7p.toml.example +0 -21
  304. package/templates/projects/go/.github/workflows/ci.yml +0 -31
  305. package/templates/projects/go/README.md +0 -7
  306. package/templates/projects/go/cmd/__PROJECT_NAME__/main.go +0 -8
  307. package/templates/projects/go/go.mod +0 -3
  308. package/templates/projects/go/go.sum +0 -0
  309. package/templates/projects/molecule/README.md +0 -7
  310. package/templates/projects/molecule/converge.yml +0 -7
  311. package/templates/projects/molecule/molecule.yml +0 -16
  312. package/templates/projects/node/.github/workflows/ci.yml +0 -30
  313. package/templates/projects/node/README.md +0 -7
  314. package/templates/projects/node/package-lock.json +0 -12
  315. package/templates/projects/node/package.json +0 -10
  316. package/templates/projects/node/src/index.js +0 -3
  317. package/templates/projects/packer/README.md +0 -15
  318. package/templates/projects/packer/main.pkr.hcl +0 -15
  319. package/templates/projects/python/.github/workflows/ci.yml +0 -34
  320. package/templates/projects/python/README.md +0 -7
  321. package/templates/projects/python/pyproject.toml +0 -25
  322. package/templates/projects/python/src/__PROJECT_NAME__/__init__.py +0 -2
  323. package/templates/projects/python/tests/test_basic.py +0 -3
@@ -1,333 +0,0 @@
1
- #!/usr/bin/env bash
2
- # SPDX-License-Identifier: Apache-2.0 OR MIT
3
- # Copyright (c) 2015-2026 Sebastien Rousseau
4
- set -euo pipefail
5
-
6
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7
- # shellcheck source=../../lib/dot/ui.sh
8
- # shellcheck disable=SC1091
9
- source "$SCRIPT_DIR/../../lib/dot/ui.sh"
10
- # shellcheck source=../../lib/dot/log.sh
11
- # shellcheck disable=SC1091
12
- source "$SCRIPT_DIR/../../lib/dot/log.sh"
13
- # shellcheck source=../../lib/dot/ai-install.sh
14
- # shellcheck disable=SC1091
15
- source "$SCRIPT_DIR/../../lib/dot/ai-install.sh"
16
- export DOT_COMMAND="apply"
17
-
18
- # Temp file cleanup. `set +u` guards the array expansion: on bash 3.2
19
- # (macOS) expanding an empty array under `set -u` is an "unbound
20
- # variable" error, which would fire on every clean `dot sync`.
21
- _TMPFILES=()
22
- _LOCK_DIR=""
23
- cleanup() {
24
- set +u
25
- rm -f "${_TMPFILES[@]}" 2>/dev/null
26
- [[ -n "$_LOCK_DIR" ]] && rmdir "$_LOCK_DIR" 2>/dev/null
27
- set -u
28
- }
29
- trap cleanup EXIT
30
-
31
- # Help flag
32
- case "${1:-}" in
33
- -h | --help)
34
- cat <<HELP
35
- chezmoi-apply.sh - Apply dotfiles with enhanced diagnostics
36
-
37
- Usage:
38
- dot apply [OPTIONS] [-- CHEZMOI_ARGS]
39
-
40
- Environment Variables:
41
- DOTFILES_CHEZMOI_APPLY_FLAGS Extra flags for chezmoi apply
42
- DOTFILES_CHEZMOI_VERBOSE=1 Enable verbose output
43
- DOTFILES_CHEZMOI_KEEP_GOING=1 Continue on errors
44
- DOTFILES_NONINTERACTIVE=1 Skip interactive menus (AI provider installer)
45
- DOTFILES_INTERACTIVE_APPLY=1 Re-enable chezmoi overwrite prompts
46
- (apply is unattended/--force by default)
47
- DOTFILES_ALIAS_STRICT_MODE=1 Run alias governance checks
48
- DOTFILES_SNAPSHOT_ON_APPLY=1 Create baseline snapshot (default)
49
- DOTFILES_POST_APPLY_REPAIR=1 Run post-apply repairs (default)
50
- DOTFILES_CHEZMOI_STATUS=1 Show status after apply (default)
51
- HELP
52
- exit 0
53
- ;;
54
- esac
55
-
56
- args=("$@")
57
- if [[ -n "${DOTFILES_CHEZMOI_APPLY_FLAGS:-}" ]]; then
58
- # Safely parse space-separated flags into array
59
- read -ra flag_array <<<"$DOTFILES_CHEZMOI_APPLY_FLAGS"
60
- args+=("${flag_array[@]}")
61
- fi
62
-
63
- if [[ "${DOTFILES_CHEZMOI_VERBOSE:-0}" = "1" ]]; then
64
- args+=("--verbose")
65
- fi
66
-
67
- if [[ "${DOTFILES_CHEZMOI_KEEP_GOING:-0}" = "1" ]]; then
68
- args+=("--keep-going")
69
- fi
70
-
71
- has_flag() {
72
- local needle="$1"
73
- local arg
74
- # Guard the expansion: on bash 3.2 (macOS) iterating an empty array
75
- # under `set -u` is an unbound-variable error.
76
- [[ ${#args[@]} -eq 0 ]] && return 1
77
- for arg in "${args[@]}"; do
78
- [[ "$arg" == "$needle" ]] && return 0
79
- done
80
- return 1
81
- }
82
-
83
- # Apply unattended by default, like an OS package manager. chezmoi is
84
- # always run below under `gum spin` or with its output captured, so it
85
- # never has a controlling TTY; its "<file> has changed since chezmoi last
86
- # wrote it" confirmation prompt therefore cannot be answered and aborts
87
- # the run with "could not open a new TTY". Passing --force applies the
88
- # canonical source without prompting, so local drift to *managed* files
89
- # yields to the source — exactly how `apt`/system updates behave. Keep
90
- # machine-specific tweaks in the unmanaged ~/.zshrc.local or
91
- # ~/.config/zsh/rc.d.local/*.zsh, which chezmoi never overwrites.
92
- # Opt back into chezmoi's prompts with DOTFILES_INTERACTIVE_APPLY=1.
93
- if [[ "${DOTFILES_INTERACTIVE_APPLY:-0}" != "1" ]] && ! has_flag "--force"; then
94
- args+=("--force")
95
- fi
96
-
97
- # Whether interactive menus (the optional AI-provider installer below) may
98
- # prompt. Suppressed without a TTY, under CI, or when non-interactive is
99
- # requested — so unattended runs never hang waiting on input.
100
- INTERACTIVE=1
101
- if [[ "${DOTFILES_NONINTERACTIVE:-0}" == "1" ]] || [[ -n "${CI:-}" ]] || [[ ! -t 0 ]] || [[ ! -t 1 ]]; then
102
- INTERACTIVE=0
103
- fi
104
-
105
- ui_init
106
-
107
- # Prevent concurrent execution. flock(1) is Linux-only — it does not exist
108
- # on macOS, where `! flock` previously took the "already running" branch and
109
- # made `dot apply` a silent no-op. Use flock where present, otherwise fall
110
- # back to an atomic mkdir lock (portable to macOS/BSD).
111
- _lock_base="${XDG_RUNTIME_DIR:-${TMPDIR:-/tmp}}/dotfiles-chezmoi-apply"
112
- if command -v flock >/dev/null 2>&1; then
113
- exec 9>"${_lock_base}.lock"
114
- if ! flock -n 9; then
115
- ui_warn "Already running" "Another instance is active"
116
- exit 0
117
- fi
118
- elif ! mkdir "${_lock_base}.lock.d" 2>/dev/null; then
119
- ui_warn "Already running" "Another instance is active"
120
- exit 0
121
- else
122
- _LOCK_DIR="${_lock_base}.lock.d" # removed by cleanup() on exit
123
- fi
124
-
125
- run_step() {
126
- local title="$1"
127
- shift
128
- local out
129
- out="$(umask 077 && mktemp)"
130
- _TMPFILES+=("$out")
131
- if [[ "$UI_ENABLED" = "1" ]]; then
132
- if gum spin --spinner dot --title "$title" -- "$@" >"$out" 2>&1; then
133
- ui_ok "$title"
134
- if [[ "${DOTFILES_CHEZMOI_VERBOSE:-0}" = "1" ]] && [[ -s "$out" ]]; then
135
- cat "$out"
136
- fi
137
- else
138
- ui_err "$title"
139
- cat "$out"
140
- rm -f "$out"
141
- exit 1
142
- fi
143
- else
144
- echo "$title..."
145
- if "$@" >"$out" 2>&1; then
146
- if [[ "${DOTFILES_CHEZMOI_VERBOSE:-0}" = "1" ]] && [[ -s "$out" ]]; then
147
- cat "$out"
148
- fi
149
- else
150
- cat "$out"
151
- rm -f "$out"
152
- exit 1
153
- fi
154
- fi
155
- rm -f "$out"
156
- }
157
-
158
- dot_log info "apply_start"
159
- _apply_start=$(date +%s)
160
- ui_header "Applying dotfiles"
161
- if [[ "${DOTFILES_ALIAS_STRICT_MODE:-0}" == "1" ]]; then
162
- governance_script="$SCRIPT_DIR/../diagnostics/alias-governance.sh"
163
- if [[ -f "$governance_script" ]]; then
164
- run_step "Alias governance (strict)" env DOTFILES_ALIAS_POLICY=strict bash "$governance_script"
165
- fi
166
- fi
167
- run_step "Chezmoi apply" chezmoi apply "${args[@]}"
168
-
169
- if [[ "${DOTFILES_SNAPSHOT_ON_APPLY:-1}" = "1" ]]; then
170
- snapshot_script="$SCRIPT_DIR/../diagnostics/snapshot.sh"
171
- snapshot_dir="${XDG_STATE_HOME:-$HOME/.local/state}/dotfiles/snapshots"
172
- snapshot_file="${snapshot_dir}/baseline.json"
173
- if [[ -f "$snapshot_script" && ! -f "$snapshot_file" ]]; then
174
- mkdir -p "$snapshot_dir"
175
- bash "$snapshot_script" --baseline >/dev/null 2>&1 || true
176
- fi
177
- fi
178
-
179
- check_cmd() {
180
- local cmd="$1"
181
- if command -v "$cmd" &>/dev/null; then
182
- return 0
183
- fi
184
- if command -v mise &>/dev/null; then
185
- if mise ls --installed 2>/dev/null | grep -qE "($cmd|aqua:.*$cmd)"; then
186
- return 0
187
- fi
188
- fi
189
- return 1
190
- }
191
-
192
- echo ""
193
- ui_header "AI provider CLI checks (optional)"
194
-
195
- # binary|mise_package|label (claude uses the native installer, not mise)
196
- _AI_PROVIDERS=(
197
- "claude|native|Claude Code"
198
- "codex|npm:@openai/codex|Codex CLI"
199
- "copilot|npm:@github/copilot|Copilot CLI"
200
- "goose|native|Goose"
201
- "agy|native|Antigravity CLI"
202
- "kimi|native|Kimi CLI"
203
- "sgpt|pipx:shell-gpt|Shell-GPT"
204
- "ollama|aqua:ollama/ollama|Ollama"
205
- "opencode|npm:opencode-ai|OpenCode"
206
- "aider|pipx:aider-chat|Aider"
207
- "kiro-cli|kiro-cli|Kiro CLI"
208
- "autohand|npm:autohand-cli|Autohand Code"
209
- "vibe|pipx:mistral-vibe|Mistral Vibe"
210
- "qwen|npm:@qwen-code/qwen-code|Qwen Code"
211
- "zai|npm:@guizmo-ai/zai-cli|ZAI"
212
- )
213
-
214
- _ai_missing=()
215
- for _entry in "${_AI_PROVIDERS[@]}"; do
216
- IFS='|' read -r _bin _pkg _label <<<"$_entry"
217
- if check_cmd "$_bin"; then
218
- ui_ok "$_label"
219
- else
220
- ui_info "$_label" "not installed"
221
- _ai_missing+=("$_entry")
222
- fi
223
- done
224
-
225
- if [[ ${#_ai_missing[@]} -gt 0 ]] && [[ "$INTERACTIVE" == "1" ]]; then
226
- if command -v mise &>/dev/null; then
227
- echo ""
228
- _ai_install_action=""
229
- if command -v gum &>/dev/null; then
230
- _ai_install_action=$(printf '%s\n' "Install all" "Choose which to install" "Skip" |
231
- gum choose --header "Missing AI providers — install via mise?") || _ai_install_action=""
232
- else
233
- ui_info "Tip" "Install all missing AI providers with: mise install"
234
- ui_info "Tip" "Or individually: mise use -g <package>@latest"
235
- fi
236
-
237
- _ai_to_install=()
238
- case "$_ai_install_action" in
239
- "Install all")
240
- _ai_to_install=("${_ai_missing[@]}")
241
- ;;
242
- "Choose which to install")
243
- _ai_pick_choices=()
244
- for _entry in "${_ai_missing[@]}"; do
245
- IFS='|' read -r _bin _pkg _label <<<"$_entry"
246
- _ai_pick_choices+=("$_label")
247
- done
248
- _ai_picked=$(printf '%s\n' "${_ai_pick_choices[@]}" |
249
- gum choose --no-limit --header "Select providers to install (Space to toggle, Enter to confirm)") || _ai_picked=""
250
- if [[ -n "$_ai_picked" ]]; then
251
- while IFS= read -r _selected; do
252
- [[ -z "$_selected" ]] && continue
253
- for _entry in "${_ai_missing[@]}"; do
254
- IFS='|' read -r _bin _pkg _label <<<"$_entry"
255
- if [[ "$_label" == "$_selected" ]]; then
256
- _ai_to_install+=("$_entry")
257
- fi
258
- done
259
- done <<<"$_ai_picked"
260
- fi
261
- ;;
262
- esac
263
-
264
- if [[ ${#_ai_to_install[@]} -gt 0 ]]; then
265
- echo ""
266
- for _entry in "${_ai_to_install[@]}"; do
267
- IFS='|' read -r _bin _pkg _label <<<"$_entry"
268
- if [[ "$_bin" == "claude" ]]; then
269
- install_claude_native "$_label"
270
- continue
271
- fi
272
- if [[ "$_bin" == "goose" ]]; then
273
- install_goose_native "$_label"
274
- continue
275
- fi
276
- if [[ "$_bin" == "agy" ]]; then
277
- install_agy_native "$_label"
278
- continue
279
- fi
280
- if [[ "$_bin" == "kimi" ]]; then
281
- install_kimi_native "$_label"
282
- continue
283
- fi
284
- if command -v gum &>/dev/null; then
285
- if gum spin --spinner dot --title "Installing $_label ($_pkg)" -- \
286
- mise use -g "$_pkg@latest" 2>&1; then
287
- ui_ok "$_label" "installed"
288
- else
289
- ui_warn "$_label" "install failed (continuing)"
290
- fi
291
- else
292
- ui_info "Installing" "$_label via mise ($_pkg)"
293
- mise use -g "$_pkg@latest" 2>&1 || ui_warn "$_label" "install failed (continuing)"
294
- fi
295
- done
296
- fi
297
- else
298
- ui_warn "mise" "not found — install mise first to manage AI providers"
299
- fi
300
- fi
301
-
302
- if [[ "${DOTFILES_CHEZMOI_STATUS:-1}" = "1" ]]; then
303
- printf "\n"
304
- ui_header "Status"
305
- status_out="$(chezmoi status || true)"
306
- if [[ -z "$status_out" ]]; then
307
- ui_ok "Clean"
308
- else
309
- printf "%s\n" "$status_out"
310
- fi
311
- fi
312
-
313
- if [[ "${DOTFILES_POST_APPLY_REPAIR:-1}" = "1" ]]; then
314
- post_apply_script="$SCRIPT_DIR/post-apply-repair.sh"
315
- if [[ -f "$post_apply_script" ]]; then
316
- printf "\n"
317
- bash "$post_apply_script" || true
318
- fi
319
- fi
320
-
321
- if [[ "${DOTFILES_PREWARM_ON_APPLY:-1}" = "1" ]]; then
322
- prewarm_script="$SCRIPT_DIR/prewarm.sh"
323
- if [[ -f "$prewarm_script" ]]; then
324
- printf "\n"
325
- run_step "Pre-warming shell caches" bash "$prewarm_script"
326
- fi
327
- fi
328
-
329
- printf "\n"
330
- _apply_end=$(date +%s)
331
- dot_log info "apply_end" "duration_s=$((_apply_end - _apply_start))"
332
- dot_metric "chezmoi_apply_duration" "$((_apply_end - _apply_start))" "s"
333
- ui_info "Shell reload" "Run 'exec zsh' or restart your terminal to reload aliases/functions."
@@ -1,16 +0,0 @@
1
- #!/usr/bin/env bash
2
- # SPDX-License-Identifier: Apache-2.0 OR MIT
3
- # Copyright (c) 2015-2026 Sebastien Rousseau
4
- set -euo pipefail
5
-
6
- excludes=(scripts)
7
- if [[ -n "${DOTFILES_CHEZMOI_DIFF_EXCLUDES:-}" ]]; then
8
- IFS=',' read -r -a excludes <<<"${DOTFILES_CHEZMOI_DIFF_EXCLUDES}"
9
- fi
10
-
11
- args=()
12
- for ex in "${excludes[@]}"; do
13
- args+=("--exclude" "$ex")
14
- done
15
-
16
- chezmoi diff "${args[@]}" "$@"
@@ -1,46 +0,0 @@
1
- #!/usr/bin/env bash
2
- # SPDX-License-Identifier: Apache-2.0 OR MIT
3
- # Copyright (c) 2015-2026 Sebastien Rousseau
4
- set -euo pipefail
5
-
6
- if [[ $# -lt 1 ]]; then
7
- echo "Usage: dot remove <path> [--source] [--dry-run]" >&2
8
- exit 1
9
- fi
10
-
11
- remove_source=0
12
- args=()
13
- paths=()
14
-
15
- for arg in "$@"; do
16
- case "$arg" in
17
- --source)
18
- remove_source=1
19
- ;;
20
- --dry-run)
21
- args+=("--dry-run")
22
- ;;
23
- *)
24
- paths+=("$arg")
25
- ;;
26
- esac
27
- done
28
-
29
- if [[ ${#paths[@]} -eq 0 ]]; then
30
- echo "No path provided." >&2
31
- exit 1
32
- fi
33
-
34
- # shellcheck disable=SC1091
35
- if [[ $remove_source -eq 0 ]]; then
36
- args+=("--keep-source")
37
- fi
38
-
39
- printf "About to run: chezmoi remove %s %s\n" "${args[*]:-}" "${paths[*]}"
40
- read -r -p "Proceed? [y/N] " confirm
41
- if [[ "$confirm" != "y" && "$confirm" != "Y" ]]; then
42
- echo "Aborted."
43
- exit 1
44
- fi
45
-
46
- chezmoi remove ${args[@]+"${args[@]}"} "${paths[@]}"
@@ -1,67 +0,0 @@
1
- #!/usr/bin/env bash
2
- # SPDX-License-Identifier: Apache-2.0 OR MIT
3
- # Copyright (c) 2015-2026 Sebastien Rousseau
4
- set -euo pipefail
5
-
6
- args=()
7
- if [[ -n "${DOTFILES_CHEZMOI_UPDATE_FLAGS:-}" ]]; then
8
- # Safely parse space-separated flags into array
9
- read -ra flag_array <<<"$DOTFILES_CHEZMOI_UPDATE_FLAGS"
10
- args+=("${flag_array[@]}")
11
- fi
12
-
13
- if [[ "${DOTFILES_CHEZMOI_VERBOSE:-0}" = "1" ]]; then
14
- args+=("--verbose")
15
- fi
16
-
17
- # Apply unattended by default (see chezmoi-apply.sh). `chezmoi update` runs
18
- # `apply` internally, so without --force it blocks on the "<file> has
19
- # changed since chezmoi last wrote it" prompt — and `dot update` is often
20
- # run from cron/CI/--async with no TTY, where that prompt aborts the run.
21
- # --force makes updates land like an OS package-manager update; opt back
22
- # into prompting with DOTFILES_INTERACTIVE_APPLY=1.
23
- if [[ "${DOTFILES_INTERACTIVE_APPLY:-0}" != "1" ]]; then
24
- _has_force=0
25
- if [[ ${#args[@]} -gt 0 ]]; then
26
- for _a in "${args[@]}"; do [[ "$_a" == "--force" ]] && _has_force=1; done
27
- fi
28
- [[ "$_has_force" == "0" ]] && args+=("--force")
29
- fi
30
-
31
- ASYNC=false
32
- if [[ "${DOTFILES_ASYNC_UPDATE:-0}" = "1" ]]; then
33
- ASYNC=true
34
- fi
35
- if [[ "${1:-}" == "--async" ]]; then
36
- ASYNC=true
37
- shift
38
- fi
39
-
40
- STATE_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/dotfiles/update"
41
- mkdir -p "$STATE_DIR"
42
- LOG_FILE="$STATE_DIR/last.log"
43
- STATUS_FILE="$STATE_DIR/last.status"
44
- NOTICE_FILE="$STATE_DIR/notice"
45
-
46
- run_update() {
47
- echo "Updating dotfiles..."
48
- # `${args[@]+...}`: with DOTFILES_INTERACTIVE_APPLY=1 no flags are added,
49
- # and bash 3.2 (the system bash on macOS) treats an unguarded empty array
50
- # expansion under `set -u` as an unbound variable — `dot update` then died
51
- # instead of running chezmoi.
52
- chezmoi update ${args[@]+"${args[@]}"}
53
- }
54
-
55
- if $ASYNC; then
56
- echo "Update running in background..."
57
- {
58
- run_update
59
- echo $? >"$STATUS_FILE"
60
- } >"$LOG_FILE" 2>&1 &
61
- date -u +%Y-%m-%dT%H:%M:%SZ >"$NOTICE_FILE"
62
- disown || true
63
- exit 0
64
- fi
65
-
66
- run_update
67
- echo $? >"$STATUS_FILE"
@@ -1,87 +0,0 @@
1
- #!/usr/bin/env bash
2
- # SPDX-License-Identifier: Apache-2.0 OR MIT
3
- # Copyright (c) 2015-2026 Sebastien Rousseau
4
- # shellcheck disable=SC2034
5
- # =============================================================================
6
- # heal-chezmoi.sh — Chezmoi drift and backup repair functions for heal.sh
7
- # Sourced by heal.sh; inherits set -euo pipefail, ui.sh, and shared variables.
8
- # =============================================================================
9
-
10
- create_pre_heal_backup() {
11
- local rollback_script="$REPO_ROOT/scripts/ops/rollback.sh"
12
- if [[ -f "$rollback_script" ]]; then
13
- log_info "Creating backup before heal..."
14
- bash "$rollback_script" backup --force 2>/dev/null || true
15
- else
16
- # Minimal inline backup
17
- local timestamp
18
- timestamp=$(date +"%Y%m%d_%H%M%S")
19
- local backup_path="$BACKUP_DIR/backup_${timestamp}_pre_heal"
20
- mkdir -p "$backup_path"
21
- for f in "$HOME/.bashrc" "$HOME/.zshrc" "$HOME/.profile"; do
22
- if [[ -f "$f" ]]; then
23
- cp -a "$f" "$backup_path/" 2>/dev/null || true
24
- fi
25
- done
26
- log_info "Backup created at $backup_path"
27
- fi
28
- }
29
-
30
- heal_chezmoi_drift() {
31
- if ! command -v chezmoi >/dev/null 2>&1; then return 0; fi
32
-
33
- local status_output
34
- status_output=$(chezmoi status 2>/dev/null || echo "")
35
-
36
- if [[ -z "$status_output" ]]; then
37
- printf ' \033[38;5;42m✓\033[0m chezmoi state\n'
38
- return 0
39
- fi
40
-
41
- # Partition the drift: column 2 is what `chezmoi apply` would fix
42
- # (destination differs from source). Column 1 is source-only drift
43
- # (unstaged edits in the chezmoi source tree). Apply can't help with
44
- # the second case — that needs `git commit` in the source repo.
45
- local applicable
46
- local source_only
47
- applicable=$(printf '%s\n' "$status_output" | awk 'substr($0,2,1)!=" "' | wc -l | tr -d ' ')
48
- source_only=$(printf '%s\n' "$status_output" | awk 'substr($0,1,1)!=" " && substr($0,2,1)==" "' | wc -l | tr -d ' ')
49
-
50
- ISSUES_FOUND=$((ISSUES_FOUND + 1))
51
-
52
- if [[ "$DRY_RUN" == "1" ]]; then
53
- log_dry "run 'chezmoi apply --force' to re-sync ($applicable file(s))"
54
- return 0
55
- fi
56
-
57
- # Skip the apply if every file is source-only drift; nothing to fix.
58
- if [[ "$applicable" -eq 0 ]]; then
59
- printf ' \033[38;5;220m⚠\033[0m chezmoi state %s file(s) modified in source only — commit or revert in the source repo\n' "$source_only"
60
- return 0
61
- fi
62
-
63
- # Capture apply output so we can surface failure reasons.
64
- local apply_log
65
- apply_log=$(mktemp)
66
- if chezmoi apply --force >"$apply_log" 2>&1; then
67
- FIXES_APPLIED=$((FIXES_APPLIED + 1))
68
- CHEZMOI_APPLIED=1
69
- persist_log "HEAL: chezmoi apply --force"
70
-
71
- # Verify: did apply actually clean the drift?
72
- local remaining
73
- remaining=$(chezmoi status 2>/dev/null | awk 'substr($0,2,1)!=" "' | wc -l | tr -d ' ')
74
- if [[ "$remaining" -eq 0 ]]; then
75
- printf ' \033[38;5;42m✓\033[0m chezmoi re-apply %s file(s) synced\n' "$applicable"
76
- else
77
- # shellcheck disable=SC2016
78
- printf ' \033[38;5;220m⚠\033[0m chezmoi re-apply %s applied, %s still drifted — run `chezmoi diff` to inspect\n' \
79
- "$((applicable - remaining))" "$remaining"
80
- fi
81
- else
82
- printf ' \033[38;5;196m✗\033[0m chezmoi re-apply failed; see %s\n' "$apply_log"
83
- tail -5 "$apply_log" | sed 's/^/ /'
84
- return 1
85
- fi
86
- rm -f "$apply_log"
87
- }
@@ -1,129 +0,0 @@
1
- #!/usr/bin/env bash
2
- # SPDX-License-Identifier: Apache-2.0 OR MIT
3
- # Copyright (c) 2015-2026 Sebastien Rousseau
4
- # shellcheck disable=SC2034
5
- # =============================================================================
6
- # heal-system.sh — System-level repair functions for heal.sh
7
- # Sourced by heal.sh; inherits set -euo pipefail, ui.sh, and shared variables.
8
- # =============================================================================
9
-
10
- heal_broken_symlinks() {
11
- local broken=()
12
-
13
- while IFS= read -r -d '' link; do
14
- local filename
15
- filename=$(basename "$link")
16
-
17
- # Skip known false positives (e.g., Chrome lock files in backups)
18
- [[ "$link" == *"google-chrome-backup"* ]] && continue
19
- [[ "$filename" == "SingletonLock" || "$filename" == "SingletonCookie" || "$filename" == "SingletonSocket" ]] && continue
20
-
21
- if [[ ! -e "$link" ]]; then
22
- broken+=("$link")
23
- fi
24
- done < <(find "$HOME" -maxdepth 3 -type l -print0 2>/dev/null || true)
25
-
26
- # Special handling for common transient/app locks that dot doctor reported
27
- local lock_patterns=("SingletonLock" "SingletonCookie")
28
-
29
- if [[ ${#broken[@]} -eq 0 ]]; then
30
- printf ' \033[38;5;42m✓\033[0m symlinks\n'
31
- return 0
32
- fi
33
-
34
- ISSUES_FOUND=$((ISSUES_FOUND + ${#broken[@]}))
35
-
36
- for link in "${broken[@]}"; do
37
- local target
38
- target=$(readlink "$link" 2>/dev/null || echo "unknown")
39
- local filename
40
- filename=$(basename "$link")
41
-
42
- local is_lock=0
43
- for pat in "${lock_patterns[@]}"; do
44
- if [[ "$filename" == *"$pat"* ]]; then
45
- is_lock=1
46
- break
47
- fi
48
- done
49
-
50
- if [[ "$DRY_RUN" == "1" ]]; then
51
- log_dry "remove broken symlink: $link -> $target"
52
- else
53
- if [[ "$is_lock" == "0" ]] && [[ "$FORCE" != "1" ]] && [[ "${DOTFILES_NONINTERACTIVE:-0}" != "1" ]]; then
54
- read -rp "Remove broken symlink $link -> $target? [y/N] " response
55
- if [[ ! "$response" =~ ^[Yy]$ ]]; then
56
- continue
57
- fi
58
- fi
59
- if rm -f "$link" 2>/dev/null; then
60
- printf ' \033[38;5;42m✓\033[0m removed %s\n' "$link"
61
- FIXES_APPLIED=$((FIXES_APPLIED + 1))
62
- persist_log "HEAL: removed broken symlink $link"
63
- else
64
- printf ' \033[38;5;214m⚠\033[0m could not remove %s\n' "$link"
65
- fi
66
- fi
67
- done
68
- }
69
-
70
- heal_missing_critical_files() {
71
- local critical_files=("$HOME/.zshrc" "$HOME/.bashrc" "$HOME/.profile")
72
- local missing=()
73
-
74
- for file in "${critical_files[@]}"; do
75
- if [[ ! -f "$file" ]] && [[ ! -L "$file" ]]; then
76
- missing+=("$file")
77
- ISSUES_FOUND=$((ISSUES_FOUND + 1))
78
- fi
79
- done
80
-
81
- if [[ ${#missing[@]} -eq 0 ]]; then
82
- printf ' \033[38;5;42m✓\033[0m shell configs\n'
83
- return 0
84
- fi
85
-
86
- if ! command -v chezmoi >/dev/null 2>&1; then return 1; fi
87
-
88
- if [[ "$DRY_RUN" == "1" ]]; then
89
- log_dry "regenerate missing files via chezmoi"
90
- elif [[ "$CHEZMOI_APPLIED" != "1" ]]; then
91
- if _pkg_install "shell configs" 0 1 chezmoi apply --force; then
92
- CHEZMOI_APPLIED=1
93
- local restored=0
94
- for file in "${missing[@]}"; do
95
- if [[ -f "$file" ]] || [[ -L "$file" ]]; then
96
- restored=$((restored + 1))
97
- fi
98
- done
99
- FIXES_APPLIED=$((FIXES_APPLIED + restored))
100
- persist_log "HEAL: regenerated $restored critical file(s)"
101
- fi
102
- fi
103
- }
104
-
105
- heal_missing_xdg_dirs() {
106
- local xdg_dirs=("$HOME/.config/shell" "$HOME/.config/nvim" "$HOME/.config/git")
107
- local missing=()
108
-
109
- for dir in "${xdg_dirs[@]}"; do
110
- [[ -d "$dir" ]] || missing+=("$dir")
111
- done
112
-
113
- if [[ ${#missing[@]} -eq 0 ]]; then
114
- printf ' \033[38;5;42m✓\033[0m xdg directories\n'
115
- return 0
116
- fi
117
-
118
- ISSUES_FOUND=$((ISSUES_FOUND + ${#missing[@]}))
119
- for dir in "${missing[@]}"; do
120
- if [[ "$DRY_RUN" == "1" ]]; then
121
- log_dry "create directory: $dir"
122
- else
123
- mkdir -p "$dir"
124
- printf ' \033[38;5;42m✓\033[0m %s\n' "$(basename "$dir")"
125
- FIXES_APPLIED=$((FIXES_APPLIED + 1))
126
- persist_log "HEAL: created directory $dir"
127
- fi
128
- done
129
- }