Files
fleet-dotfiles-template/docs/setup-new-fleet.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

162 lines
5.1 KiB
Markdown

# Setup — first machine of a new fleet
If you'd rather have an agent (Claude Code, Codex, etc.) walk you through this interactively, point the agent at this repo and tell it to follow [`AGENTS.md`](../AGENTS.md). The instructions below are the same flow, written for a human to follow directly.
## Prerequisites
```bash
brew install chezmoi age duckdb
```
You need git access to whichever forge you'll host the fleet repo on (gitea, GitHub, forgejo, gitlab — anything chezmoi can clone over HTTPS or SSH).
## 1. Fork this template
Fork `fleet-dotfiles-template` to your forge:
- **Gitea:** `https://gitea.tojo.team/cardinale/fleet-dotfiles-template` → click Fork.
- **GitHub:** if mirrored there, fork it.
- **Other forges:** clone, push to a new repo on your forge.
Name the fork however you want (`my-fleet-dotfiles`, `<your-handle>-dotfiles`, etc.). The rest of this doc assumes you've named it `fleet-dotfiles` on your forge.
## 2. Generate an age keypair (one for the whole fleet)
This keypair encrypts the secrets file. The private key never touches the forge. Every machine in the fleet gets a copy of it via secure side-channel.
```bash
mkdir -p ~/.config/chezmoi
age-keygen -o ~/.config/chezmoi/key.txt
chmod 600 ~/.config/chezmoi/key.txt
```
`age-keygen` prints the public key to stderr and writes it as the first commented line of `key.txt` prefixed with `# public key: `. Capture it — you'll paste it into the chezmoi config in the next step.
## 3. Initialize chezmoi from your fork
```bash
chezmoi init https://<forge>/<you>/fleet-dotfiles.git
```
This clones the fork to `~/.local/share/chezmoi/` and runs the template prompts. When it asks for the age recipient, paste the public key you captured.
If you missed the prompt, run `chezmoi edit-config` and replace `REPLACE_ME_WITH_YOUR_AGE_PUBLIC_KEY` in the rendered config.
## 4. Replace placeholders with your real config
The example files live in `examples/`. Move and edit them into the chezmoi source layout:
```bash
chezmoi cd
# Fleet roster
mv examples/fleet.yaml.example .chezmoidata/fleet.yaml
$EDITOR .chezmoidata/fleet.yaml
# (replace placeholder hostnames, users, pubkeys; for now you only need this machine's pubkey)
# Git identity
mv examples/gitconfig.example dot_gitconfig
$EDITOR dot_gitconfig
# (replace <YOUR_EMAIL> and <YOUR_NAME>)
# SSH config (templated)
mv examples/ssh-config.tmpl.example private_dot_ssh/config.tmpl
$EDITOR private_dot_ssh/config.tmpl
# (replace placeholder hostnames + usernames with your real fleet)
# Shell config (templated)
mv examples/zshrc.tmpl.example dot_zshrc.tmpl
$EDITOR dot_zshrc.tmpl
# (add your own PATH, aliases, completions; keep the secrets.env source line)
# Claude Code top-level instructions
mv examples/CLAUDE.md.example dot_claude/CLAUDE.md
$EDITOR dot_claude/CLAUDE.md
# (add personal sections if you want; the template only carries fleet-relevant ones)
```
## 5. Generate this machine's identity SSH key
If `~/.ssh/id_ed25519` doesn't exist:
```bash
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ""
```
Then add this machine's pubkey to `.chezmoidata/fleet.yaml`:
```bash
PUBKEY=$(cat ~/.ssh/id_ed25519.pub)
echo "Add this to .chezmoidata/fleet.yaml under your machine's entry:"
echo " pubkey: \"$PUBKEY\""
```
## 6. Set up encrypted secrets
```bash
mkdir -p ~/.config/fleet-dotfiles
cp $(chezmoi source-path)/examples/secrets.env.example ~/.config/fleet-dotfiles/secrets.env
chmod 600 ~/.config/fleet-dotfiles/secrets.env
$EDITOR ~/.config/fleet-dotfiles/secrets.env
# (fill in real values for tokens you actually use; delete the rest)
# Encrypt + add to chezmoi source:
chezmoi add --encrypt ~/.config/fleet-dotfiles/secrets.env
```
Verify:
```bash
ls $(chezmoi source-path)/dot_config/private_fleet-dotfiles/
# Expect: encrypted_private_secrets.env.age
```
## 7. Apply
```bash
chezmoi diff # review changes
chezmoi apply # materialize them
```
Verify the launchd jobs registered:
```bash
launchctl list | grep -E "chezmoi|taskdurations"
# Expect 3 lines: claude-watcher, claude-puller, taskdurations.pull-fleet
```
If any are missing, run:
```bash
for plist in ~/Library/LaunchAgents/com.{chezmoi,taskdurations}.*.plist; do
launchctl unload "$plist" 2>/dev/null
launchctl load "$plist"
done
```
## 8. Install task-durations (optional)
If you want fleet-wide time estimates:
```bash
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
```
The Stop hook in your `~/.claude/settings.json` will keep the local corpus fresh; the `com.taskdurations.pull-fleet` launchd job will mesh-rsync peer parquets every 5 minutes.
## 9. Push to your forge
```bash
chezmoi cd
git status # confirm no unencrypted secrets are staged
git add -A
git commit -m "Initial fleet dotfiles for $(hostname -s)"
git push -u origin main
```
You're done. Open the forge URL and confirm the encrypted secrets file is present (`encrypted_private_secrets.env.age`, NOT `secrets.env`).
To onboard the next machine, see [`add-machine.md`](add-machine.md).