About a year ago, while learning Go, I wrote a really simple configuration manager called cm. Things like Chef and Puppet felt too heavy-handed for really simple configuration management; I just wanted a sparse copy of particular paths in
/etc that I could restore from. The idea was that I'd have an repository of these paths that I could push or pull from, like version control.
This turned out to not work well for its intended use. The state of configuration across major distribution versions is far more volatile than I'd expected, with
/etc/programrc often getting modified to a
/etc/program.rc.d/ directory, and other things like carefully curated apt-sources were not at all transferable.
Still, I had this tool which eased the maintenance of arbitrary files. If your repository was on a network mount, it would backup or restore from that mount; if it was under version control, you could restore from history in a simple 2-step process.
cm felt like a classic unix tool that did one simple thing well, and being a single static binary, it was incredibly easy to bootstrap.
I just had no idea what it was good for.
This finally clicked when I got fed up with my system for managing dotfiles. I'd been managing them by making
~/ a mercurial repository. This had a number of drawbacks: bootstrapping it was awkward,
hg st was slow and would show a giant list of unadded files (fixable with
hg st -mard, which I'd never remember),
~/.hgrc was conflicted between my default mercurial settings and my
~/ repo settings, and I was rapidly forgetting how to use mercurial in general.
It struck me that
cm was a perfect solution for this; I could essentially move this repos to
~/dotfiles/ and then push/pull from it using
My dotfiles github repo contains my current system, which also has something of an ad-hoc "universal binary" of
cm for linux 386/86_64 and OSX 64. Even after months of not touching it, it still feels really natural to go and sync between a number of systems.