Expert assistant for chezmoi dotfiles management. Use when: "add this file to chezmoi", "make this a template", "encrypt this secret", "apply on a new machine", "run script only once", "manage dotfiles across machines". Examples: - user: "Track my .zshrc with chezmoi" → chezmoi add ~/.zshrc - user: "Make my .gitconfig machine-specific" → convert to .tmpl, use {{ .chezmoi.hostname }} - user: "Run a script only on first apply" → once_ prefix - user: "Sync to a new laptop" → chezmoi init --apply $GITHUB_USERNAME - user: "Why isn't my file being applied?" → diagnose source attribute, diff, doctor
96
96%
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Advisory
Suggest reviewing before use
This skill handles all aspects of package and dependency management in chezmoi dotfiles repositories, with emphasis on security, reproducibility, and automated updates.
.chezmoiexternals/ directoryInvoke this skill when the user requests:
Determine what the user wants:
.chezmoiexternals/ structureChoose the appropriate package manager (see ./ecosystem-guide.md for details):
| Use Case | Ecosystem | Location |
|---|---|---|
| macOS packages (Homebrew) | brew/cask/mas | home/.chezmoidata/packages.yaml |
| CLI developer tools | mise (Aqua) | .mise.toml or home/dot_config/mise/config.toml |
| Python tools | pip | home/dot_config/dotfiles/requirements.txt |
| Docker/devcontainer | docker | home/dot_config/docker-compose/*.yml, .devcontainer/ |
| External files/repos | chezmoi externals | home/.chezmoiexternals/*.toml[.tmpl] |
| Install script CLIs | cli-versions | home/dot_config/dotfiles/cli-versions.toml |
IMPORTANT: Organize externals by primary program using the .chezmoiexternals/ directory structure.
home/.chezmoiexternals/
├── zsh.externals.toml # Zsh plugins and tools
├── bat.externals.toml # Bat themes and syntaxes
├── tmux.externals.toml # Tmux configurations
└── nvim.externals.toml # Neovim pluginshome/.chezmoiexternals/ are treated as .chezmoiexternal.<format> files.tmpl suffix for templating support (OS conditionals, variables){{ if lookPath "zsh" }}
# Zsh plugins and tools
[".zsh/znap/zsh-snap"]
type = "git-repo"
url = "https://github.com/marlonrichert/zsh-snap.git"
revision = "25754a45d9ceafe6d7d082c9ebe40a08cb85a4f0"
refreshPeriod = "168h"
[".zsh/plugins/zsh-autosuggestions"]
{{ end }}type = "git-repo"
url = "https://github.com/zsh-users/zsh-autosuggestions.git"
revision = "85919cd1ffa7d2d5412f6d3fe437ebdbeeec4fc5"
refreshPeriod = "168h"Chezmoi supports four external types (detailed in ./externals-reference.md):
For complete Git repositories (plugins, frameworks):
[".zsh/plugins/plugin-name"]
type = "git-repo"
url = "https://github.com/user/repo.git"
revision = "<commit-sha>" # MUST pin to SHA
refreshPeriod = "168h"For single files (themes, configs):
[".config/tool/theme.tmTheme"]
type = "file"
url = "https://github.com/user/repo/raw/<commit-sha>/file.ext"
refreshPeriod = "168h"For extracting single binary from release archive:
[".local/bin/tool"]
type = "archive-file"
url = "https://github.com/user/repo/releases/download/v1.2.3/tool.tar.gz"
executable = true
path = "tool"
checksum = "sha256:abc123..."For extracting entire archive into directory:
[".config/tool"]
type = "archive"
url = "https://github.com/user/repo/archive/<commit-sha>.tar.gz"
exact = true
stripComponents = 1
refreshPeriod = "168h"CRITICAL: Always use immutable references:
| Type | Pinning Method | Example |
|---|---|---|
| Git repo | Commit SHA in revision | revision = "abc123..." |
| GitHub file | Commit SHA in URL path | raw/<sha>/file.ext |
| Release binary | Version tag + checksum | v1.2.3 + checksum = "sha256:..." |
| Docker image | Digest | image:tag@sha256:... |
NEVER use:
latest tagsFor each external dependency, verify or add corresponding Renovate rule in renovate.json5.
See ./renovate-integration.md for detailed patterns.
Quick reference:
{
customType: 'regex',
fileMatch: ['^home/\\.chezmoiexternals/.*\\.toml(\\.tmpl)?$'],
matchStrings: [
'revision = "(?<currentDigest>[a-f0-9]{40})".*?# renovate: repo=(?<depName>.*?) branch=(?<currentValue>.*?)\\n',
],
datasourceTemplate: 'git-refs',
}.externals.toml file# renovate: repo=user/repo branch=main
[".path/to/dependency"]
type = "git-repo"
url = "https://github.com/user/repo.git"
revision = "<commit-sha>"home/.chezmoidata/packages.yamlPreview changes:
chezmoi diffCheck external URLs:
# Verify latest commit SHA
gh api repos/USER/REPO/commits/BRANCH --jq .sha
# Check latest release tag
gh api repos/USER/REPO/releases/latest --jq .tag_name
# Verify file exists at SHA
curl -fsSL https://github.com/USER/REPO/raw/SHA/path/to/fileApply changes:
chezmoi applyTest external updates:
chezmoi update --force# 1. Get latest commit SHA
gh api repos/zsh-users/zsh-history-substring-search/commits/master --jq .sha
# 2. Add to home/.chezmoiexternals/zsh.externals.toml
# 3. Add Renovate rule to renovate.json5
# 4. Preview and apply
chezmoi diff
chezmoi apply# 1. Edit home/.chezmoidata/packages.yaml
# 2. Add to appropriate section (brews/casks)
# 3. Renovate will track automatically (homebrew datasource)home/.chezmoiexternal.tomlgrep -r "\.chezmoiexternal\.toml\.tmpl" home/{{ include ".chezmoiexternal.toml" }} for hashinghome/.chezmoiexternals/.chezmoiexternals/bat.externals.toml){{ if lookPath "zsh" }})chezmoi diff (will error if references are broken)chezmoi diff succeeds# 1. Fetch current SHA
gh api repos/USER/REPO/commits/BRANCH --jq .sha
# 2. Update revision in .chezmoiexternals/*.toml
# 3. Apply
chezmoi applyWhen making changes, provide:
Decision:
- Ecosystem: <brew|mise|python|docker|chezmoi-external|cli-versions>
- Rationale: <1-2 sentences>
- Organization: <which .chezmoiexternals/ file or other manifest>
Files To Edit:
- <path1>
- <path2>
Proposed Changes:
<concise diff-like hunks showing additions/modifications>
Renovate Integration:
- Rule Status: <exists|needs-addition|needs-update>
- Pattern: <brief description of regex or datasource>
Verification Commands:
- chezmoi diff
- <optional gh api commands to verify versions>
Next Steps:
- [ ] Review proposed changes
- [ ] Preview with chezmoi diff
- [ ] Apply with chezmoi applychezmoi diff before applyingUse Go templates for platform-specific externals:
{{ if eq .chezmoi.os "darwin" }}
[".local/bin/tool-mac"]
{{ else if eq .chezmoi.os "linux" }}
type = "archive-file"
url = "https://github.com/user/tool/releases/download/v1.0.0/tool-darwin-{{ .chezmoi.arch }}.tar.gz"
executable = true
[".local/bin/tool-linux"]
{{ end }}type = "archive-file"
url = "https://github.com/user/tool/releases/download/v1.0.0/tool-linux-{{ .chezmoi.arch }}.tar.gz"
executable = trueExternal fails to download:
curl -fsSL <url>gh api repos/USER/REPO/commits/SHAchezmoi apply -vRenovate not detecting dependency:
Checksum mismatch:
curl -fsSL <url> | shasum -a 256.chezmoiexternals/PROGRAM.externals.toml# renovate: comments{{ if }} for conditional installsNEVER use mutable references (latest, branch names, version ranges) in externals. WHY: Mutable refs make reproductions non-deterministic — the same chezmoi apply produces different results on different days, breaking machine parity.
NEVER execute package managers (brew install, mise use, chezmoi apply) without explicit user permission. WHY: Package installs modify system state; the agent's role is to propose changes, not apply them unilaterally.
NEVER create a new .chezmoiexternal.toml at the repo root when .chezmoiexternals/ already exists. WHY: Mixing the legacy single-file format with the directory-based format confuses chezmoi and leads to duplicate or shadowed external definitions.
NEVER add a new external ecosystem when an existing one already covers the use case. WHY: Every additional ecosystem (Homebrew + mise + pip + externals + cli-versions) multiplies maintenance burden; always consult ./references/ecosystem-guide.md before introducing a new one.
NEVER omit a Renovate rule when adding a pinned external. WHY: A pinned dependency with no automation becomes stale immediately — security vulnerabilities and breaking changes accumulate silently until someone notices.
NEVER skip chezmoi diff before proposing chezmoi apply. WHY: Externals can overwrite local modifications; showing the diff first lets the user confirm no unexpected files will be changed.
references/externals-reference.md — Complete external type specificationsreferences/renovate-integration.md — Renovate automation patternsreferences/ecosystem-guide.md — Package manager selection guide