CtrlK
BlogDocsLog inGet started
Tessl Logo

pantheon-ai/chezmoi

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

Quality

96%

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Advisory

Suggest reviewing before use

Overview
Quality
Evals
Security
Files

SKILL.mdmanaging-chezmoi-packages/

name:
managing-chezmoi-packages
description:
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).

Managing Chezmoi Packages

This skill handles all aspects of package and dependency management in chezmoi dotfiles repositories, with emphasis on security, reproducibility, and automated updates.

Core Principles

  1. Version Pinning: Always pin to immutable references (commit SHAs, specific versions, digests)
  2. Renovate Automation: Ensure all dependencies have corresponding Renovate rules
  3. Organization: Group externals by primary program using .chezmoiexternals/ directory
  4. Minimal Edits: Make focused changes without unrelated modifications
  5. Preview First: Show proposed changes before applying

When to Use This Skill

Invoke this skill when the user requests:

  • Adding/updating/removing packages or tools
  • Managing chezmoi external dependencies
  • Pinning versions or updating SHAs
  • Organizing external files by program
  • Setting up Renovate automation for dependencies
  • Choosing between package ecosystems (Homebrew, mise, etc.)

Workflow

1. Identify the Request

Determine what the user wants:

  • Add: New package or external dependency
  • Update: Change version/SHA of existing package
  • Remove: Delete package or external
  • Organize: Migrate externals to .chezmoiexternals/ structure
  • Pin: Add immutable version/SHA reference

2. Select the Ecosystem

Choose the appropriate package manager (see ./ecosystem-guide.md for details):

Use CaseEcosystemLocation
macOS packages (Homebrew)brew/cask/mashome/.chezmoidata/packages.yaml
CLI developer toolsmise (Aqua).mise.toml or home/dot_config/mise/config.toml
Python toolspiphome/dot_config/dotfiles/requirements.txt
Docker/devcontainerdockerhome/dot_config/docker-compose/*.yml, .devcontainer/
External files/reposchezmoi externalshome/.chezmoiexternals/*.toml[.tmpl]
Install script CLIscli-versionshome/dot_config/dotfiles/cli-versions.toml

3. For Chezmoi Externals: Use .chezmoiexternals/ Directory

IMPORTANT: Organize externals by primary program using the .chezmoiexternals/ directory structure.

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

How It Works

  • Files in home/.chezmoiexternals/ are treated as .chezmoiexternal.<format> files
  • Each file defines externals for a specific program
  • Use .tmpl suffix for templating support (OS conditionals, variables)
  • Paths in each file are relative to the home directory

Example: zsh.externals.toml

{{ 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"

4. External Types and Patterns

Chezmoi supports four external types (detailed in ./externals-reference.md):

git-repo

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"

file

For single files (themes, configs):

[".config/tool/theme.tmTheme"]
type = "file"
url = "https://github.com/user/repo/raw/<commit-sha>/file.ext"
refreshPeriod = "168h"

archive-file

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

archive

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"

5. Version Pinning Requirements

CRITICAL: Always use immutable references:

TypePinning MethodExample
Git repoCommit SHA in revisionrevision = "abc123..."
GitHub fileCommit SHA in URL pathraw/<sha>/file.ext
Release binaryVersion tag + checksumv1.2.3 + checksum = "sha256:..."
Docker imageDigestimage:tag@sha256:...

NEVER use:

  • latest tags
  • Mutable branch names without SHA pinning
  • Version ranges or wildcards
  • URLs without commit SHAs or checksums

6. Ensure Renovate Integration

For 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',
}

7. Apply Changes

For .chezmoiexternals/ files

  1. Create or update the appropriate .externals.toml file
  2. Add comments explaining each dependency
  3. Include Renovate annotations for tracking:
    # renovate: repo=user/repo branch=main
    [".path/to/dependency"]
    type = "git-repo"
    url = "https://github.com/user/repo.git"
    revision = "<commit-sha>"

For packages.yaml

  1. Edit home/.chezmoidata/packages.yaml
  2. Add to appropriate section (darwin/linux, brews/casks/mas)
  3. Follow existing patterns

8. Verification Commands

Preview 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

Common Workflows

Adding a New Zsh Plugin

# 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

Adding a Homebrew Package

# 1. Edit home/.chezmoidata/packages.yaml
# 2. Add to appropriate section (brews/casks)
# 3. Renovate will track automatically (homebrew datasource)

Migrating Existing Externals to .chezmoiexternals/

  1. Identify program groupings in home/.chezmoiexternal.toml
  2. Search for references to the old file before migration:
    grep -r "\.chezmoiexternal\.toml\.tmpl" home/
    Common references to fix:
    • Scripts using {{ include ".chezmoiexternal.toml" }} for hashing
    • Documentation or comments mentioning the file
  3. Create program-specific files in home/.chezmoiexternals/
  4. Move related externals to appropriate file
  5. Update any references found in step 2 to point to new files (e.g., .chezmoiexternals/bat.externals.toml)
  6. Keep conditionals (e.g., {{ if lookPath "zsh" }})
  7. Verify with chezmoi diff (will error if references are broken)
  8. Remove old file only after all references are updated and chezmoi diff succeeds

Updating External to Latest SHA

# 1. Fetch current SHA
gh api repos/USER/REPO/commits/BRANCH --jq .sha

# 2. Update revision in .chezmoiexternals/*.toml
# 3. Apply
chezmoi apply

Output Format

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

Important Constraints

  • Never execute package managers without explicit permission
  • Always preview with chezmoi diff before applying
  • Use minimal edits: Change only what's necessary
  • Maintain comments: Explain why each dependency exists
  • Follow patterns: Match existing style and structure
  • Version pinning: No mutable references

Platform-Specific Handling

Use 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

Troubleshooting

External fails to download:

  • Verify URL accessibility: curl -fsSL <url>
  • Check commit SHA exists: gh api repos/USER/REPO/commits/SHA
  • Review chezmoi logs: chezmoi apply -v

Renovate not detecting dependency:

  • Verify regex pattern matches your format
  • Check fileMatch glob is correct
  • Test regex: use online regex tester with actual file content
  • Ensure annotations are present if required

Checksum mismatch:

  • Download file and compute SHA: curl -fsSL <url> | shasum -a 256
  • Update checksum in external definition
  • Verify URL points to correct version

Best Practices

  1. Group by program: Use .chezmoiexternals/PROGRAM.externals.toml
  2. Document dependencies: Add comments explaining purpose
  3. Annotate for Renovate: Include # renovate: comments
  4. Use templates: Leverage {{ if }} for conditional installs
  5. Set refreshPeriod: Balance freshness vs. performance (168h = weekly)
  6. Test on clean machine: Verify externals work from scratch
  7. Pin everything: No mutable references, ever

Anti-Patterns

NEVER 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.

Eval Scenarios

  • Scenario 0: Add a Zsh plugin as a chezmoi external
  • Scenario 1: Ecosystem selection across three tool types
  • Scenario 2: Cross-platform release binary via archive-file external
  • Scenario 3: Renovate automation rules for existing externals
  • Scenario 4: Migrate legacy .chezmoiexternal.toml to .chezmoiexternals/

References

managing-chezmoi-packages

tile.json