@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,476 +0,0 @@
1
- #!/usr/bin/env bash
2
- # SPDX-License-Identifier: Apache-2.0 OR MIT
3
- # Copyright (c) 2015-2026 Sebastien Rousseau
4
- ## Theme Switcher — Switch between theme families and light/dark modes.
5
- ##
6
- ## Supports Tokyo Night, Catppuccin, Rose Pine, Kanagawa, and other
7
- ## popular theme families. Updates chezmoi data and applies changes.
8
- ##
9
- ## # Requirements
10
- ## - chezmoi: Dotfiles manager
11
- ## - sed: For updating theme configuration
12
- ##
13
- ## # Usage
14
- ## dot theme list # Show all available themes
15
- ## dot theme set NAME # Set theme to NAME
16
- ## dot theme toggle # Toggle light/dark within family
17
- ## dot theme family # Switch between theme families
18
- ## dot theme current # Show current theme info
19
- ##
20
- ## # Platform Notes
21
- ## - All platforms: Updates chezmoi configuration
22
-
23
- set -euo pipefail
24
-
25
- # Cleanup function for temp files
26
- cleanup() {
27
- if [[ -n "${tmp_file:-}" ]] && [[ -f "$tmp_file" ]]; then
28
- rm -f "$tmp_file"
29
- fi
30
- }
31
- trap cleanup EXIT
32
-
33
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
34
- # shellcheck source=../../lib/dot/ui.sh
35
- # shellcheck disable=SC1091
36
- source "$SCRIPT_DIR/../../lib/dot/ui.sh"
37
-
38
- ui_init
39
-
40
- resolve_source_dir() {
41
- if [ -n "${CHEZMOI_SOURCE_DIR:-}" ] && [ -d "$CHEZMOI_SOURCE_DIR" ]; then
42
- echo "$CHEZMOI_SOURCE_DIR"
43
- return
44
- fi
45
- if [ -d "$HOME/.dotfiles" ]; then
46
- echo "$HOME/.dotfiles"
47
- return
48
- fi
49
- if [ -d "$HOME/.local/share/chezmoi" ]; then
50
- echo "$HOME/.local/share/chezmoi"
51
- return
52
- fi
53
- echo ""
54
- }
55
-
56
- SRC_DIR="$(resolve_source_dir)"
57
- if [ -z "$SRC_DIR" ]; then
58
- ui_err "Dotfiles source" "not found"
59
- exit 1
60
- fi
61
-
62
- # Descend into the chezmoi source subdir when .chezmoiroot is present (post-reorg, chezmoi files under defaults/)
63
- CHEZMOI_SRC="$SRC_DIR"
64
- if [[ -f "$SRC_DIR/.chezmoiroot" ]]; then
65
- _sub="$(head -1 "$SRC_DIR/.chezmoiroot" | tr -d '[:space:]')"
66
- [[ -n "$_sub" && -d "$SRC_DIR/$_sub" ]] && CHEZMOI_SRC="$SRC_DIR/$_sub"
67
- fi
68
-
69
- DATA_FILE="$CHEZMOI_SRC/.chezmoidata.toml"
70
- THEMES_FILE="$CHEZMOI_SRC/.chezmoidata/themes.toml"
71
- WALLPAPER_DIR="${DOTFILES_WALLPAPER_DIR:-$HOME/Pictures/Wallpapers}"
72
- if [ ! -f "$DATA_FILE" ]; then
73
- ui_err "Missing" "$DATA_FILE"
74
- exit 1
75
- fi
76
-
77
- # =============================================================================
78
- # Theme Database
79
- # =============================================================================
80
-
81
- # Default preferences (must be present keys in themes.toml — the theme
82
- # regeneration removed the old macos-monterey-* names; bloom is the current
83
- # default family and always ships a dark+light pair).
84
- DEFAULT_DARK="bloom-dark"
85
- DEFAULT_LIGHT="bloom-light"
86
-
87
- # Machine-local chezmoi override (chezmoi.toml [data] theme) takes precedence
88
- # over .chezmoidata.toml when rendering, so it is the authoritative "current"
89
- # value. Kept in sync by dot-theme-sync's write_theme().
90
- CHEZMOI_CFG="${XDG_CONFIG_HOME:-$HOME/.config}/chezmoi/chezmoi.toml"
91
-
92
- # =============================================================================
93
- # Theme Functions
94
- # =============================================================================
95
-
96
- current_theme() {
97
- # Prefer the machine-local override (what chezmoi actually renders), so
98
- # `dot theme current` never disagrees with the deployed configs. Fall back
99
- # to the repo default in .chezmoidata.toml when no override is set.
100
- if [[ -f "$CHEZMOI_CFG" ]]; then
101
- local override
102
- override="$(awk -F'"' '/^theme =/ {print $2}' "$CHEZMOI_CFG" | head -n 1)"
103
- if [[ -n "$override" ]]; then
104
- echo "$override"
105
- return 0
106
- fi
107
- fi
108
- awk -F'"' '/^theme =/ {print $2}' "$DATA_FILE" | head -n 1
109
- }
110
-
111
- theme_mode() {
112
- local name="${1:-}"
113
- awk -v n="$name" '
114
- $0 == "[themes." n "]" { found=1; next }
115
- /^\[/ { found=0 }
116
- found && /^mode/ { sub(/.*= *"/, ""); sub(/".*/, ""); print; exit }
117
- ' "$THEMES_FILE"
118
- }
119
-
120
- theme_exists() {
121
- local name="${1:-}"
122
- grep -q "^\[themes\.${name}\]$" "$THEMES_FILE" 2>/dev/null
123
- }
124
-
125
- all_theme_names() {
126
- sed -n 's/^\[themes\.\([a-zA-Z0-9-]*\)\]$/\1/p' "$THEMES_FILE" | sort -u
127
- }
128
-
129
- # List wallpaper families that have BOTH dark and light variants in themes.toml.
130
- # Only these are presented to users — unpaired wallpapers are hidden.
131
- #
132
- # This was two associative arrays. Those are bash 4 only, and macOS still
133
- # ships 3.2 as /bin/bash, where `local -A` fails outright ("local: -A:
134
- # invalid option"). Both arrays then stayed empty, so this function printed
135
- # nothing and `dot theme list`, `dot theme family` and the interactive picker
136
- # silently offered no themes at all on a stock macOS shell.
137
- #
138
- # Two newline-separated lists plus `comm` behave identically on 3.2 and 4+.
139
- paired_families() {
140
- local darks="" lights="" name family
141
- while IFS= read -r name; do
142
- case "$name" in
143
- *-dark) darks="${darks}${name%-dark}"$'\n' ;;
144
- *-light) lights="${lights}${name%-light}"$'\n' ;;
145
- esac
146
- done < <(all_theme_names)
147
-
148
- # `fallback` is a synthetic safety theme (see themes.toml) that templates
149
- # degrade to when .theme is unset/invalid — never a user-selectable one.
150
- comm -12 \
151
- <(printf '%s' "$darks" | sort -u) \
152
- <(printf '%s' "$lights" | sort -u) |
153
- grep -vxF 'fallback' || true
154
- }
155
-
156
- # Determine source type (system/custom) for a wallpaper family.
157
- wallpaper_source() {
158
- local family="${1:-}"
159
- # Check for custom wallpapers: dynamic (family.heic) or split (family-dark/light.ext)
160
- for ext in heic jpg png webp; do
161
- if [[ -f "$WALLPAPER_DIR/${family}.${ext}" || -f "$WALLPAPER_DIR/${family}-dark.${ext}" || -f "$WALLPAPER_DIR/${family}-light.${ext}" || -f "$WALLPAPER_DIR/${family}-0.${ext}" ]]; then
162
- echo "Custom"
163
- return
164
- fi
165
- done
166
- echo "System"
167
- }
168
-
169
- get_theme_family() {
170
- local theme="${1:-}"
171
- # Read family from themes.toml if available
172
- if [[ -f "$THEMES_FILE" ]]; then
173
- local family
174
- family="$(awk -v n="$theme" '
175
- $0 == "[themes." n "]" { found=1; next }
176
- /^\[/ { found=0 }
177
- found && /^family/ { sub(/.*= *"/, ""); sub(/".*/, ""); print; exit }
178
- ' "$THEMES_FILE")"
179
- if [[ -n "$family" ]]; then
180
- echo "$family"
181
- return
182
- fi
183
- fi
184
- # Fallback: strip -dark/-light suffix
185
- local family="${theme%-dark}"
186
- [[ "$family" != "$theme" ]] || family="${theme%-light}"
187
- echo "$family"
188
- }
189
-
190
- is_dark_theme() {
191
- local theme="${1:-}"
192
- case "$theme" in
193
- *-dark)
194
- return 0
195
- ;;
196
- *)
197
- return 1
198
- ;;
199
- esac
200
- }
201
-
202
- set_theme() {
203
- local new_theme="${1:-}"
204
- if [ -z "$new_theme" ]; then
205
- # A picker needs someone to pick. Under DOTFILES_NONINTERACTIVE the
206
- # selector cannot run, and ui_pick reports "nothing selected" the same
207
- # way it reports a cancel — so answering with a silent success would
208
- # make a forgotten argument indistinguishable from a theme change.
209
- if [ "${DOTFILES_NONINTERACTIVE:-0}" = "1" ]; then
210
- ui_err "Missing theme name" "no interactive picker in a non-interactive session"
211
- ui_info "Usage" "dot theme set <name> (or 'dot theme list' to see them)"
212
- return 1
213
- fi
214
- pick_theme
215
- return
216
- fi
217
- dot-theme-sync "$new_theme"
218
- }
219
-
220
- # Interactive theme picker
221
- pick_theme() {
222
- local current
223
- current="$(current_theme)"
224
-
225
- if [[ ! -f "$THEMES_FILE" ]]; then
226
- ui_err "Missing" "$THEMES_FILE"
227
- exit 1
228
- fi
229
-
230
- local current_family="${current%-dark}"
231
- [[ "$current_family" != "$current" ]] || current_family="${current%-light}"
232
- local current_mode="dark"
233
- is_dark_theme "$current" 2>/dev/null || current_mode="light"
234
-
235
- # Build theme list: one row per family, shows active mode
236
- local theme_list=""
237
- local family source marker active_mode
238
- while IFS= read -r family; do
239
- [[ -n "$family" ]] || continue
240
- source="$(wallpaper_source "$family")"
241
- marker="○"
242
- active_mode=""
243
- if [[ "$family" == "$current_family" ]]; then
244
- marker="✓"
245
- active_mode="$current_mode"
246
- fi
247
- theme_list+="$(printf '%s %-35s %-8s %s' "$marker" "$family" "$source" "$active_mode")"$'\n'
248
- done < <(paired_families)
249
-
250
- local selected_family
251
- selected_family="$(printf '%s' "$theme_list" | ui_pick \
252
- --header "Select wallpaper theme (current: $current_family [$current_mode])" \
253
- --prompt "Theme >" |
254
- awk '$1 !~ /^#/ && NF >= 2 {print $2}')" || return 0
255
-
256
- if [[ -n "$selected_family" ]]; then
257
- # Apply with current appearance mode (dark/light)
258
- local new_theme="${selected_family}-${current_mode}"
259
- if [[ "$new_theme" != "$current" ]]; then
260
- dot-theme-sync "$new_theme"
261
- else
262
- ui_info "Theme" "already on $current"
263
- fi
264
- else
265
- # Cancelled, or no selector could run. Either way nothing changed, and
266
- # saying so beats exiting mute on a command the user asked to be
267
- # interactive.
268
- ui_info "Theme" "no selection — still on $current"
269
- fi
270
- }
271
-
272
- list_themes() {
273
- local current
274
- current="$(current_theme)"
275
- local current_family="${current%-dark}"
276
- [[ "$current_family" != "$current" ]] || current_family="${current%-light}"
277
-
278
- local count=0
279
- local family source
280
-
281
- printf ' %-35s %s\n' "WALLPAPER" "SOURCE"
282
- printf ' %-35s %s\n' "---------" "------"
283
- while IFS= read -r family; do
284
- [[ -n "$family" ]] || continue
285
- source="$(wallpaper_source "$family")"
286
- if [[ "$family" == "$current_family" ]]; then
287
- ui_ok "$family" "$source ◀"
288
- else
289
- printf ' %-35s %s\n' "$family" "$source"
290
- fi
291
- count=$((count + 1))
292
- done < <(paired_families)
293
-
294
- echo ""
295
- ui_info "Current" "$(current_theme) ($count wallpaper themes available)"
296
- }
297
-
298
- # Toggle between light and dark within the same family, or switch families
299
- toggle_theme() {
300
- local current
301
- current="$(current_theme)"
302
-
303
- if is_dark_theme "$current"; then
304
- if [[ "$current" == *-dark ]]; then
305
- set_theme "${current%-dark}-light"
306
- else
307
- set_theme "$DEFAULT_LIGHT"
308
- fi
309
- else
310
- if [[ "$current" == *-light ]]; then
311
- set_theme "${current%-light}-dark"
312
- else
313
- set_theme "$DEFAULT_DARK"
314
- fi
315
- fi
316
- }
317
-
318
- # Switch to the next wallpaper family while preserving mode.
319
- switch_family() {
320
- local current family
321
- current="$(current_theme)"
322
- family="$(get_theme_family "$current")"
323
- local mode="dark"
324
- local families=()
325
- local idx=0
326
- local next_family=""
327
-
328
- if [[ "$current" == *-light ]]; then
329
- mode="light"
330
- fi
331
-
332
- while IFS= read -r name; do
333
- [[ -n "$name" ]] || continue
334
- families+=("$name")
335
- done < <(paired_families)
336
-
337
- if [[ ${#families[@]} -eq 0 ]]; then
338
- set_theme "$DEFAULT_DARK"
339
- return
340
- fi
341
-
342
- for idx in "${!families[@]}"; do
343
- if [[ "${families[$idx]}" == "$family" ]]; then
344
- next_family="${families[$(((idx + 1) % ${#families[@]}))]}"
345
- break
346
- fi
347
- done
348
-
349
- if [[ -z "$next_family" ]]; then
350
- next_family="${families[0]}"
351
- fi
352
-
353
- set_theme "${next_family}-${mode}"
354
- }
355
-
356
- # Show current theme info
357
- show_current() {
358
- local current family
359
- current="$(current_theme)"
360
- family="$(get_theme_family "$current")"
361
- local mode="dark"
362
- if ! is_dark_theme "$current" 2>/dev/null; then
363
- mode="light"
364
- fi
365
- ui_info "Current" "$current ($family, $mode)"
366
- }
367
-
368
- # Detect system appearance (Dark/Light) and sync dotfiles
369
- sync_theme() {
370
- local os_mode="dark" # Default fallback
371
- case "$(uname -s)" in
372
- Darwin)
373
- if defaults read -g AppleInterfaceStyle >/dev/null 2>&1; then
374
- os_mode="dark"
375
- else
376
- os_mode="light"
377
- fi
378
- ;;
379
- Linux)
380
- if command -v gsettings >/dev/null 2>&1; then
381
- # Check GNOME color scheme. Fixes a long-standing bug where the
382
- # variable was declared as `local scheme=scheme=$(...)` — the
383
- # extra `scheme=` prefix made the value always start with that
384
- # literal, so the `prefer-light` test below could never match
385
- # and the system always fell through to the dark branch.
386
- local scheme
387
- scheme=$(gsettings get org.gnome.desktop.interface color-scheme 2>/dev/null | tr -d "'")
388
- if [[ "$scheme" == "prefer-light" ]]; then
389
- os_mode="light"
390
- else
391
- os_mode="dark"
392
- fi
393
- fi
394
- ;;
395
- esac
396
-
397
- local current
398
- current="$(current_theme)"
399
- if is_dark_theme "$current" && [[ "$os_mode" == "light" ]]; then
400
- ui_info "Sync" "System is light, switching dotfiles to light..."
401
- toggle_theme
402
- elif ! is_dark_theme "$current" && [[ "$os_mode" == "dark" ]]; then
403
- ui_info "Sync" "System is dark, switching dotfiles to dark..."
404
- toggle_theme
405
- else
406
- ui_ok "Sync" "Dotfiles already match system ($os_mode mode)"
407
- fi
408
- }
409
-
410
- # =============================================================================
411
- # Main
412
- # =============================================================================
413
-
414
- case "${1:-}" in
415
- list)
416
- list_themes
417
- ;;
418
- set)
419
- shift
420
- # `"${1:-}"`, not `"$1"`: with no theme name the bare positional aborts
421
- # the script under `set -u` before set_theme's own empty-string check can
422
- # open the picker `dot help theme` promises. Worse, the abort is silent
423
- # about its status on bash 3.2 (macOS /bin/bash): when a script dies on an
424
- # unbound variable with an EXIT trap installed — switch.sh installs
425
- # `trap cleanup EXIT` — 3.2 exits 0, and no handler can recover the status
426
- # because `$?` is already 0 when the handler runs. So on a stock Mac this
427
- # one missing default turned every `dot theme set` typo into a reported
428
- # success. Keep every expansion in this script guarded.
429
- set_theme "${1:-}"
430
- ;;
431
- toggle)
432
- toggle_theme
433
- ;;
434
- sync)
435
- sync_theme
436
- ;;
437
- family)
438
- switch_family
439
- ;;
440
- current)
441
- show_current
442
- ;;
443
- rebuild)
444
- shift
445
- bash "$SCRIPT_DIR/rebuild-themes.sh" "$@"
446
- ;;
447
- help | --help | -h)
448
- ui_header "Usage"
449
- ui_info "dot theme" "[command]"
450
- echo ""
451
- ui_header "Commands"
452
- ui_ok "(no args)" "Interactive theme picker (fzf)"
453
- ui_ok "list" "Show all available themes"
454
- ui_ok "set [NAME]" "Set theme (interactive if no name)"
455
- ui_ok "toggle" "Toggle between light/dark within current family"
456
- ui_ok "family" "Cycle between theme families"
457
- ui_ok "current" "Show current theme info"
458
- ui_ok "sync" "Sync dotfiles with system dark/light mode"
459
- ui_ok "rebuild" "Regenerate themes from system + custom wallpapers"
460
- echo ""
461
- show_current
462
- ;;
463
- "")
464
- pick_theme
465
- ;;
466
- *)
467
- # Treat unknown args as theme names for quick switching: dot theme macos-sequoia-dark
468
- if grep -q "^\[themes\.${1}\]" "$THEMES_FILE" 2>/dev/null; then
469
- dot-theme-sync "$1"
470
- else
471
- ui_err "Unknown command or theme" "$1"
472
- ui_info "Usage" "dot theme [list|set <name>|toggle|family|current|help]"
473
- exit 1
474
- fi
475
- ;;
476
- esac
@@ -1,137 +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
- WALLPAPER_DIR="${DOTFILES_WALLPAPER_DIR:-$HOME/Pictures/Wallpapers}"
7
- INTERVAL="${DOTFILES_WALLPAPER_INTERVAL:-300}"
8
- ONCE=0
9
-
10
- while [[ $# -gt 0 ]]; do
11
- case "$1" in
12
- --interval)
13
- INTERVAL="$2"
14
- shift 2
15
- ;;
16
- --once)
17
- ONCE=1
18
- shift
19
- ;;
20
- --light)
21
- FORCE_MODE="light"
22
- shift
23
- ;;
24
- --dark)
25
- FORCE_MODE="dark"
26
- shift
27
- ;;
28
- *)
29
- shift
30
- ;;
31
- esac
32
- done
33
-
34
- if [[ ! -d "$WALLPAPER_DIR" ]]; then
35
- echo "Wallpaper directory not found: $WALLPAPER_DIR" >&2
36
- exit 1
37
- fi
38
-
39
- # Detect current color scheme (light/dark)
40
- detect_mode() {
41
- if [[ -n "${FORCE_MODE:-}" ]]; then
42
- echo "$FORCE_MODE"
43
- return
44
- fi
45
- if command -v gsettings &>/dev/null; then
46
- local scheme
47
- scheme="$(gsettings get org.gnome.desktop.interface color-scheme 2>/dev/null || echo "")"
48
- case "$scheme" in
49
- *dark*) echo "dark" ;;
50
- *) echo "light" ;;
51
- esac
52
- else
53
- echo "dark"
54
- fi
55
- }
56
-
57
- # Pick a random wallpaper matching mode, excluding the given path
58
- pick_wallpaper() {
59
- local mode="$1"
60
- local exclude="${2:-}"
61
- local files=()
62
- while IFS= read -r line; do
63
- [[ "$line" == "$exclude" ]] && continue
64
- files+=("$line")
65
- done < <(find "$WALLPAPER_DIR" -maxdepth 1 -type f -iname "*-${mode}.jpg")
66
-
67
- if [[ ${#files[@]} -eq 0 ]]; then
68
- return 1
69
- fi
70
-
71
- if command -v shuf &>/dev/null; then
72
- printf '%s\n' "${files[@]}" | shuf -n 1
73
- else
74
- echo "${files[$RANDOM % ${#files[@]}]}"
75
- fi
76
- }
77
-
78
- apply_wallpaper() {
79
- local wp="$1"
80
- local mode="$2"
81
-
82
- case "$(uname -s)" in
83
- Darwin)
84
- osascript -e "tell application \"System Events\" to set picture of every desktop to POSIX file \"$wp\"" || true
85
- ;;
86
- Linux)
87
- if command -v gsettings &>/dev/null; then
88
- local light_wp dark_wp
89
- local base="${wp%-${mode}.jpg}"
90
- light_wp="${base}-light.jpg"
91
- dark_wp="${base}-dark.jpg"
92
-
93
- if [[ -f "$light_wp" ]] && [[ -f "$dark_wp" ]]; then
94
- gsettings set org.gnome.desktop.background picture-uri "file://${light_wp}"
95
- gsettings set org.gnome.desktop.background picture-uri-dark "file://${dark_wp}"
96
- gsettings set org.gnome.desktop.screensaver picture-uri "file://${light_wp}"
97
- else
98
- local wp_uri="file://${wp}"
99
- gsettings set org.gnome.desktop.background picture-uri "$wp_uri"
100
- gsettings set org.gnome.desktop.background picture-uri-dark "$wp_uri"
101
- gsettings set org.gnome.desktop.screensaver picture-uri "$wp_uri"
102
- fi
103
- gsettings set org.gnome.desktop.background picture-options "zoom"
104
- elif command -v swaybg &>/dev/null; then
105
- pkill swaybg || true
106
- swaybg -i "$wp" -m fill &
107
- elif command -v feh &>/dev/null; then
108
- feh --bg-fill "$wp"
109
- else
110
- echo "No supported wallpaper setter found (gsettings/swaybg/feh)." >&2
111
- return 1
112
- fi
113
- ;;
114
- *)
115
- echo "Wallpaper rotation not supported on this OS." >&2
116
- return 1
117
- ;;
118
- esac
119
- }
120
-
121
- LAST_WP=""
122
-
123
- while true; do
124
- MODE="$(detect_mode)"
125
- wp="$(pick_wallpaper "$MODE" "$LAST_WP" || true)"
126
- if [[ -z "$wp" ]]; then
127
- echo "No ${MODE} wallpapers found in $WALLPAPER_DIR" >&2
128
- exit 1
129
- fi
130
- apply_wallpaper "$wp" "$MODE"
131
- LAST_WP="$wp"
132
- echo "Wallpaper applied (${MODE}): $(basename "$wp")"
133
- if [[ "$ONCE" -eq 1 ]]; then
134
- break
135
- fi
136
- sleep "$INTERVAL"
137
- done