twpayne/chezmoi
Manage your dotfiles across multiple diverse machines, securely.
Healthy across all four use cases
Permissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 2d ago
- ✓8 active contributors
- ✓MIT licensed
Show 3 more →Show less
- ✓CI configured
- ✓Tests present
- ⚠Single-maintainer risk — top contributor 83% of recent commits
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/twpayne/chezmoi)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/twpayne/chezmoi on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: twpayne/chezmoi
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/twpayne/chezmoi shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across all four use cases
- Last commit 2d ago
- 8 active contributors
- MIT licensed
- CI configured
- Tests present
- ⚠ Single-maintainer risk — top contributor 83% of recent commits
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live twpayne/chezmoi
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/twpayne/chezmoi.
What it runs against: a local clone of twpayne/chezmoi — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in twpayne/chezmoi | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 32 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of twpayne/chezmoi. If you don't
# have one yet, run these first:
#
# git clone https://github.com/twpayne/chezmoi.git
# cd chezmoi
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of twpayne/chezmoi and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "twpayne/chezmoi(\\.git)?\\b" \\
&& ok "origin remote is twpayne/chezmoi" \\
|| miss "origin remote is not twpayne/chezmoi (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "Makefile" \\
&& ok "Makefile" \\
|| miss "missing critical file: Makefile"
test -f ".github/workflows/main.yml" \\
&& ok ".github/workflows/main.yml" \\
|| miss "missing critical file: .github/workflows/main.yml"
test -f ".config/golangci.yml" \\
&& ok ".config/golangci.yml" \\
|| miss "missing critical file: .config/golangci.yml"
test -f "go.mod" \\
&& ok "go.mod" \\
|| miss "missing critical file: go.mod"
test -f "assets/chezmoi.io/docs/developer-guide/architecture.md" \\
&& ok "assets/chezmoi.io/docs/developer-guide/architecture.md" \\
|| miss "missing critical file: assets/chezmoi.io/docs/developer-guide/architecture.md"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 32 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~2d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/twpayne/chezmoi"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
chezmoi is a dotfile manager written in Go that synchronizes configuration files (dotfiles) across multiple machines while supporting encryption, templating, and secure secret management. It lets you version-control sensitive configs (SSH keys, API tokens) using age or other encryption backends, then deploy them safely to diverse systems via a declarative state model. Monorepo structure: main chezmoi tool in cmd/chezmoi with internal/cmd/*.go subcommands; state engine in internal/chezmoi (Config, State, TargetState); encryption backends abstracted in internal/secretmanager (age, bitwarden, gopass, keyvault, etc.); website docs generated from .tmpl templates in assets/chezmoi.io/docs. Tool dependencies managed via go.mod with tool directives for code generation (generate-helps, execute-template, etc.).
👥Who it's for
Systems administrators, DevOps engineers, and power users who maintain dotfiles across many machines (laptops, servers, containers) and need to keep sensitive configuration encrypted at rest and selectively decrypt per-host during deployment.
🌱Maturity & risk
Production-ready and actively maintained. The project has extensive Go test coverage, comprehensive CI/CD via GitHub Actions (.github/workflows/main.yml), detailed documentation at chezmoi.io, and uses semantic versioning with goreleaser (config at .config/goreleaser.yaml). Latest releases are recent, indicating ongoing development.
Low risk for core functionality; the codebase is large (1.2M+ lines of Go) with substantial test coverage and active maintenance. However, dependency surface is wide (age, Azure SDK, AWS SDK, git, keyvault clients), creating potential supply-chain risk. Single primary author (twpayne) visible in repo structure suggests concentration of maintenance knowledge, though community contributions are tracked (see contributors.rocks badge in README).
Active areas of work
Active development on multi-machine synchronization, secret backends (Azure Keyvault, AWS Secrets Manager, gopass integration), and templating features. Workflows in .github/workflows/ show ongoing: govulncheck (security scanning), installer testing, docs preview, and PR cache management. The codebase integrates recent sprig v3 (templating) and age v1.3.1 (encryption).
🚀Get running
git clone https://github.com/twpayne/chezmoi.git
cd chezmoi
make build
./chezmoi --help
Requires Go 1.25.7+. Use make to see all targets (defined in Makefile at repo root).
Daily commands:
make build
./chezmoi init
./chezmoi status
./chezmoi apply -vv
For development/testing: make test, make lint (uses golangci-lint config at .config/golangci.yml). See assets/chezmoi.io/docs/developer-guide/using-make.md for full Makefile targets.
🗺️Map of the codebase
Makefile— Defines all build, test, and release targets; essential for understanding the development workflow and CI/CD pipeline..github/workflows/main.yml— Primary CI/CD workflow that runs tests, linting, and builds; critical for understanding quality gates and release process..config/golangci.yml— Linting configuration that enforces code quality standards across the entire Go codebase.go.mod— Module definition and dependency manifest; required to understand external dependencies and Go version requirements.assets/chezmoi.io/docs/developer-guide/architecture.md— Official architecture documentation explaining chezmoi's core design, abstractions, and data model..github/CONTRIBUTING.md— Contribution guidelines covering code style, testing requirements, and PR process for all contributors.README.md— High-level project overview and entry point; explains chezmoi's purpose as a dotfile manager.
🛠️How to make changes
Add a new command to chezmoi
- Create command implementation in internal/cmds/ following existing command patterns (e.g., apply.md, add.md) (
assets/chezmoi.io/docs/reference/commands/index.md) - Add command markdown documentation in reference/commands/ directory with usage and examples (
assets/chezmoi.io/docs/reference/commands/add.md) - Wire command into CLI dispatcher and ensure help text is generated via generate-helps tool (
internal/cmds/generate-helps) - Add integration tests using txtar format, validated by lint-txtar (
internal/cmds/lint-txtar) - Update Makefile with test target and ensure golangci.yml linting passes (
.config/golangci.yml)
Add a new encryption backend
- Implement encryption interface following age backend pattern in reference/commands/age.md (
assets/chezmoi.io/docs/reference/commands/age.md) - Create key generation command alongside age-keygen.md as template (
assets/chezmoi.io/docs/reference/commands/age-keygen.md) - Document security properties in developer guide (
assets/chezmoi.io/docs/developer-guide/security.md) - Add configuration support via edit-config.md patterns (
assets/chezmoi.io/docs/reference/commands/edit-config.md) - Ensure all tests pass with govulncheck (
.github/workflows/govulncheck.yml)
Update documentation for a feature
- Edit or create .md file in assets/chezmoi.io/docs/reference/commands/ for command documentation (
assets/chezmoi.io/docs/reference/commands/apply.md) - Run markdownlint validation to ensure consistency (
.config/markdownlint-cli2.yaml) - If adding code examples, validate with execute-template tool (
internal/cmds/execute-template) - Update main index or reference page in docs/reference/ if introducing new section (
assets/chezmoi.io/docs/reference/commands/index.md) - Verify documentation builds successfully via build-docs workflow (
.github/workflows/build-docs.yml)
Add a platform-specific feature (e.g., Windows support)
- Implement platform-specific logic in application-order.md patterns (
assets/chezmoi.io/docs/reference/application-order.md) - Update .editorconfig and linting rules for consistency (
.editorconfig) - Document platform-specific behavior in reference guides (
assets/chezmoi.io/docs/reference/commands/apply.md) - Add cross-platform tests to main.yml workflow (
.github/workflows/main.yml) - Ensure goreleaser generates binaries for target platforms (
.config/goreleaser.yaml)
🔧Why these technologies
- Go 1.25.7 — Enables cross-platform compilation for macOS, Linux, Windows; provides performance and reliability for system-level dotfile management.
- age encryption (reference/commands/age.md) — Modern, minimal encryption backend for securing sensitive dotfile data; integrates seamlessly with chezmoi's template system.
- Text archive (txtar) format — Enables reproducible integration tests without external dependencies; validates chezmoi behavior across scenarios.
- Template system (execute-template) — Allows dotfiles to be parameterized and adapted per-machine; core to chezmoi's multi-machine management story.
- GitHub Actions workflows — Automates testing, linting, vulnerability scanning, and releases; ensures code quality before release.
⚖️Trade-offs already made
-
Single binary distribution via goreleaser
- Why: Simplifies installation and updates across machines; reduces dependency management overhead.
- Consequence: Larger binary size; less flexibility for modular installations.
-
Config file templating (execute-template)
- Why: Enables dynamic configuration without external tools; adapts chezmoi behavior per-machine.
- Consequence: Adds complexity to configuration; potential for subtle templating errors.
-
Git-based state management (reference/commands/git.md implied)
- Why: Leverages existing version control infrastructure; enables easy auditing and rollback.
- Consequence: Requires users to manage git workflows; may confuse with system git configs.
-
Optional encryption (age backend)
- Why: Allows secure storage of secrets in version control; opt-in to avoid overhead for non-sensitive files.
- Consequence: Users must understand encryption workflows; key management adds operational complexity.
🚫Non-goals (don't propose these)
- Real-time synchronization of dotfiles across machines (command-driven
🪤Traps & gotchas
Templating context: chezmoi uses Go templates + sprig functions; confusing syntax with shell/env var expansion ({{ .chezmoi.homeDir }} vs $HOME). Cross-platform path handling: internal uses AbsPath (platform-aware); tests use testdata/txtar format which requires exact whitespace. Secret backend auth: each backend (AWS, Azure, Bitwarden, gopass) has silent fallback behavior if env vars missing—easy to deploy broken configs. State format: dotfiles are stored in a special directory structure (dot_ prefix, encrypted_ prefix, etc.) that's non-obvious; see internal/chezmoi/targetstate.go. Git integration: chezmoi auto-commits by default if .git/ exists in source repo; can surprise users if they expect manual control.
🏗️Architecture
💡Concepts to learn
- Declarative State Model — chezmoi's core design: you declare desired state in a source repo, then apply() diffs actual vs desired and idempotently converges; critical to understanding why chezmoi differs from shell-script dotfile managers
- Age Encryption (filippo.io/age) — Modern, minimal-configuration encryption used for secrets in dotfiles; chezmoi uses it as default backend for encrypted_ files; essential to understand how sensitive config stays secure at rest
- Go Templates + Sprig Functions — chezmoi dotfiles use Go's template/text engine with Masterminds/sprig helpers (range, if, dict); users write templates that chezmoi renders per-machine with context like .chezmoi.hostname, .chezmoi.os
- Pluggable Secret Manager Interface — internal/secretmanager defines a clean interface allowing swappable backends (age, bitwarden, AWS Secrets Manager, Azure Keyvault, gopass); teaches dependency injection in Go and how to extend chezmoi
- Idempotent Apply (Desired State Convergence) — chezmoi apply re-runs safely because it compares current filesystem state to desired state and only modifies what differs; understanding this prevents confusion when running apply multiple times
- txtar (Text Archive Format) — chezmoi uses txtar (Go's testdata format) for fixtures in tests; every internal/*_test.go uses this to define test files and expected outputs; essential for reading/writing tests
- Cross-Platform Path Abstraction (AbsPath/RelPath) — chezmoi runs on Windows, macOS, Linux; internal/chezmoi defines AbsPath and RelPath types to safely handle path separators and home directory expansion; mistakes here break multiplatform deployments
🔗Related repos
anishathalye/dotbot— Alternative dotfile manager using YAML-based task automation instead of chezmoi's declarative state model; simpler but less powerful for multi-machine secretsthoughtbot/rcm— Historical dotfile manager (shell-based) that predates chezmoi; inspired many patterns but lacks encryption and templatingfilippo.io/age— Lightweight encryption library that chezmoi depends on (v1.3.1) for encrypting sensitive dotfile values; essential to understand the crypto modeltwpayne/chezmoi-data— Community repo collecting dotfile examples and chezmoi templates shared by users; reference implementationsgolang/go— chezmoi is pure Go; understanding Go's module system, testing patterns, and cross-compilation tooling directly impacts development
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add integration tests for chezmoi's encryption backends (age, ejson, gopass)
The repo has dependencies on multiple secret management tools (filippo.io/age, github.com/Shopify/ejson, github.com/gopasspw/gopass) but the test coverage for these backends appears incomplete. New contributors could add integration tests that verify encryption/decryption workflows across all three backends, ensuring they work correctly with chezmoi's dotfile templating system.
- [ ] Examine existing tests in internal/ directory to understand current test structure
- [ ] Create tests/integration/encryption_backends_test.go with test cases for age, ejson, and gopass
- [ ] Test end-to-end workflows: encrypt dotfile → apply → decrypt on different machine
- [ ] Add test fixtures in assets/ for encrypted test dotfiles
- [ ] Update .github/workflows/main.yml to run these integration tests with required tools installed
Document and add missing test coverage for Azure Keyvault and AWS Secrets Manager integrations
The repo pulls in Azure SDK (github.com/Azure/azure-sdk-for-go) and AWS SDK (github.com/aws/aws-sdk-go-v2) for secret storage, but there's no visible documentation in assets/chezmoi.io/docs/ for these cloud integrations, and test coverage may be incomplete. A contributor could add both documentation and unit tests for these backends.
- [ ] Create assets/chezmoi.io/docs/reference/secret-management/azure-keyvault.md with configuration examples
- [ ] Create assets/chezmoi.io/docs/reference/secret-management/aws-secrets-manager.md with configuration examples
- [ ] Add unit tests in internal/ for Azure and AWS secret retrieval and caching
- [ ] Update assets/chezmoi.io/docs/reference/command-line-flags/common.md to document cloud-specific flags
- [ ] Add examples showing credentials configuration per machine in quick-start guide
Add comprehensive tests for chezmoi's TUI components (charmbracelet packages)
The repo has recent dependencies on charmbracelet/bubbletea, charmbracelet/bubbles, and charmbracelet/lipgloss for terminal UI, but there's likely minimal test coverage for interactive UI workflows. New contributors could add tests for the interactive apply/diff prompts that users see.
- [ ] Identify TUI entry points in internal/cmd/ that use bubbletea
- [ ] Create internal/cmd/apply_ui_test.go and internal/cmd/diff_ui_test.go
- [ ] Test model initialization, state transitions, and user input handling for interactive prompts
- [ ] Add test fixtures for different TUI scenarios (single file, multiple files, conflicts)
- [ ] Update .github/workflows/main.yml to ensure TUI tests run in headless environments
🌿Good first issues
- Add shell-completion tests for newly added subcommands (edit, status, etc.): cmd/chezmoi/completion{bash,fish,zsh}_test.go lack coverage for all command flags: Low risk, isolated to test files, improves robustness without touching core state logic
- Document the txtar test format used throughout internal/*_test.go in assets/chezmoi.io/docs/developer-guide/testing.md; currently undocumented but critical for understanding test fixtures: High impact for onboarding; pure documentation, no code changes
- Add a new secret backend template in internal/secretmanager/{newbackend}.go (e.g., HashiCorp Vault integration) by copying gopass.go pattern and implementing the SecretManager interface: Self-contained, teaches interface patterns, directly valuable to users needing custom secret stores
⭐Top contributors
Click to expand
Top contributors
- @twpayne — 83 commits
- @KapJI — 11 commits
- @bradenhilton — 1 commits
- @Nastaliss — 1 commits
- @halostatue — 1 commits
📝Recent commits
Click to expand
Recent commits
ff6317e— chore: Update dependencies (twpayne)02a3c94— chore: Update Github Actions (twpayne)f323d05— chore: Update tools (twpayne)aa52ca5— chore: Ignore close errors (twpayne)8f342f2— chore: Update dependencies (twpayne)4fc80e0— chore: Update Github Actions (twpayne)eab95d6— chore: Update tools (twpayne)b6b0f1c— chore: Update GitHub Actions (twpayne)3ce6406— chore: Update tools (twpayne)7165955— chore: Update dependencies (twpayne)
🔒Security observations
The chezmoi codebase demonstrates a strong security-conscious design, particularly for a dotfile management tool handling sensitive configurations. Strengths include use of established cryptographic libraries (age, Azure Key Vault, AWS Secrets Manager) and proper security documentation. However, there are areas of concern: (1) complexity of multiple cryptographic backends increases configuration risk
- Medium · Outdated Go Version —
go.mod (go 1.25.7). The project specifies Go 1.25.7, which may contain unpatched security vulnerabilities. Go versions should be kept current with the latest stable releases to ensure all security patches are applied. Fix: Update to the latest stable Go version. Verify that 1.25.7 is the current stable release or upgrade to a newer version if available. - Medium · Potential Cryptographic Library Risks —
go.mod (filippo.io/age, Azure SDK, AWS SDK, github.com/Shopify/ejson). The project uses multiple cryptographic libraries (filippo.io/age, Azure Key Vault, AWS Secrets Manager, Shopify/ejson). While these are reputable, the complexity of managing multiple encryption backends increases the surface area for misconfiguration or improper key handling. Fix: Conduct a thorough security review of cryptographic implementation. Ensure proper key storage, rotation policies, and access controls. Verify that secrets are never logged or exposed in debug output. - Medium · Third-Party Dependency Risk - Sprig Template Functions —
go.mod (github.com/Masterminds/sprig/v3). The project uses Masterminds/sprig/v3 for template functions. Template injection vulnerabilities are a known risk class. If user input is passed to templates without proper sanitization, this could allow arbitrary code execution. Fix: Audit all template usage to ensure user input is properly escaped and validated. Use template sandbox/safety mechanisms where possible. Consider using a restricted template engine if handling untrusted input. - Low · Multiple Package Management Systems Supported —
go.mod (Azure SDK, AWS SDK, gopasspw/gopass). The project integrates with multiple external package managers and secrets systems (Azure Key Vault, AWS Secrets Manager, gopass). Each integration introduces potential security risks through API calls and credential handling. Fix: Document security considerations for each supported system. Ensure proper credential isolation, minimal permission scopes, and audit logging. Provide user guidance on secure configuration. - Low · Git Integration Risk —
go.mod (github.com/go-git/go-git/v5). The project uses go-git/go-git/v5 for Git operations. Git operations can expose sensitive information if not handled carefully, including credentials in URLs or sensitive file paths. Fix: Ensure git credentials are not logged or exposed in output. Use SSH keys with proper access controls instead of embedded credentials. Validate git repository URLs before use. - Low · HTTP Caching Implementation —
go.mod (github.com/gregjones/httpcache). The project includes gregjones/httpcache (appears to be truncated version without specific version). HTTP caching could inadvertently cache sensitive responses containing authentication tokens or secrets. Fix: Ensure HTTP responses containing sensitive data are marked with appropriate Cache-Control headers. Implement cache key validation to prevent cross-user cache contamination. - Low · Lack of Visible Input Validation —
assets/chezmoi.io/docs/reference/commands/ (multiple command files). Based on file structure showing multiple command implementations and template support, input validation patterns are not visible in static analysis. This could indicate inconsistent or missing validation. Fix: Implement consistent input validation across all command handlers. Use allowlists for file paths and command arguments. Reject unexpected input types and report validation errors clearly. - Low · Development Tools Security —
go.mod (tool directive section). The go.mod includes several development/build tools (capslock, goversioninfo, actionlint, etc.). These tools may have different security standards than production code and could be vectors for supply chain attacks. Fix: Regularly audit development tool dependencies. Use pinned versions and verify checksums. Consider using a separate build environment with restricted access for compilation.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.