Decisions
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:
- Bare git repository: Simple but poor UX, no templating
- GNU Stow: Symlink-based, limited features
- Chezmoi only: Powerful but complex CLI
- Custom from scratch: High maintenance burden
- Chezmoi + wrapper: Best of both worlds
Decision
Use Chezmoi as the core engine with a custom dot CLI wrapper that:
Architecture
┌─────────────────────────────────────────────┐
│ 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 syncvschezmoi apply) - Domain-specific commands (
dot doctor,dot theme) - Integration with external tools (Nix, Docker, Neovim)
- Consistent help and error messages
3. Modular command structure:
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:
# Main dispatcher in dot CLI
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:
- Wrap chezmoi commands with better defaults
- Add entirely new functionality (benchmarks, themes)
- Integrate with system tools (nix, docker, brew)
- 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
- Identify the appropriate module (or create new one)
- Add function
cmd_<name>()to module - Add case to module's dispatch
- Add case to main dot CLI dispatcher
- Update help text
- Add tests if complex
Module Template
#!/usr/bin/env bash
# Dotfiles CLI - <Category> Commands
SCRIPT_DIR=""
case "" in
example) ; ;;
*) ; ;;
esac