One-command setup for a highly opinionated Mac (and, later, Linux) development machine β web (React/Next/Vite) and native (React Native/Expo). It ships a curated stack with the decisions already made; chezmoi is the single orchestrator that installs everything, applies configs, and is safe to re-run on a fresh or existing machine.
- What gets installed: see TOOLS.md (auto-generated from the registry) and SKILLS.md (global agent skills).
- Source of truth:
home/.chezmoidata/registry.tomlβ one block per tool, toggle withenabled = true/false.
On a brand-new Mac with nothing installed (no git, no Homebrew), paste this single line:
sh -c "$(curl -fsSL https://ax-at.github.io/dotfiles/install)"It installs chezmoi if it's missing (a self-contained static binary β no git/brew required), then clones this repo and applies it.
What that one line runs
The URL serves install, which:
- installs chezmoi to
~/.local/binviaget.chezmoi.io(only if not already present), then - runs
chezmoi init --apply ax-atβ chezmoi's built-in git cloneshttps://github.com/ax-at/dotfiles.git(no system git needed) and applies everything.
Prefer to skip the wrapper? Run sh -c "$(curl -fsLS get.chezmoi.io)" -- init --apply ax-at directly, or β with Homebrew + git already installed β brew install chezmoi && chezmoi init --apply ax-at.
chezmoi will then:
- install Rosetta 2 (Apple Silicon) + Homebrew (which pulls in the Xcode Command Line Tools),
brew bundleevery enabled package from the registry,- install runtimes via mise (Node LTS, pnpm, Ruby, Zulu-17 JDK, Python) + npm CLIs,
- run the official installers for AI tools /
fallow/pass-cli, - install editor extensions, generate SSH keys +
ghlogin, and apply macOS defaults, - drop all dotfiles (zsh, starship, ghostty, git, nano, karabiner, linearmouse).
You'll be prompted once for your git identity (work + personal) and a few module toggles.
π‘ If the Command Line Tools GUI dialog ever blocks the run, finish it and re-run
chezmoi apply.
βΉοΈ How to tell it worked. chezmoi is silent on success β there's no completion banner. A normal shell prompt with no
Error:line means it finished; confirm withecho $?(0= success, non-zero = it aborted). A few steps continue on non-fatal errors instead of aborting, so scan the log for strayHTTP/error/failedlines. The known one: registering the SSH signing key needsgh'sadmin:ssh_signing_keyscope β if it's missing you'll see a404there, but the run still completes and everything else is applied.
chezmoi overwrites files it manages. Before the first apply on a machine you care about, install chezmoi without applying, then review:
sh -c "$(curl -fsLS get.chezmoi.io)" -- init ax-at # install + clone, DON'T apply
chezmoi diff # review every change
chezmoi apply --dry-run --verbose # see what scripts would run
# happy? then:
chezmoi apply(Drop the --apply and it clones only. If chezmoi is already installed, just chezmoi init ax-at.)
Back up any existing ~/.zshrc, ~/.gitconfig, etc. that you want to keep.
Secrets are never committed and never written to disk. The repo only ever holds
pass://vault/item/field reference locators (not secrets). At the point a tool runs, pass-cli
resolves those references and injects the real values into that tool's process environment only β
masked in logs, gone when the process exits:
# A committed reference (safe to publish):
export SOME_TOKEN="pass://Personal/some-service/password"
# Resolved into the child's env at invocation, nothing persisted:
pass-cli run -- some-toolOn a new machine, pass-cli installs automatically; authenticate once:
pass-cli login # one-time interactive auth
pass-cli info # verify the session
proton-pass-doctor # health-check the whole pipeline end to endproton-pass-doctor is a brew doctor-style diagnostic: it checks that pass-cli is installed, a
session is active, and a pass:// reference actually resolves to a real value β exiting non-zero
with a specific message for whichever step is wrong.
Degrades gracefully: before you log in, references simply stay unresolved and tools fall back to
their own auth β nothing breaks. No secret is wired in this repo yet; each real secret is added as a
per-tool pass-cli run wrapper when needed.
Tracked here because Apple/vendor flows require a human:
- Sign in to Apple ID (System Settings) β required for the App Store.
- Xcode (iOS builds): install from the App Store (or
mas install 497799835), launch once to accept the license, thensudo xcode-select -s /Applications/Xcode.app/Contents/Developer. - Android Studio first-run: install the SDK + an emulator (AVD).
ANDROID_HOMEis already exported in.zshrc. -
pass-cli login(see Secrets). - Grant Karabiner-Elements and LinearMouse their permissions (Input Monitoring / Accessibility) when prompted.
- Karabiner: open it β Complex Modifications β "Add Predefined Rule" β enable all "Windows Shortcuts" rules.
- VS Code / Cursor: turn off the built-in Settings Sync (chezmoi manages
settings.json). - Log out / back in so fast key-repeat + modifier changes fully apply.
Everything is driven by the registry and module toggles.
- Add a tool: append a
[[packages]]block tohome/.chezmoidata/registry.toml. - Remove a tool: set
enabled = false(stays documented, won't install). - Toggle a whole group: edit
[modules]in the registry (or answer the init prompts). - Switch an install method (e.g. AI tool from
brewβ official installer): change themethodfor that entry. - Regenerate the catalog:
./scripts/gen-tools.sh(CI enforces it stays current).
After editing, apply with chezmoi apply. Provisioning scripts re-run automatically when their content changes.
A curated set of agent skills is installed globally (available in every project) via npx skills for five agents: universal (the shared .agents/skills dir many tools read), claude-code, openclaw, hermes-agent, and pi. The full catalog is in SKILLS.md.
- Source of truth:
home/.chezmoidata/skills.tomlβ one[[repos]]block per source repo (repo+ askills = [...]list, plus an optional per-repoagentsoverride; omitted β all agents in the top-levelagentslist). Each repo installs in a single batchednpx skills add(one clone, symlinked into every target agent). - Agent granularity is per repo, not per skill: every skill in a
[[repos]]block shares that block's agent set. If one skill needs a different set, give it its own[[repos]]block (as theax-at/better-auth-skillsfork does). - Add / remove a skill: add or delete it from a block, then
chezmoi apply. The script reconciles against on-disk reality (skills list -g --json): it installs whatever's missing and uninstalls anything it previously installed that you've dropped from the file. It reads a manifest at~/.local/state/dotfiles/skills.appliedonly to scope removals, so skills you add by hand are never removed β and because reconcile trusts reality, it self-heals if the manifest drifts. (Identity is the skill name: hand-adding a skill whose name collides with a curated one makes it look "ours.") - Pin a skill: the CLI has no
@tagsyntax, butrepoaccepts any git source, so point it at a branch URL to pin (e.g. our forkax-at/better-auth-skillsfor the security skill). - Note: five Matt Pocock skills (
grilling,grill-me,code-review,resolving-merge-conflicts) plusshadcn/improve'simproveshare names with Claude Code built-ins and deliberately override them. - Regenerate the catalog:
make update-skills(CI enforces it stays current).
Runs after gh login (step 65, below), so clones are GitHub-authenticated and dodge anonymous rate limits β without exporting any token to the third-party skills the CLI runs. Installs are best-effort: a broken upstream skill logs a warning and is skipped β it never blocks chezmoi apply.
A bats suite covers template rendering, registry integrity, and the provisioning scripts' shell-function logic. It's offline-first β no installs, no machine changes. The one network-aware check (zsh plugin validation) prefers live GitHub when it's reachable and falls back to a pinned snapshot otherwise, so the suite stays green β and never flakes β anywhere. Run it against live GitHub on demand with make check-plugins. On a machine provisioned by this repo, chezmoi and bats are already on PATH (both are in the registry), so there's nothing to set up:
make test # whole suite
make test FILE=templates # one suite β test/templates.bats
make test FILTER=oxc # one test β regex over test names (bats -f)
make lint # shellcheck + shfmt + actionlintThe first run fetches pinned bats into test/lib/ (gitignored); the same suite gates every push via CI. Not yet bootstrapped and chezmoi isn't on PATH? Point at it once: make test CHEZMOI_BIN=~/.local/bin/chezmoi.
update-all # brew upgrade + mise upgrade + chezmoi update (alias in .zshrc)dotfiles/
βββ install # one-line bootstrap (served at ax-at.github.io/dotfiles/install)
βββ .nojekyll # serve Pages as static files (don't run Jekyll/Liquid)
βββ README.md # this guide
βββ TOOLS.md # generated tool catalog
βββ SKILLS.md # generated agent-skills catalog
βββ .chezmoiroot # β "home" (keeps repo meta out of $HOME)
βββ scripts/ # maintenance helpers (wired to `make` targets)
β βββ gen-tools.sh # regenerate TOOLS.md from the registry
β βββ gen-skills.sh # regenerate SKILLS.md from skills.toml
β βββ gen-ghostty-themes.sh # snapshot Ghostty's built-in themes for tests
β βββ check-plugins-live.sh # validate zsh plugin refs against live GitHub
βββ .github/workflows/ci.yml # template lint + TOOLS.md freshness + shellcheck
βββ home/ # β chezmoi source root
βββ .chezmoi.toml.tmpl # init prompts (identity + module toggles)
βββ .chezmoidata/registry.toml # SINGLE SOURCE OF TRUTH (tools)
βββ .chezmoidata/skills.toml # curated global agent skills
βββ .chezmoiexternal.toml # fetches Karabiner ruleset
βββ .chezmoiscripts/ # ordered provisioning steps
βββ dot_zshrc.tmpl dot_zsh_plugins.txt dot_gitconfig.tmpl dot_nanorc
βββ dot_config/{starship,ghostty,linearmouse,mise}/
| Script | Does |
|---|---|
run_once_before_10-prerequisites |
Rosetta + Homebrew (+ CLT) |
run_onchange_after_20-packages |
generate Brewfile from registry β brew bundle |
run_onchange_after_30-mise |
runtimes + npm-global CLIs |
run_onchange_after_40-ai-tools |
official script installers |
run_onchange_after_50-editor-extensions |
VS Code + Cursor extensions |
run_once_after_60-ssh-github |
SSH key + gh auth + signing key |
run_onchange_after_65-agent-skills |
reconcile global agent skills via npx skills |
run_onchange_after_70-macos-defaults |
dev defaults + Ubuntu-feel tweaks |
The registry schema already supports linux (and per-distro apt/dnf) install methods, and chezmoi branches on {{ .chezmoi.os }} / {{ .chezmoi.osRelease.id }}. The Linux GUI-app story (flatpak/snap) and per-distro overrides are intentionally not built yet.
- Karabiner ships Windows/Linux shortcuts (
Ctrl+C/V/X/Z/A,Ctrl+β/βword-jump,Home/End) and excludes terminals, so shellCtrl+C/readline stay correct. - LinearMouse disables pointer acceleration (flat, Linux-like movement) and natural scrolling.
- Modifier keys stay at default (Winββ, Altββ₯); Karabiner does the shortcut work β don't also swap βββ₯.