Automated dotfiles synchronization for macOS using LaunchAgent and yadm. Your dotfiles are automatically committed and pushed to git whenever they change - zero manual intervention required.
Platform: macOS only (uses LaunchAgent) Git Platform: Any (GitHub, GitLab, Gitea, Bitbucket, self-hosted)
# Install and start auto-sync
./dotfiles-auto-sync install
# Configure which files to backup
edit config/files.conf
# Check status and logs
./dotfiles-auto-sync status
./dotfiles-auto-sync logsPrerequisites:
- macOS with Homebrew installed
- yadm initialized with remote repository configured
- SSH keys set up for git authentication
Dependencies (auto-installed if missing):
yadm- Yet Another Dotfiles ManagerHomebrew- macOS package manager
The installer verifies all requirements and guides you through any missing setup.
A macOS LaunchAgent monitors your dotfiles and triggers automatic syncs via:
- File watching - Runs immediately when watched files change
- Scheduled backup - Daily at 12:00 PM as a safety net
Sync process:
- Fetch and pull from remote (
--rebase) - Stash uncommitted changes if needed
- Add configured dotfiles to yadm
- Commit with timestamp
- Push to remote repository
- Log to
~/Library/Logs/de.sherrill.dotfiles-auto-sync.log
cd dotfiles-auto-sync
./dotfiles-auto-sync installThe installer will:
- Verify or install Homebrew and yadm
- Check yadm initialization and remote configuration
- Validate SSH connectivity
- Install and load the LaunchAgent
- Guide you through any missing configuration
If you need to set up yadm first:
yadm init
yadm remote add origin [email protected]:username/dotfiles.git
yadm add ~/.zshrc ~/.zprofile
yadm commit -m "Initial dotfiles"
yadm push -u origin mainBy default, nothing is backed up. Edit config/files.conf to specify which dotfiles to sync.
The template includes common examples:
- Shell configs:
~/.zshrc,~/.zprofile,~/.bashrc - Terminal configs:
~/.config/starship.toml,~/.config/alacritty/alacritty.yml - Editor configs:
~/.vimrc,~/.config/nvim/init.vim - Git config:
~/.gitconfig
Note: files.conf defines what gets backed up when sync runs. To control what triggers automatic syncs, update WatchPaths in the LaunchAgent plist (see Customization).
dotfiles-auto-sync install # Install and configure auto-sync
dotfiles-auto-sync sync # Manually trigger sync
dotfiles-auto-sync status # Check LaunchAgent status
dotfiles-auto-sync logs # View sync logs
dotfiles-auto-sync uninstall # Remove auto-sync system
dotfiles-auto-sync help # Show help
dotfiles-auto-sync version # Show versionCheck status:
./dotfiles-auto-sync status
# Or: launchctl list | grep de.sherrill.dotfiles-auto-syncView logs:
./dotfiles-auto-sync logs
# Or: tail -f ~/Library/Logs/de.sherrill.dotfiles-auto-sync.logUpdate both locations to enable immediate syncing:
-
LaunchAgent WatchPaths - Edit
~/Library/LaunchAgents/de.sherrill.dotfiles-auto-sync.plist:<key>WatchPaths</key> <array> <string>/Users/yourname/.zshrc</string> <string>/Users/yourname/.zprofile</string> <!-- Add more paths --> </array>
-
files.conf - Edit
dotfiles-auto-sync/config/files.confwith same files -
Reload LaunchAgent:
launchctl unload ~/Library/LaunchAgents/de.sherrill.dotfiles-auto-sync.plist launchctl load ~/Library/LaunchAgents/de.sherrill.dotfiles-auto-sync.plist
Why both? WatchPaths triggers the sync on file changes, files.conf defines what gets backed up. Without both, files only sync on the daily schedule.
Default: Daily at 12:00 PM (noon)
Edit ~/Library/LaunchAgents/de.sherrill.dotfiles-auto-sync.plist:
<!-- Every 6 hours -->
<key>StartInterval</key>
<integer>21600</integer>
<!-- Or specific times (8 AM, 12 PM, 6 PM) -->
<key>StartCalendarInterval</key>
<array>
<dict>
<key>Hour</key>
<integer>8</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
<dict>
<key>Hour</key>
<integer>12</integer>
<key>Minute</key>
<integer>0</integer>
</dict>
</array>Reload LaunchAgent after changes (see above).
LaunchAgent not triggering:
- Verify loaded:
./dotfiles-auto-sync status - Check permissions:
ls -l dotfiles-auto-sync(must be executable) - Review system logs:
log show --predicate 'subsystem == "com.apple.launchd"' --last 1h
Failed to push to remote:
- Verify remote:
yadm remote -v - Test manual push:
yadm push - Check SSH authentication
Merge conflicts:
The sync script automatically stashes local changes before pulling. Conflicts are logged and can be resolved manually with yadm.
CLI Design:
- Single entry point:
dotfiles-auto-sync(no extension) - Subcommand pattern for clear intent
- Implementation located in
lib/directory - Dependency verification at startup
- Colored logging with status symbols
Project Structure:
dotfiles-auto-sync/
├── dotfiles-auto-sync # Main entry point
├── lib/ # Core implementation
│ ├── logger.sh, deps.sh, backup-core.sh
│ ├── install-core.sh, uninstall-core.sh
├── config/
│ └── de.sherrill.dotfiles-auto-sync.plist.template
└── README.md
Template System: LaunchAgent plist uses placeholders ({{HOME}}, {{DOTFILES_BACKUP_PATH}}) dynamically replaced during installation for portability.
- yadm documentation
- LaunchAgent documentation
- LaunchControl - GUI for managing LaunchAgents
This project was developed with assistance from Claude Code. All code and implementation decisions have been reviewed and verified by the author.
