Anthony Cardinale ebccdda936 Initial public release
A chezmoi-based fleet-dotfiles template for macOS workstations:

- Two-way auto-sync via launchd watcher + 5-min puller
- Mesh SSH via modify_authorized_keys driven by .chezmoidata/fleet.yaml
- age-encrypted secrets file
- Bundled Claude Code agentic team (11 agents) + /lite + /lite-sub commands
- Verify-before-claiming Stop hook
- Generic statusline + project-boundary validate-path hook
- Reference launchd plist for cross-fleet task-durations aggregation
  (companion repo: gitea.tojo.team/cardinale/task-durations)
- AGENTS.md walks an agent through the entire setup Q&A interactively
- docs/ covers architecture, security model, fleet onboarding
2026-05-02 17:26:32 -04:00
2026-05-02 17:26:32 -04:00
2026-05-02 17:26:32 -04:00
2026-05-02 17:26:32 -04:00
2026-05-02 17:26:32 -04:00
2026-05-02 17:26:32 -04:00
2026-05-02 17:26:32 -04:00
2026-05-02 17:26:32 -04:00
2026-05-02 17:26:32 -04:00
2026-05-02 17:26:32 -04:00
2026-05-02 17:26:32 -04:00
2026-05-02 17:26:32 -04:00
2026-05-02 17:26:32 -04:00
2026-05-02 17:26:32 -04:00
2026-05-02 17:26:32 -04:00

fleet-dotfiles-template

A chezmoi-based dotfiles template for syncing Claude Code, shell, git, SSH, and per-machine secrets across a fleet of macOS workstations. Auto-commits any change you make on one machine, propagates it to the others within ~7 minutes, and keeps a unioned view of Claude Code task-duration stats across the whole fleet.

The repo is a template — fork it, replace the example files in examples/ with your own real config, and you have a working fleet sync without writing the plumbing yourself.

What you get

Two-way sync of ~/.claude/, shell, git, SSH config A launchd watcher commits + pushes changes the moment you save; a 5-minute puller applies incoming updates from peers.
Encrypted secrets One file (secrets.env) holds every API token; age-encrypted at rest, decrypted on apply.
Mesh SSH A modify_ script appends every fleet pubkey to each machine's authorized_keys automatically — any machine can SSH any other.
Cross-fleet time estimates Bundled Claude Code Stop hook + pull-fleet.sh produce a Hive-partitioned parquet tree. estimate.sh --fleet queries the union for grounded p50/p90/p99 task durations.
Pre-built Claude Code agents The full 11-agent agentic team (Architect, Builder, Critic, Designer, Explorer, Integrator, Requirements Analyst, Research Scout, Reviewer, Scope Negotiator, Tester) and two slash commands (/lite, /lite-sub).
Verify-before-claiming hook Catches hedging language ("likely", "could be", "might") missing an [unverified] tag and prompts a revision before turn end.

Requirements

  • macOS (the launchd plists are macOS-specific; everything else is portable)
  • chezmoi (brew install chezmoi)
  • age for secret encryption (brew install age)
  • duckdb for task-durations queries (brew install duckdb)
  • Git with SSH key access to your forge (GitHub, Gitea, etc.)

Quickstart

The full walkthrough is in docs/setup-new-fleet.md. The short version:

# 1. Fork this repo on your forge of choice (gitea / github / forgejo)

# 2. On your first machine:
brew install chezmoi age duckdb

# 3. Generate an age keypair (one for the whole fleet — copy to each machine via secure channel):
mkdir -p ~/.config/chezmoi
age-keygen -o ~/.config/chezmoi/key.txt
chmod 600 ~/.config/chezmoi/key.txt
# Copy the public key (printed by age-keygen) — you'll paste it into .chezmoi.toml.tmpl

# 4. Initialize chezmoi from your fork:
chezmoi init https://<your-forge>/<you>/fleet-dotfiles.git

# 5. Edit the rendered .chezmoi.toml to insert your age public key:
chezmoi edit-config

# 6. Replace the placeholder example files with your real config:
chezmoi cd
# ...edit examples/*.example, then move them into the right chezmoi paths...

# 7. Apply:
chezmoi apply

For each subsequent fleet machine, see docs/add-machine.md.

Repo layout

fleet-dotfiles-template/
├── README.md                                              ← this file
├── LICENSE                                                ← MIT
├── docs/
│   ├── architecture.md                                    ← how the watcher / puller / pull-fleet pipeline works
│   ├── security.md                                        ← age encryption boundaries, what gets encrypted vs cleartext
│   ├── setup-new-fleet.md                                 ← bootstrap walkthrough
│   └── add-machine.md                                     ← onboarding subsequent machines
│
├── examples/                                              ← replace these with your real config
│   ├── fleet.yaml.example                                 → .chezmoidata/fleet.yaml
│   ├── secrets.env.example                                → ~/.config/fleet-dotfiles/secrets.env (then `chezmoi add --encrypt`)
│   ├── ssh-config.tmpl.example                            → private_dot_ssh/config.tmpl
│   ├── CLAUDE.md.example                                  → dot_claude/CLAUDE.md
│   ├── zshrc.tmpl.example                                 → dot_zshrc.tmpl
│   └── gitconfig.example                                  → dot_gitconfig
│
├── .chezmoi.toml.tmpl                                     ← stub asking for your age public key
├── .chezmoiexternal.toml                                  ← public skill repos cloned by chezmoi
├── .chezmoiignore
├── .chezmoiversion
│
├── dot_local/bin/executable_chezmoi-auto-sync.sh          ← the watcher script
│
├── private_Library/LaunchAgents/                          ← chezmoi-templated launchd jobs
│   ├── com.chezmoi.claude-watcher.plist.tmpl              ← fires on file change
│   ├── com.chezmoi.claude-puller.plist.tmpl               ← runs every 5 min, pulls updates
│   └── com.taskdurations.pull-fleet.plist.tmpl            ← runs every 5 min, mesh-rsyncs task-durations parquets
│
├── run_onchange_after_reload-launchd-agents.sh.tmpl       ← reloads launchd whenever a plist changes
│
├── private_dot_ssh/
│   └── modify_private_authorized_keys.tmpl                ← appends every fleet pubkey to authorized_keys
│
└── dot_claude/                                            ← Claude Code config
    ├── agents/agentic-team/                               ← 11 specialized agents + shared principles + team.md
    ├── commands/
    │   ├── lite.md                                        ← /lite — Agent Teams parallel scout/explorer/critic/tester
    │   └── lite-sub.md                                    ← /lite-sub — same roles via plain subagents pinned to Opus
    ├── hooks/
    │   ├── executable_verify-before-claiming.py           ← Stop hook flagging unverified hedges
    │   └── executable_validate-path.js                    ← PreToolUse hook enforcing project boundary (uses $PROJECT_PATH)
    └── executable_statusline-command.sh                   ← user@host /path | Model | ctx:N% | rate-limit pacer

Fleet aggregation for time estimates

The bundled task-durations system gives you cross-machine p50/p90/p99 task durations grounded in your real Claude Code transcripts. It's referenced by the ~/.claude/scripts/task-durations/ paths in the watcher script and the launchd plists, but the scripts themselves live in a separate public repo (so they can evolve independently of this template):

Upstream: https://gitea.tojo.team/cardinale/task-durations

To install on a fleet machine:

mkdir -p ~/.claude/scripts
git clone https://gitea.tojo.team/cardinale/task-durations.git ~/.claude/scripts/task-durations
chmod +x ~/.claude/scripts/task-durations/*.{py,sh}
python3 ~/.claude/scripts/task-durations/extract.py     # initial corpus build

Architecture writeup is in task-durations' own docs/.

License

MIT — see LICENSE.

S
Description
Public template for syncing dotfiles, Claude Code config, and encrypted secrets across a fleet of macOS machines via chezmoi + age. Includes mesh SSH, two-way auto-sync, agentic-team agents, /lite + /lite-sub slash commands, and cross-fleet time estimates.
https://www.chezmoi.io Readme MIT 116 KiB
Languages
Shell 55.4%
Python 37.3%
JavaScript 7.3%