5.3 KiB
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. The instructions below are the same flow, written for a human to follow directly.
Prerequisites
brew install chezmoi age duckdb
Reference docs for the moving parts: chezmoi (quick start), 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.
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
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:
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:
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ""
Then add this machine's pubkey to .chezmoidata/fleet.yaml:
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
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:
ls $(chezmoi source-path)/dot_config/private_fleet-dotfiles/
# Expect: encrypted_private_secrets.env.age
7. Apply
chezmoi diff # review changes
chezmoi apply # materialize them
Verify the launchd jobs registered:
launchctl list | grep -E "chezmoi|taskdurations"
# Expect 3 lines: claude-watcher, claude-puller, taskdurations.pull-fleet
If any are missing, run:
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:
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
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.