Files
fleet-dotfiles-template/README.md
T
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

126 lines
7.2 KiB
Markdown

# 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://<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`](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).
## License
MIT — see [LICENSE](LICENSE).