← Biblioteca 📦 Repo · 12 min Ver en GitHub ↗

chezmoi: cómo gestionar tus dotfiles en N máquinas como si fueran una sola

Un motor declarativo "source state → target state → apply" que trata tu home directory como infraestructura versionada, plantillada y cifrada.

dev-toolsdotfilesopen-sourceproductividadtwpayne/chezmoi
🎧 Escuchar Voz Álvaro (Edge TTS). Si el audio no carga, todavía no está generado.

⚡ En 30 segundos

chezmoi (de twpayne, escrito en Go, MIT) gestiona tus dotfiles.bashrc, .gitconfig, claves SSH…— a través de varias máquinas distintas y de forma segura. Guardas una sola copia versionada en git (el source state), y chezmoi calcula y aplica los ficheros reales en cada máquina (el target state), resolviendo las diferencias por host con plantillas Go y guardando los secretos cifrados.

Por qué importa: no es un repo de IA-agentes, pero es un caso de estudio precioso de motor declarativo de reconciliación de estado (el mismo patrón que Terraform o Kubernetes, aplicado a tu home). El diseño —System componible, estado en SHA256, atributos codificados en el nombre del fichero— es directamente robable para cualquier herramienta que tenga que "llevar un sistema de un estado A a un estado deseado B".

Para quién: cualquiera con >1 portátil/servidor; y para ti, Raúl, como plantilla mental de arquitectura idempotente que reusar en tus micro-SaaS.

54
subcomandos chezmoi documentados
Go
lenguaje único del core
4
estados clave: source / target / actual / persistent
SHA256
huella guardada (no el contenido) → no filtra secretos
4 SO
CI en Linux, macOS, Windows, FreeBSD
MIT
licencia

🧠 El problema que resuelve

Tienes un portátil personal, uno del trabajo y un par de servidores. Quieres el mismo .zshrc en todos… pero no exactamente el mismo: tu email de git cambia entre personal y trabajo, en el server no quieres tu config de GUI, y tu clave SSH privada no puede acabar en texto plano en un repo público de GitHub.

Las soluciones caseras (un repo de dotfiles + symlinks con stow, o un script de bash) se rompen justo en esos tres puntos: variación por máquina, secretos y idempotencia (volver a correr el script sin romper nada ni preguntar dos veces). chezmoi resuelve los tres como ciudadanos de primera clase:

La idea central, citando el doc de arquitectura: "chezmoi evalúa el source state para computar un target state del destino, lo compara con el estado real y aplica los cambios necesarios". Es Terraform para tu $HOME.

🏗 Arquitectura

SOURCE STATE ~/.local/share/ chezmoi (git) dot_bashrc.tmpl … TARGET STATE (deseado, calculado) plantilla ejecutada + descifrado ACTUAL STATE ~/.bashrc real en disco compute DIFF + APPLY delta mínimo target vs actual lee actual escribe delta PERSISTENT STATE boltdb: map[Bucket]map[Key]Value SHA256 por entry · scripts run_once ¿lo tocó un tercero?

Lectura del diagrama: el source state (tu repo git) se transforma en el target state ejecutando plantillas y descifrando. chezmoi lee el actual state (lo que hay en disco), calcula el delta mínimo y solo escribe lo que difiere (no reescribe ficheros idénticos). El persistent state guarda el SHA256 de cada entry escrito: así detecta si un tercero modificó un fichero desde la última vez (y avisa antes de pisarlo), y decide si re-ejecutar los scripts run_once_ / run_onchange_.

🔑 Conceptos / técnicas clave

Los 4 estadossource (lo que versionas), target (lo deseado, calculado), actual (lo que hay en disco) y persistent (memoria de chezmoi). Cada uno es una interfaz Go: SourceStateEntry, TargetStateEntry, ActualStateEntry, PersistentState. Entender estos cuatro = entender el 80% del repo.
Atributos en el nombre del fichero — chezmoi no usa metadata externa: codifica los permisos y el comportamiento como prefijos/sufijos del nombre. dot_bashrc.bashrc; private_ quita permisos de grupo/mundo; executable_ pone el bit +x; encrypted_ está cifrado; .tmpl es plantilla; exact_ en un dir borra lo no declarado. Parseados por FileAttr / DirAttr. Truco elegante: el sistema de ficheros es la base de datos.
System componible (decorator pattern) — toda interacción con el SO pasa por la interfaz System. El real es RealSystem; --dry-run lo envuelve en DryRunSystem (lee de verdad, descarta escrituras); --debug lo envuelve en DebugSystem (loguea cada llamada). Añadir un modo nuevo = un wrapper nuevo, cero cambios en el core. Patrón clave a robar.
Plantillas Go por máquina — un fichero .tmpl se ejecuta con datos del host (.chezmoi.os, hostname, variables de config). Así un único dot_gitconfig.tmpl rinde tu email personal en un host y el del trabajo en otro. chezmoi execute-template y chezmoi data sirven para depurarlas.
Scripts run_ idempotentes — ficheros con prefijo run_ se ejecutan en cada apply. run_once_ solo si su SHA256 no se ha visto antes (instalación inicial). run_onchange_ solo si su contenido cambió (re-aplicar al editar). Modificadores before_/after_ controlan el orden. El registro vive en el bucket scriptState/entryState del estado persistente.
Cifrado abstraído — interfaz Encryption con dos implementaciones, AGEEncryption y GPGEncryption (y un DebugEncryption que loguea). Como el estado persistente solo guarda hashes SHA256 y no contenidos, los secretos nunca tocan la DB de chezmoi.
Tipos de path separadosAbsPath vs RelPath vs SourceRelPath vs ExtPath son tipos Go distintos, así el compilador impide bugs como unir dos paths absolutos. Todo se normaliza a forward-slashes internamente. Disciplina de tipos que evita una clase entera de errores cross-platform.

Comandos que de verdad usas a diario

ComandoQué hace
chezmoi init $USERClona tu repo de dotfiles de GitHub al source dir (con --apply lo aplica de una). El "bootstrap de máquina nueva".
chezmoi add $FILEMete un fichero de tu home al source state (con --template lo añade como plantilla).
chezmoi edit $FILEAbre el editor sobre la versión source del fichero (--apply lo aplica al guardar).
chezmoi diffMuestra el delta que haría apply, sin tocar nada.
chezmoi statusResumen rápido de qué cambiaría.
chezmoi applyReconcilia: pone tu home igual al target state.
chezmoi updategit pull del remoto + apply. El "sincroniza esta máquina".
chezmoi doctorDiagnostica problemas comunes. Lo primero a correr si algo va raro.
chezmoi execute-templateEjecuta una plantilla suelta para testear/depurar.
chezmoi managed / unmanagedLista qué controla (o no controla) chezmoi.

🗂 Mapa de ficheros importantes

RutaPara qué sirve
internal/chezmoi/El core. Aquí viven System, SourceState, los *StateEntry, Encryption, el persistent state y el manejo de paths. Si quieres entender el motor, empieza aquí.
internal/cmd/*cmd.goUn fichero por subcomando (applycmd.go, addcmd.go…). Los comandos son métodos del struct Config, que centraliza toda la configuración.
internal/cmd/*templatefuncs.goFunciones de plantilla disponibles dentro de los .tmpl.
internal/cmd/testdata/scripts/*.txtarTests end-to-end con testscript: cada .txtar es un guion ejecutable que monta un FS falso y verifica comandos reales. Oro para ver comportamiento esperado sin leer código.
assets/chezmoi.io/docs/Única fuente de verdad de la documentación: la web chezmoi.io, el help y los ejemplos se generan de aquí. 91 de los ficheros del repo son .md.
assets/chezmoi.io/docs/developer-guide/architecture.mdEl doc que resume toda la arquitectura en una página. Léelo si vas a contribuir.
assets/chezmoi.io/docs/reference/target-types.mdLa referencia de TODOS los prefijos de fichero (dot_, private_, run_once_, exact_, symlink_…). Tu chuleta para nombrar ficheros.
.config/goreleaser.yaml · golangci.ymlRelease multiplataforma y linting. Pipeline de un proyecto Go serio.

🎯 Qué puedes aplicar tú

⚠️ Limitaciones / cuándo NO usarlo