skills/specialized/chezmoi/managing-chezmoi-packages/SKILL.md
Use this skill when managing packages, external dependencies, binaries, or CLI tools in a chezmoi dotfiles repository. Handles adding/updating/removing packages in .chezmoidata/packages.yaml, creating .chezmoiexternals/ organized files, pinning versions with Renovate automation, and selecting the correct package ecosystem (Homebrew, mise, Python, Docker, chezmoi externals).
npx skillsauth add pantheon-org/tekhne managing-chezmoi-packagesInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
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 plugins
home/.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 diff
Check 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/file
Apply changes:
chezmoi apply
Test 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/
Common references to fix:
{{ 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 apply
When 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 apply
chezmoi 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 = true
External 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 guidetools
A skill that produces warnings but no errors.
testing
A well-formed example skill for testing the validator.
development
A skill with code blocks and imperative instructions for testing content and contamination analysis.
tools