Back to skills
SKILL.md
Chezmoi
CSecurityManage dotfiles across multiple machines with chezmoi. Use when working with dotfile management, templating, secrets, machine-specific configs, or chezmoi commands.
- 22 stars
- 0 votes
- 0 copies
- 1 view
- Added September 20, 2026
Security analysis
63/100- Accesses sensitive system or user directories
- Reads or references SSH private keys
- Modifies startup scripts or system services for persistence
Pro scans all 4 files and shows the line behind each finding
npx -y skills add lev-os/agents --skill chezmoi --agent claude-codeAre you the author of Chezmoi?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/lev-os-chezmoi)---
name: chezmoi
description: Manage dotfiles across multiple machines with chezmoi. Use when working with dotfile management, templating, secrets, machine-specific configs, or chezmoi commands.
---
# Chezmoi Dotfile Manager
Manage your dotfiles across multiple diverse machines, securely.
## Quick Reference
| Command | Purpose |
|---------|---------|
| `chezmoi init` | Initialize chezmoi (creates ~/.local/share/chezmoi) |
| `chezmoi add <file>` | Add file to source state |
| `chezmoi edit <file>` | Edit source version of file |
| `chezmoi diff` | Preview changes before applying |
| `chezmoi apply` | Apply changes to home directory |
| `chezmoi update` | Pull latest changes and apply |
| `chezmoi cd` | Open shell in source directory |
| `chezmoi doctor` | Check for problems |
## Local Workflow Contract
On this machine, use the `dotfiles` helper as the control plane instead of jumping straight to `chezmoi update`.
### Dry Run First
```bash
dotfiles status # Summary dashboard for chezmoi + ~/.agents
dotfiles sync # Dry-run planner, writes latest report
dotfiles inspect report # Full dry-run report
dotfiles inspect chezmoi-diff # Full target/source diff
dotfiles inspect chezmoi-remote # Remote commits not yet local
dotfiles inspect agents-remote # ~/.agents remote commits not yet local
```
### Explicit Apply Paths
```bash
dotfiles sync --apply chezmoi # Re-add, commit, pull --rebase, push, apply
dotfiles sync --apply agents # Commit, pull --rebase, push ~/.agents
dotfiles sync --apply all # Run both explicit apply paths
dotfiles pull # Pull chezmoi source repo and apply
dotfiles agents-pull # Pull ~/.agents with rebase
```
### Behavior Rules
- `dotfiles sync` is the safe entry point. It performs a dry run and does not mutate state.
- Read the dry-run report before choosing an apply action when local and remote both moved.
- `~/.agents` stays a separate git repo; it is surfaced in the same dashboard but is not folded into chezmoi source state.
- The latest dry-run report is written to `~/.local/state/lev/dotfiles-sync-plan.latest.txt`.
## One-liner Bootstrap
```bash
sh -c "$(curl -fsLS get.chezmoi.io)" -- init --apply $GITHUB_USERNAME
```
## Core Concepts
### Source State vs Target State
- **Source state**: Files in `~/.local/share/chezmoi/` (managed by chezmoi)
- **Target state**: Files in your home directory (what chezmoi manages)
- **Destination directory**: Usually `~` (your home)
### File Naming Conventions
| Prefix/Suffix | Meaning | Example |
|---------------|---------|---------|
| `dot_` | Creates `.` prefix | `dot_bashrc` → `.bashrc` |
| `private_` | Mode 0600 | `private_dot_ssh/` |
| `executable_` | Mode +x | `executable_dot_local/bin/myscript` |
| `readonly_` | Read-only | `readonly_dot_config/` |
| `empty_` | Create empty file | `empty_dot_gitkeep` |
| `symlink_` | Create symlink | `symlink_dot_config` |
| `.tmpl` | Template file | `dot_bashrc.tmpl` |
### Directory Attributes
```
~/.local/share/chezmoi/
├── dot_config/
│ ├── exact_nvim/ # exact_ = remove unlisted files
│ └── private_gnupg/ # private_ = mode 0700
├── private_dot_ssh/
│ └── private_config # mode 0600
└── dot_bashrc.tmpl # template
```
## Templating
### Basic Template Syntax
```
{{ .chezmoi.hostname }} # Current hostname
{{ .chezmoi.os }} # darwin, linux, windows
{{ .chezmoi.arch }} # amd64, arm64
{{ .chezmoi.username }} # Current user
{{ .chezmoi.homeDir }} # Home directory path
```
### Conditionals
```bash
# dot_bashrc.tmpl
{{ if eq .chezmoi.os "darwin" -}}
export HOMEBREW_PREFIX="/opt/homebrew"
{{ else if eq .chezmoi.os "linux" -}}
export HOMEBREW_PREFIX="${HOMEBREW_PREFIX:-$HOME/.linuxbrew}"
{{ end -}}
```
### Machine-specific Config
Create `~/.config/chezmoi/chezmoi.toml` for machine-specific data:
```toml
[data]
email = "me@work.com"
git_signing_key = "ABC123"
[data.work]
enabled = true
```
Then in templates:
```
{{ .email }}
{{ if .work.enabled }}
# Work-specific config
{{ end }}
```
### Prompt for Data on Init
Create `.chezmoi.<format>.tmpl` (e.g., `.chezmoi.toml.tmpl`):
```toml
[data]
email = {{ promptString "Email address" | quote }}
signingkey = {{ promptString "GPG signing key" | quote }}
```
## Password Manager Integration
### 1Password
```toml
# In template
{{ onepasswordRead "op://vault/item/field" }}
{{ (onepassword "item-name").password }}
```
### Bitwarden
```toml
{{ (bitwarden "item-name").login.password }}
```
### pass (Unix Password Store)
```toml
{{ pass "path/to/secret" }}
```
### Generic (Any Password Manager)
```toml
# In chezmoi.toml
[secret]
command = "my-secret-tool"
args = ["get"]
# In templates
{{ secret "secret-name" }}
```
## Encryption
### Using age (Recommended)
```bash
# Generate key
chezmoi age-keygen
# Configure in chezmoi.toml
[age]
identity = "~/.config/chezmoi/key.txt"
recipient = "age1..."
```
### Encrypt Files
```bash
# Add encrypted file
chezmoi add --encrypt ~/.ssh/id_rsa
# Result: encrypted_private_dot_ssh/private_id_rsa.age
```
## Scripts
### Run Scripts on Apply
| Prefix | Runs When |
|--------|-----------|
| `run_` | Every apply |
| `run_once_` | Only once (tracked by checksum) |
| `run_onchange_` | When script content changes |
### Script Ordering
Scripts run alphabetically. Use numeric prefixes:
```
.chezmoiscripts/
├── run_once_before_01-install-homebrew.sh
├── run_once_before_02-install-packages.sh
└── run_onchange_after_reload-shell.sh
```
### Script Template
```bash
#!/bin/bash
# run_once_before_install-packages.sh.tmpl
{{ if eq .chezmoi.os "darwin" -}}
brew bundle --file=/dev/stdin <<EOF
brew "ripgrep"
brew "fd"
cask "wezterm"
EOF
{{ else if eq .chezmoi.os "linux" -}}
sudo apt-get install -y ripgrep fd-find
{{ end -}}
```
## External Files
### Import from URL/Archive
Create `.chezmoiexternal.toml`:
```toml
[".oh-my-zsh"]
type = "archive"
url = "https://github.com/ohmyzsh/ohmyzsh/archive/master.tar.gz"
stripComponents = 1
refreshPeriod = "168h"
[".local/bin/starship"]
type = "file"
url = "https://starship.rs/install.sh"
executable = true
```
### Import from Git
```toml
[".tmux/plugins/tpm"]
type = "git-repo"
url = "https://github.com/tmux-plugins/tpm.git"
refreshPeriod = "168h"
```
## Configuration File
Located at `~/.config/chezmoi/chezmoi.toml`:
```toml
# Source directory (default: ~/.local/share/chezmoi)
sourceDir = "~/.dotfiles"
# Diff tool
[diff]
pager = "delta"
# Merge tool
[merge]
command = "nvim"
args = ["-d", "{{ .Destination }}", "{{ .Source }}", "{{ .Target }}"]
# Git auto-commit
[git]
autoCommit = true
autoPush = false
# Data for templates
[data]
name = "Your Name"
email = "your@email.com"
```
## Common Workflows
### New Machine Setup
```bash
# Install chezmoi and apply dotfiles
sh -c "$(curl -fsLS get.chezmoi.io)" -- init --apply $GITHUB_USERNAME
```
### Daily Updates
```bash
# Pull changes and apply
chezmoi update
# Or step-by-step
chezmoi git pull
chezmoi diff
chezmoi apply
```
### Adding New Files
```bash
chezmoi add ~/.bashrc # Regular file
chezmoi add --encrypt ~/.ssh/config # Encrypted
chezmoi add --template ~/.gitconfig # As template
chezmoi add --autotemplate ~/.config/X # Auto-detect template
```
### Editing Files
```bash
chezmoi edit ~/.bashrc # Edit source, then apply
chezmoi edit-config # Edit chezmoi.toml
```
## Troubleshooting
See `references/troubleshooting.md` for common issues including:
- Vimpager/AnsiEsc ANSI escape code issues
- Diff pager configuration
- Encryption setup problems
## References
- **Official Docs**: https://www.chezmoi.io/
- **GitHub**: https://github.com/twpayne/chezmoi
- **Quick Start**: https://www.chezmoi.io/quick-start/
- **User Guide**: https://www.chezmoi.io/user-guide/
- **Reference**: https://www.chezmoi.io/reference/
## Template Functions Reference
### Filesystem
| Function | Description |
|----------|-------------|
| `glob "pattern"` | Find files matching pattern |
| `include "path"` | Include file contents |
| `stat "path"` | Get file info |
| `lookPath "cmd"` | Find command in PATH |
### Strings
| Function | Description |
|----------|-------------|
| `contains "substr" "str"` | Check substring |
| `hasPrefix "pre" "str"` | Check prefix |
| `hasSuffix "suf" "str"` | Check suffix |
| `replace "old" "new" "str"` | Replace in string |
| `trim "str"` | Trim whitespace |
| `quote "str"` | Quote for TOML |
### Data Formats
| Function | Description |
|----------|-------------|
| `toJson .data` | Convert to JSON |
| `toToml .data` | Convert to TOML |
| `toYaml .data` | Convert to YAML |
| `fromJson "str"` | Parse JSON |
| `fromToml "str"` | Parse TOML |
| `fromYaml "str"` | Parse YAML |
### Execution
| Function | Description |
|----------|-------------|
| `output "cmd" "args"...` | Run command, return output |
| `env "VAR"` | Get environment variable |
Files in this skill
- SKILL.md
- references/package-management.md
- references/templates.md
- references/troubleshooting.md
Attribution
Comments
Loading comments…