UNPKG

@sebastienrousseau/dotfiles

Version:

The Trusted Shell Platform — Universal dotfiles managed by Chezmoi. Features Bash & Zsh for macOS, Linux & WSL. Rust modern tooling & enterprise-grade security.

172 lines (128 loc) 5.15 kB
--- render_with_liquid: false --- # ADR-004: Chezmoi + Custom CLI Wrapper Architecture **Status**: Accepted **Date**: 2026-02-09 **Authors**: @sebastienrousseau ## Context Managing dotfiles requires: - Tracking file changes and applying them consistently - Handling platform-specific configurations - Supporting encrypted secrets - Providing a good developer experience Options considered: 1. **Bare git repository**: Simple but poor UX, no templating 2. **GNU Stow**: Symlink-based, limited features 3. **Chezmoi only**: Powerful but complex CLI 4. **Custom from scratch**: High maintenance burden 5. **Chezmoi + wrapper**: Best of both worlds ## Decision Use **Chezmoi as the core engine** with a **custom `dot` CLI wrapper** that: ### Architecture ```text ┌─────────────────────────────────────────────┐ │ dot CLI │ │ (User-friendly interface, custom commands) │ ├─────────────────────────────────────────────┤ │ Command Modules │ │ core │ diagnostics │ tools │ appearance │ │ secrets │ security │ meta │ ├─────────────────────────────────────────────┤ │ Shared Library │ │ utils.sh (resolve_source_dir, run_script) │ ├─────────────────────────────────────────────┤ │ Chezmoi │ │ (Template engine, state management, apply) │ └─────────────────────────────────────────────┘ ``` ### Core Principles **1. Chezmoi handles complexity:** - Template rendering with Go text/template - Encrypted secrets with age - State tracking (what's applied vs source) - Cross-platform path handling **2. dot CLI handles UX:** - Memorable command names (`dot sync` vs `chezmoi apply`) - Domain-specific commands (`dot doctor`, `dot theme`) - Integration with external tools (Nix, Docker, Neovim) - Consistent help and error messages **3. Modular command structure:** ```text scripts/dot/ ├── lib/ │ └── utils.sh # Shared functions └── commands/ ├── core.sh # apply, sync, update, add, diff ├── diagnostics.sh # doctor, heal, health, benchmark ├── tools.sh # tools, new, packages ├── appearance.sh # theme, wallpaper, fonts ├── secrets.sh # secrets-init, secrets ├── security.sh # firewall, backup, encrypt-check └── meta.sh # upgrade, docs, learn ``` **4. Delegation pattern:** ```bash # Main dispatcher in dot CLI dispatch() { local module="$1" cmd="$2" shift 2 exec bash "$src_dir/scripts/dot/commands/$module.sh" "$cmd" "$@" } ``` ### Chezmoi Integration Points | Feature | Chezmoi | dot CLI | |---------|---------|---------| | Apply changes | `chezmoi apply` | `dot sync` | | View diff | `chezmoi diff` | `dot diff` | | Edit secrets | `chezmoi edit --encrypted` | `dot secrets` | | Source directory | `chezmoi source-path` | `dot cd` | | Health check | `chezmoi doctor` | `dot doctor` (extended) | ### Extension Points Custom commands can: 1. Wrap chezmoi commands with better defaults 2. Add entirely new functionality (benchmarks, themes) 3. Integrate with system tools (nix, docker, brew) 4. Provide interactive experiences (tour, learn) ## Consequences ### Positive - Leverage Chezmoi's battle-tested engine - User-friendly interface for common tasks - Easy to add domain-specific commands - Modular structure enables testing and maintenance - Single entry point (`dot`) for all operations ### Negative - Two layers to understand (chezmoi + dot) - Version coupling between chezmoi and scripts - Some chezmoi features not exposed via dot ### Neutral - Advanced users can still use chezmoi directly - Documentation needed for both layers - Upgrade path when chezmoi adds new features ## Implementation Notes ### Adding a New Command 1. Identify the appropriate module (or create new one) 2. Add function `cmd_<name>()` to module 3. Add case to module's dispatch 4. Add case to main dot CLI dispatcher 5. Update help text 6. Add tests if complex ### Module Template ```bash #!/usr/bin/env bash # Dotfiles CLI - <Category> Commands set -e SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/../lib/utils.sh" cmd_example() { # Implementation } case "${1:-}" in example) shift; cmd_example "$@" ;; *) echo "Unknown command: ${1:-}" >&2; exit 1 ;; esac ``` ## References - [Chezmoi Documentation](https://www.chezmoi.io/) - [Command Pattern](https://refactoring.guru/design-patterns/command) - [Unix Philosophy](https://en.wikipedia.org/wiki/Unix_philosophy)