返回 Skill 列表
extension
分类: 开发与工程无需 API Key

chezmoi

使用chezmoi跨多台机器管理点文件。在处理点文件管理、模板、密钥、特定于机器的配置或chezmoi命令时使用。

person作者: jakexiaohubgithub

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

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

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

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

# dot_bashrc.tmpl
{{ if eq .chezmoi.os "darwin" -}}
export HOMEBREW_PREFIX="/opt/homebrew"
{{ else if eq .chezmoi.os "linux" -}}
export HOMEBREW_PREFIX="/home/linuxbrew/.linuxbrew"
{{ end -}}

Machine-specific Config

Create ~/.config/chezmoi/chezmoi.toml for machine-specific data:

[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):

[data]
    email = {{ promptString "Email address" | quote }}
    signingkey = {{ promptString "GPG signing key" | quote }}

Password Manager Integration

1Password

# In template
{{ onepasswordRead "op://vault/item/field" }}
{{ (onepassword "item-name").password }}

Bitwarden

{{ (bitwarden "item-name").login.password }}

pass (Unix Password Store)

{{ pass "path/to/secret" }}

Generic (Any Password Manager)

# In chezmoi.toml
[secret]
    command = "my-secret-tool"
    args = ["get"]

# In templates
{{ secret "secret-name" }}

Encryption

Using age (Recommended)

# Generate key
chezmoi age-keygen

# Configure in chezmoi.toml
[age]
    identity = "~/.config/chezmoi/key.txt"
    recipient = "age1..."

Encrypt Files

# 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

#!/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:

[".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

[".tmux/plugins/tpm"]
    type = "git-repo"
    url = "https://github.com/tmux-plugins/tpm.git"
    refreshPeriod = "168h"

Configuration File

Located at ~/.config/chezmoi/chezmoi.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

# Install chezmoi and apply dotfiles
sh -c "$(curl -fsLS get.chezmoi.io)" -- init --apply $GITHUB_USERNAME

Daily Updates

# Pull changes and apply
chezmoi update

# Or step-by-step
chezmoi git pull
chezmoi diff
chezmoi apply

Adding New Files

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

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 |