# 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`](https://www.chezmoi.io) (`brew install chezmoi`) - [`age`](https://github.com/FiloSottile/age) for secret encryption (`brew install age`) - [`duckdb`](https://duckdb.org/) 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`](docs/setup-new-fleet.md). The short version: ```bash # 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:////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`](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: ```bash 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/](https://gitea.tojo.team/cardinale/task-durations/src/branch/main/docs/fleet-architecture.md). ## References The plumbing this template builds on: - **[chezmoi](https://www.chezmoi.io)** — dotfile manager. Source: [twpayne/chezmoi](https://github.com/twpayne/chezmoi). Reference docs: [reference](https://www.chezmoi.io/reference/), [quick start](https://www.chezmoi.io/quick-start/), [user guide](https://www.chezmoi.io/user-guide/command-overview/). - **[age](https://github.com/FiloSottile/age)** — file encryption used for the secrets file and SSH keys in the chezmoi source. - **[DuckDB](https://duckdb.org/)** — analytics engine for the optional task-durations feature ([Hive partitioning docs](https://duckdb.org/docs/stable/data/partitioning/hive_partitioning)). - **[launchd](https://www.launchd.info/)** — macOS service manager that runs the watcher + puller + pull-fleet jobs. Apple's reference: [launchd.plist(5)](https://developer.apple.com/library/archive/documentation/MacOSX/Conceptual/BPSystemStartup/Chapters/CreatingLaunchdJobs.html). - **Companion repo:** [task-durations](https://gitea.tojo.team/cardinale/task-durations) — the cross-fleet time estimator referenced from the launchd plist and Stop hook. ## License MIT — see [LICENSE](LICENSE).