Personal configuration files managed with chezmoi.
| Category | What | Highlights |
|---|---|---|
| Claude Code | Settings, 17 subagents, 17 global skills | Opus default, auto-permissions, desktop notifications, repo PII scrubbing (scrub-repo) |
| Zsh | Zim framework, autosuggestions, syntax highlighting | Fish-like experience with history substring search |
| Git | GPG signing, per-machine email | DCO sign-off ready, work email auto-set for configured org repos |
| iTerm2 | Catppuccin Mocha, MesloLGS Nerd Font | True color, auto-installed profile, 14pt font |
| Tmux | Catppuccin theme, easy splits, Claude Code agent teams | Alt+arrow pane nav, top status bar, vi copy mode |
| macOS | Developer defaults | Fast key repeat, Finder tweaks, Dock auto-hide, no smart quotes |
Install these before running the setup:
| Tool | Install | Purpose |
|---|---|---|
| Homebrew | brew.sh | macOS package manager |
| Git | brew install git |
Version control |
| GPG | brew install gnupg |
Commit signing (configure your own key) |
| Claude Code | claude.ai/code | AI coding assistant CLI |
| Node.js | brew install nvm && nvm install --lts |
JavaScript runtime |
| Tmux | brew install tmux |
Terminal multiplexer |
Optional (installed automatically by configs if missing):
- iTerm2 - Installed automatically on first
chezmoi applywith Catppuccin Mocha profile - MesloLGS Nerd Font - Installed automatically with iTerm2 setup
- Zim - Installed automatically by
.zshrcon first shell launch - chezmoi - Can self-install during setup (see below)
- git-filter-repo -
brew install git-filter-repo. Used by thescrub-reposkill and the~/.claude/scripts/scrub-pii-history.shrecovery procedure (see MIGRATION.md). Skip if you do not plan to scrub any repo's history.
These are not required to use the dotfiles, but the dotfiles ship support for them:
claude-token-analyzer is a third-party Claude Code plugin that audits token usage across your sessions. Its skills default to 繁體中文 output; the dotfiles ship English-translated skill patches at ~/.claude/cta-english-patch/.
Install order matters:
-
Install the plugin first - inside any Claude Code session, run:
/plugin marketplace add li195111/claude-token-analyzer /plugin install claude-token-analyzer@claude-token-analyzer -
Apply English skill patches (from terminal, after the plugin is installed):
~/.claude/cta-english-patch/apply.sh -
Re-apply after every
/plugin update. The script is idempotent and warns if upstream version drifts from the pinned translation target. See~/.claude/cta-english-patch/README.mdfor details.
If you skip step 2, the plugin works but reports are in 繁體中文.
Clone the repo to wherever you keep your repos, then run the setup script from inside it:
cd /path/to/cloned/dotfiles
./setup.shsetup.sh will:
- Create a symlink from
~/.local/share/chezmoito your cloned repo so chezmoi can find it - Install chezmoi if it is not already installed
- Run
chezmoi init- prompts you to select personal or work machine (controls default git email) - Show a diff of any conflicts between the repo and your existing dotfiles
- Prompt you to apply, merge interactively, or exit to resolve manually
- Run
run_once_macos-defaults.shautomatically (once, on first apply)
If you already have dotfiles on this machine, choose merge at the prompt. This opens a 3-way merge for each conflicting file so you can pick which parts to keep. After resolving, chezmoi apply is called automatically.
If you skip the prompt, you can resolve conflicts manually at any time:
chezmoi diff # review what would change
chezmoi merge-all # merge conflicts interactively file by file
chezmoi apply # apply after resolvingAfter setup, open a new terminal or run source ~/.zshrc to load Zim modules. Then follow the daily workflow below.
chezmoi applyis a one-time deploy step. Do not run it again on a machine where you are actively editing dotfiles - it overwrites local changes with no undo.
chezmoi uses a copy model: source files in this repo are copied to their target locations in ~. This means edits to ~/.zshrc, ~/.claude/CLAUDE.md, etc. are not automatically reflected in the repo - you have to push them back.
The correct direction on your main machine is local -> repo:
# 1. Edit the local file as usual (e.g. ~/.claude/CLAUDE.md, ~/.zshrc)
# 2. Commit and push from the dotfiles repo
# The pre-push hook runs `chezmoi re-add` automatically before pushing,
# syncing all modified local files to source so nothing is lost.
cd ~/repos/github.com/<your-username>/dotfiles
git add -p
git commit -S -s -m "your message"
git push
# Pull updates from GitHub (only updates source, does not touch local files)
git pullIf you want to check or sync manually at any point:
chezmoi status # see which local files differ from source
chezmoi re-add # sync all local changes to source
chezmoi diff # see what source differs from local (should be empty after re-add)If you edit files directly in the repo (not in
~/), runchezmoi applybefore committing and pushing. The pre-push hook runschezmoi re-addwhich syncs from local -> repo. If local files are stale, it will overwrite your repo changes. Always apply first so both sides match.
| Agent | Model | Purpose |
|---|---|---|
code-reviewer |
inherit | Read-only code review |
researcher |
inherit | Deep research with citations |
debugger |
inherit | Systematic bug tracing |
writer |
inherit | Technical documentation |
security-auditor |
inherit | General security audit, threat modeling, OWASP |
blockchain-security-auditor |
inherit | Adversarial Solidity audit, DeFi exploit analysis |
solidity-engineer |
inherit | Smart contracts (EVM) |
dev-advocate |
inherit | Tutorials, demos, talks |
architect |
inherit | System design, ADRs |
frontend-developer |
inherit | React/Vue/Angular, UI, accessibility, performance |
backend-architect |
inherit | API design, scalability, server-side architecture |
ai-engineer |
inherit | ML models, LLM integration, RAG, embeddings |
devops-automator |
inherit | CI/CD, Docker, Kubernetes, GitHub Actions |
database-optimizer |
inherit | Schema design, query performance, indexing |
mcp-builder |
inherit | MCP server design and implementation |
accessibility-auditor |
inherit | WCAG compliance, ARIA, screen readers |
api-tester |
inherit | API validation, endpoint testing, OWASP API Security |
/review-pr <number>- Structured PR review/debug <error>- Systematic debugging/quick-research <topic>- Fast research brief/meta-stack-eval [path]- Report-only audit of meta-stack token-efficiency + context-overload resilience (a free Tier-0 drift advisory also runs at session start)
- Autosuggestions - Fish-like suggestions as you type (right arrow to accept)
- Syntax highlighting - Valid commands in green, invalid in red
- History substring search - Type partial command, up arrow to search history
- Smart completions - Tab completion with descriptions
- Git aliases -
gst,gco,gcm, etc.
Catppuccin Mocha-inspired theme with a top status bar. No plugin manager needed.
Key bindings (cheat sheet):
| Action | Keys |
|---|---|
| Split horizontal | `Ctrl-b |
| Split vertical | Ctrl-b - |
| Navigate panes | Alt + arrow (no prefix) |
| Resize panes | Ctrl-b + arrow |
| Switch windows | Shift + left/right (no prefix) |
| New window | Ctrl-b c |
| Reload config | Ctrl-b r |
| Copy mode | Ctrl-b [ then v to select, y to copy |
Session management:
tmux new -s work # create named session
tmux a -t work # reattach to it later
tmux ls # list all sessionsDetach with Ctrl-b d — the session keeps running in the background.
Claude Code + tmux: Start tmux first (tmux new -s claude), then run claude. When Claude spawns agent teams, they automatically get their own tmux panes. The teammateMode defaults to auto - it detects tmux and uses split panes.
Copying text in Claude Code: Press Ctrl-b [ to enter copy mode, then click-drag to select text. It auto-copies to clipboard on release.
The run_once_macos-defaults.sh script runs automatically on first chezmoi apply. It sets:
- Fast keyboard repeat, no press-and-hold
- No smart quotes/dashes/autocorrect (breaks code)
- Finder: show extensions, path bar, list view, search current folder
- Dock: auto-hide, no animation delay, no recent apps
- Screenshots: PNG, no shadow
- Auto software updates
To re-run: chezmoi state delete-bucket --bucket=scriptState && chezmoi apply
~/.claude/scripts/backup-claude.sh (chezmoi-managed) does an incremental backup of your whole Claude Code environment (skills, agents, commands, settings, CLAUDE.md, friction-log, auto-memory under projects/, and plugin config) to ~/Dropbox/dot_claude, so a new machine can restore the same Claude brain. It uses rsync (not cp) so only deltas transfer and deletions mirror; the EXCLUDES array at the top skips regenerable bulk (the security/agent-sdk-venv Python venv, plugin cache, per-session ephemera) — edit it to taste.
Only the script is dotfiles-managed. Scheduling and the backup destination are deliberately not — not every machine has Dropbox, and a daily timer is a per-machine choice. Run it by hand whenever you like:
~/.claude/scripts/backup-claude.sh # writes a log to ~/.claude/backups/backup-claude.logIf this machine has Dropbox and you want an unattended daily backup, create a LaunchAgent yourself:
cat > ~/Library/LaunchAgents/local.claude-backup.plist <<EOF
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"><dict>
<key>Label</key><string>local.claude-backup</string>
<key>ProgramArguments</key>
<array><string>/bin/bash</string><string>${HOME}/.claude/scripts/backup-claude.sh</string></array>
<key>StartCalendarInterval</key><dict><key>Hour</key><integer>12</integer><key>Minute</key><integer>30</integer></dict>
<key>StandardOutPath</key><string>${HOME}/.claude/backups/launchd.out.log</string>
<key>StandardErrorPath</key><string>${HOME}/.claude/backups/launchd.err.log</string>
</dict></plist>
EOF
launchctl bootstrap "gui/$(id -u)" ~/Library/LaunchAgents/local.claude-backup.plistRuns daily at 12:30 (launchd runs a missed job on the next wake, unlike cron). To remove it later: launchctl bootout "gui/$(id -u)/local.claude-backup" && rm ~/Library/LaunchAgents/local.claude-backup.plist.
Full Disk Access is required for the scheduled run. Modern Dropbox lives under ~/Library/CloudStorage/Dropbox (the ~/Dropbox symlink points there). macOS TCC blocks background/launchd processes from writing there, even though your interactive terminal can — so the scheduled job fails with Operation not permitted until you grant access:
System Settings → Privacy & Security → Full Disk Access → + → ⌘⇧G →
/bin/bash→ Add → toggle on.
(TCC attributes the access to the LaunchAgent's executable — /bin/bash — not to rsync. Granting FDA to /bin/bash is broad; if you'd rather not, just run the script manually, which inherits the terminal's existing grant.) Verify: launchctl kickstart -k "gui/$(id -u)/local.claude-backup" && sleep 5 && tail ~/.claude/backups/backup-claude.log — expect result: OK.
rsync -ah ~/Dropbox/dot_claude/ ~/.claude/ # note trailing slashes (no nesting)
claude login # OAuth token lives in the Keychain, NOT the backupPlugins (marketplaces + config) come back with the files; the security venv rebuilds itself on first use. The OAuth token is intentionally absent from the backup (it lives in the macOS Keychain under Claude Code-credentials), so the backup carries no auth secret to Dropbox.
This repo holds no PII. Personal data (your name, emails, GPG key, GitHub username, work GitHub orgs) lives in a single file outside the repo: ~/.config/devkit/identity.json. All templated configs (gitconfig and friends) read from it at apply time.
Schema (see devkit-identity.example.json at repo root for the canonical example):
{
"full_name": "Your Name",
"email_personal": "you@example.com",
"email_work": "",
"github_username": "your-gh-username",
"gpg_signing_key": "",
"work_gh_orgs": ["org-1", "org-2"]
}Required fields: full_name, email_personal, github_username. Others are optional.
Three ways to create the file:
- chezmoi prompts (default). On first
chezmoi applythe run-once bootstrap script prompts for each field and writes the JSON. Edit the file later to change values. - Interactive script (no chezmoi): run
~/.claude/scripts/setup-identity.shafter the dotfilessetup.shcompletes. Same prompts, no chezmoi dependency. - Copy and edit:
cp devkit-identity.example.json ~/.config/devkit/identity.jsonand edit by hand.
After any edit to ~/.config/devkit/identity.json, run chezmoi apply to regenerate gitconfig and other dependent files.
A second devkit file, ~/.config/devkit/references.json, holds pointers to external systems your tooling integrates with — MCP server URLs, dashboards, etc. Anything that contains a secret (e.g. an access key embedded in a URL) belongs here, not in committed dotfiles.
Schema (see devkit-references.example.json at repo root):
{
"open_brain_mcp_url": ""
}All fields optional. Today the file is consumed by:
run_install-claude-mcps.sh— readsopen_brain_mcp_urlto register the persistent-memory MCP.
If you add a new external integration that needs a secret URL or token, add a key here rather than introducing a new env var. Setup:
cp devkit-references.example.json ~/.config/devkit/references.json
chmod 600 ~/.config/devkit/references.json
$EDITOR ~/.config/devkit/references.jsoncross-agent-review (global skill) reads its reviewer panel from a machine-local file:
~/.config/cross-agent-review/config.json (gitignored, per-machine)
This path is a convention (like ~/.gitconfig), shared by schema only — no repo depends on
another. On first chezmoi apply, run_once_before_bootstrap-cross-agent-review.sh seeds it from
cross-agent-review-config.example.json if absent. If the file is missing entirely, the skill
falls back to a built-in Claude-only default, so a fresh or offline machine still works.
Schema:
| Field | Meaning |
|---|---|
defaults.timeout_seconds |
Per-model timeout default (overridable per model). |
defaults.claude_subagent_count |
Reviewer subagents in Claude-only mode. |
models[].id |
Model identifier (claude is always present + always the orchestrator). |
models[].mode |
subagent (in-process Claude reviewers) or cli (external process). |
models[].enabled |
Toggle into/out of the panel without deleting the entry. |
models[].count + lenses |
(subagent) reviewer count + review lenses (round-robin). |
models[].command + lens + timeout_seconds |
(cli) command template ({prompt} placeholder, else stdin), focus lens, timeout. |
With ≥2 models enabled the skill runs a multi-model panel; with only claude enabled (default) it
runs Claude-only multi-subagent review. Preflight with
~/.claude/scripts/cross-agent-review-config.sh --doctor to see which configured CLIs are reachable.
Running the helper tests: the bash helpers ship self-contained test harnesses under dot_claude/scripts/tests/ (only jq/awk needed — no bats). Each resolves its helper in either layout, so it runs from the dotfiles repo OR from the deployed ~/.claude/scripts/tests/ copy:
bash dot_claude/scripts/tests/test-cross-agent-review-config.sh # expect: PASS=33 FAIL=0
bash dot_claude/scripts/tests/test-meta-stack-eval.sh # expect: PASS=48 FAIL=0chezmoi init prompts for a machine type (personal or work) and stores it in ~/.config/chezmoi/chezmoi.toml. This drives:
- Default git email -
email_personalon personal machines,email_workon work machines (both pulled from~/.config/devkit/identity.json) - includeIf directives - On personal machines, repos under any org listed in
work_gh_orgsuse the work email; on work machines, repos under<github_username>/use the personal email
To change the machine type later, edit ~/.config/chezmoi/chezmoi.toml and re-run chezmoi apply.
Local extensions (gitignored, machine-specific):
~/.config/devkit/identity.json- your identity (lives outside any repo)~/.config/devkit/references.json- external system URLs/secrets (lives outside any repo)~/.config/chezmoi/chezmoi.toml- machine type~/.claude/scopes/<name>.local.txt- private repo paths for cross-project audit skills~/.claude/projects/- auto-memory (machine-specific paths)~/.claude/target-repo/- cross-repo working-mode bindings (UUID-keyed, per-session)~/.zim/- Zim modules (installed per-machine)
Cross-machine Claude config: ~/.claude/settings.local.json is now chezmoi-managed (sourced from dot_claude/settings.local.json). Permissions, hooks, model defaults, etc. flow across personal + work machines. Work-machine-specific things (MCPs only on personal, paths with personal username) are deliberately excluded from the baseline. A pre-commit PII scan protects against accidental PII propagation when Claude Code adds permissions interactively.
A small two-file bundle gives every publishable repo the same PII protection without coupling the repos to each other or to this dotfiles repo. Self-contained: the bundle lives inside each repo and survives clones, forks, and machines without the dotfiles installed.
Canonical source (this dotfiles repo):
dot_claude/scripts/executable_pii-scan.sh— the scanner (chezmoi-managed to~/.claude/scripts/pii-scan.sh)dot_claude/scripts/pii-patterns.conf— generic structural patterns
The scanner is self-locating — it prefers a pii-patterns.conf next to it, so it works both at ~/.claude/scripts/ (dotfiles-managed) AND when bundled inside another repo at .githooks/.
Per-repo install pattern (used today by idea-forge, engram, team-digest, and this dotfiles repo):
- Bundle the scanner + patterns into
.githooks/:cp ~/.claude/scripts/pii-scan.sh .githooks/pii-scan.sh cp ~/.claude/scripts/pii-patterns.conf .githooks/pii-patterns.conf chmod +x .githooks/pii-scan.sh
- Hook installation depends on the repo's existing setup:
- No pre-commit framework (
idea-forge,team-digest): copy the bundled.githooks/pre-committemplate into.git/hooks/pre-commit:cp .githooks/pre-commit .git/hooks/pre-commit chmod +x .git/hooks/pre-commit
- pre-commit framework (
engram): add alocalhook to.pre-commit-config.yaml:Then- repo: local hooks: - id: pii-scan name: PII scan entry: bash -c 'SCANNER="$(git rev-parse --show-toplevel)/.githooks/pii-scan.sh"; if [ -x "$SCANNER" ]; then "$SCANNER" --staged; fi' language: system pass_filenames: false
uv run pre-commit install(or equivalent).
- No pre-commit framework (
Identity-specific patterns load dynamically from ~/.config/devkit/identity.json if present — real name, personal/work emails, GitHub username get added as literal regexes at scan time. This keeps repo-bundled pii-patterns.conf files publishable (no real PII committed). Forker machines without identity.json get only the structural patterns; still useful, just less specific.
Pattern update propagation: when dot_claude/scripts/pii-patterns.conf changes, re-copy it into each repo's .githooks/ and commit. No automatic propagation today — the design favors per-repo independence over centralized sync.
Per-line allow markers: lines containing the string pii-allow are skipped by the scanner. Use this to mark legitimate meta-discussion of PII patterns (e.g., in PII-discipline docs themselves) or attribution metadata. Markdown convention: <!-- pii-allow:meta --> at end of line; shell convention: # pii-allow:meta.
The committed dotfiles repo is intentionally standalone — no skill in dot_claude/skills/ requires you to also clone another repo (project workspace, persistent-memory recipe repo, etc.) for it to work. Skill prose uses generic terms like "your meta-stack repo" / "your persistent-memory MCP" / "your project workspace"; if you have those, the references are meaningful, otherwise just ignore them.
If you maintain personal skills that structurally couple to a separate repo (e.g. a skill whose entire purpose is the maintainer-side of a 2-repo workflow with a paired data-layer recipe in another repo), the recommended pattern is to keep them outside chezmoi management on each machine:
# Move the skill out of chezmoi management without deleting the live files:
chezmoi forget --force ~/.claude/<your-private-skill>
# Live files at ~/.claude/<your-private-skill>/ remain functional.
# Sync them across machines via your own private mechanism (e.g. a private
# dotfiles-personal git repo, rsync, etc.) — whatever fits your threat model.Why outside chezmoi: a public dotfiles fork shouldn't ship references to your private companion repos. The chezmoi forget pattern keeps the personal skill working on your machine without leaking into the public source.
setup.sh Bootstrap script for new machines
.chezmoi.toml.tmpl Chezmoi config template (prompts for machine type)
dot_claude/ -> ~/.claude/
agents/ -> ~/.claude/agents/
skills/ -> ~/.claude/skills/
rules/ -> ~/.claude/rules/
scripts/ -> ~/.claude/scripts/ (incl. backup-claude.sh)
settings.local.json -> ~/.claude/settings.local.json
CLAUDE.md -> ~/.claude/CLAUDE.md
devkit-identity.example.json Schema example for ~/.config/devkit/identity.json
devkit-references.example.json Schema example for ~/.config/devkit/references.json (external URLs/secrets)
dot_gitconfig.tmpl -> ~/.gitconfig (rendered from identity.json)
dot_gitconfig-work.tmpl -> ~/.gitconfig-work (work email from identity.json)
dot_gitconfig-personal.tmpl -> ~/.gitconfig-personal (personal email from identity.json)
run_once_before_bootstrap-identity.sh.tmpl First-apply hook: prompts for identity values
dot_tmux.conf -> ~/.tmux.conf
dot_zshrc -> ~/.zshrc
dot_zsh_profile -> ~/.zsh_profile
dot_zimrc -> ~/.zimrc
iterm2/ iTerm2 exported preferences (Catppuccin Mocha + Nerd Font)
run_once_macos-defaults.sh Runs once on first chezmoi apply
run_once_setup-iterm2.sh Installs iTerm2, Nerd Font, and Catppuccin profile
run_once_install-chezmoi-hooks.sh Installs pre-push hook on first apply
ISC