My personal dotfiles for setting up and maintaining a macOS Tahoe (macOS 26) machine on Apple Silicon. One script takes a clean Mac and installs my tooling for a mixed PHP/Laravel + JS/TS + Python stack, applies sensible macOS defaults, and — importantly — wires up a first-class AI agent layer (Claude Code).
Originally forked from driesvints/dotfiles and adapted for an AI-agent-driven 2026 workflow.
- Homebrew packages and casks from a single
Brewfile - Zsh + Oh My Zsh, a Starship prompt, and
$PATHsetup - Terminal: Warp with the JetBrains Mono Nerd Font
- Modern CLI tooling:
rg,ast-grep,fd,fzf,eza,zoxide,git-delta,lazygit,direnv, plusbtop,yazi,glow,jless,dust,duf,procs,sd,gping,zellij - Smart shell:
atuin(fuzzy Ctrl-R history),fzf-tab(fuzzy Tab completion), afastfetchgreeting, and "use the modern tool" nudges that remind you to reach forrg/fd/dust/… when you type the old command - Zsh autosuggestions + syntax highlighting +
you-should-usealias reminders, and a global git config (delta diffs, sane defaults, SSH-signed commits) - Per-language toolchains: Herd (PHP),
pnpm/bun(JS/TS),uv/ruff(Python) - GUI apps: Raycast (launcher), Sequel Ace (DB), Zed (editor), and more
- An AI agent layer: versioned Claude Code configs and shared MCP servers
- Productivity workflows: Laravel Boost, parallel agents via git worktrees, and auto-format hooks
- ~900 lines of opinionated
.macossystem defaults
- A Mac running macOS 26 (Tahoe) on Apple Silicon
- An internet connection (and your Apple ID signed in if you install App Store apps by hand)
These instructions set up a brand-new Mac. If you instead want to build your own dotfiles from this repo, see Customizing below.
Before wiping or migrating, run through this checklist:
- Committed and pushed all your git branches?
- Saved important documents from non-iCloud directories?
- Exported any local databases you care about?
- Saved data from apps that don't sync to iCloud?
Generate a key with the helper script:
curl https://raw.githubusercontent.com/coding-sunshine/dotfiles/HEAD/ssh.sh | sh -s "<your-email-address>"Then add the key to your GitHub account.
🛑 Run as your normal user, not
root. If your prompt ends in#(e.g.sh-3.2#) you're root — typeexituntil it ends in%. Homebrew refuses to run as root, the CLT install dialog won't appear for root, and symlinks would land in/var/rootinstead of your home directory. Never runfresh.shas root.
ℹ️ A brand-new Mac has no
gityet. The firstgitcommand triggers the Xcode Command Line Tools installer — click Install in the dialog (or runxcode-select --install) and wait for it to finish before continuing. The clone that triggered it does not run; re-issue it afterwards. Verify withgit --version.
git clone --recursive git@github.com:coding-sunshine/dotfiles.git ~/.dotfiles
cd ~/.dotfiles && ./fresh.sh🔑 The SSH clone above only works once your key from step 2 is added to GitHub. If you haven't done that yet (or want to skip SSH for the initial clone), use HTTPS instead:
git clone --recursive https://github.com/coding-sunshine/dotfiles.git ~/.dotfiles
xcode-select --install prints install requested... but no GUI dialog shows
up (common over SSH, or if you were in a root shell). Two reliable fallbacks:
- Headless install — no dialog needed:
# Tell softwareupdate to expose the CLT package, then list and install it sudo touch /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress softwareupdate --list # copy the exact "Command Line Tools for Xcode-XX.X" label sudo softwareupdate --install "Command Line Tools for Xcode-16.4" --verbose sudo rm -f /tmp/.com.apple.dt.CommandLineTools.installondemand.in-progress
- Manual download — if
softwareupdatedoesn't list it, grab the installer from https://developer.apple.com/download/all/ (sign in with your Apple ID), search "Command Line Tools", and run the.dmg.
If a previous attempt got wedged, clear it and retry:
sudo rm -rf /Library/Developer/CommandLineTools && xcode-select --install.
Confirm success with git --version before continuing.
fresh.sh is idempotent — safe to re-run. It will:
- Install Xcode Command Line Tools, Oh My Zsh, and Homebrew
- Symlink
.zshrcand.gitconfiginto your home directory - Install everything in the
Brewfile - Create project directories (
~/Herd,~/Code/{Personal,Clients,Cogneiss}) - Install the global Laravel installer (if Herd's
composeris available) - Clone your repositories (edit
clone.shfirst — it ships empty) - Symlink
config/into~/.configand set up the AI agent layer viaai.sh - Apply
.macossystem defaults (this reloads the shell at the end)
- Start Herd.app and complete its install process (provides PHP/Node/DBs).
Then install the global Laravel installer (Herd's
composeris only on$PATHafter Herd runs once):composer global require laravel/installer # so `laravel new` works - Copy the secrets template and fill in your keys:
cp ~/.dotfiles/.env.example ~/.env && $EDITOR ~/.env
- Add your SSH public key to GitHub as both an Authentication and a
Signing key (commits are SSH-signed by default — see
.gitconfig): https://github.com/settings/keys - Restart your Mac to finalize everything.
brew bundle check --file ~/.dotfiles/Brewfile # all packages installed?
ls -l ~/.claude # agent configs symlinked?
claude mcp list # MCP servers registered?
git config --get commit.gpgsign # "true" -> SSH signing on
echo $ANTHROPIC_API_KEY # ~/.env loaded? (non-empty)💡 Set your terminal/editor font to "JetBrainsMono Nerd Font" so the Starship prompt icons render instead of as empty boxes.
Your Mac is now ready to use! 🎉
💡 You can clone to a location other than
~/.dotfiles, but several scripts assume that path. If you change it, update.zshrc($DOTFILES) and the~/.dotfilesreferences infresh.shandai.sh.
The ai/ directory is the single source of truth for every coding agent
I run. ai.sh (invoked by fresh.sh, also runnable standalone)
symlinks each config into place and registers shared MCP servers. It is
idempotent — re-run it any time you change a config.
| File | Symlinked to | Purpose |
|---|---|---|
ai/AGENTS.md |
~/.claude/AGENTS.md |
Shared, tool-agnostic instructions |
ai/claude/CLAUDE.md |
~/.claude/CLAUDE.md |
Global Claude Code instructions (imports AGENTS.md) |
ai/claude/settings.json |
~/.claude/settings.json |
Model (Sonnet default) / permissions / hooks / statusline / auto memory |
ai/claude/statusline.sh |
~/.claude/statusline.sh |
Statusline: model · branch · context-usage bar · session cost |
ai/claude/agents/ |
~/.claude/agents |
Subagents: code-reviewer & planner (Opus), debugger (Sonnet), test-writer (Haiku — mechanical) |
ai/claude/commands/ |
~/.claude/commands |
Slash commands: /review, /pr, /spec, /test, /plan, /ship |
ai/claude/skills/ |
~/.claude/skills/* (per-skill) |
Skills: verify (ours) + installed: agent-browser, frontend-design, web-design-guidelines, ast-grep, find-skills, ui-ux-pro-max (+suite), impeccable, graphify (/graphify), continuous-learning-v2 (instincts), agent-eval, gstack (/gstack-*) |
ai/mcp/mcp.json |
registered via claude mcp add-json |
MCP servers: always-on filesystem, context7; opt-in github, playwright, chrome-devtools, composio |
To update: edit a file under ai/, then run ./ai.sh. Skills are symlinked
per-item so externally-installed skills coexist without polluting the repo.
Model routing. The interactive default is Sonnet 4.6 (fast and cheap for day-to-day work); the
plannerandcode-reviewersubagents run on Opus where the extra reasoning pays off. Use/modelto downshift to Haiku for trivial work or up to Opus for hard problems.
API keys live in ~/.env (git-ignored), which .zshrc sources
automatically on shell start. Start from .env.example.
Nothing secret is ever committed.
Laravel Boost gives AI agents 15 MCP tools to see your actual app (logs, queries, config, routes) instead of guessing, and it auto-installs the Herd MCP server. Run once per Laravel project:
boost # alias: composer require laravel/boost --dev && herd php artisan boost:installWorktrees let several agents work on different branches at once, each in its own
directory sharing one .git. The gwt helper makes this a one-liner:
gwt new feature-x # create ../<repo>.worktrees/feature-x on a new branch
gwtcd feature-x # jump into it
gwt ls # list worktrees
gwt rm feature-x # remove when merged
⚠️ Practical ceiling is ~5–7 agents (rate limits + disk; each worktree is a full checkout). Worktrees isolate files but share ports/DBs/services — give each running app its own port and database.
The agent layer ships reusable Claude Code building blocks (all symlinked into
~/.claude by ai.sh):
- Subagents (
ai/claude/agents/) —code-reviewerandplanner(Opus),test-writeranddebugger(Sonnet), each with its own isolated context window (verbose work stays out of the main thread). - Slash commands (
ai/claude/commands/) —/review,/pr,/spec,/test, plus/plan(delegates toplanner) and/ship(full gate: verify → review → security-review → commit). - Skills —
verifyruns stack-aware lint/test/type-check gates.ai.shalso installs (vianpx skills)agent-browser(token-lean browser CLI), Anthropic'sfrontend-design, Vercel'sweb-design-guidelines,ast-grep(structural code search),find-skills(discover/install skills),ui-ux-pro-max(design suite, 7 skills), andimpeccable(frontend polish/critique). - Vendored skills (cherry-picked from affaan-m/ECC,
not the whole bundle) —
continuous-learning-v2watches sessions via Pre/PostToolUse hooks and distils your recurring patterns into confidence-scored "instincts" (/instinct-status; heavy background observer is off by default, data in~/.local/share/ecc-homunculus), andagent-eval(guidance for head-to-head agent benchmarking — the CLI installs separately). - Capability map —
AGENTS.mdcarries a "reach for these automatically" table so agents route to the right tool (graphify, ast-grep, deep-research, autobuild, …) without you having to remember each one. - gstack (garrytan/gstack) — Garry Tan's
23-command framework (CEO/eng/design/QA/release review gates), installed
prefixed as
/gstack-*so it coexists with the commands above. Update withgstack-upgrade. - Plugins —
ai.shinstallsfeature-dev+code-review(anthropics/claude-code),frontend-design(anthropics/claude-plugins-official),superpowers(disabled by default),ponytail(DietrichGebert/ponytail — lazy/minimal-code mode,/ponytail*),caveman(JuliusBrussee/caveman — terse-output mode, on by default;caveman-offto silence for a session), androundtable(wan-huiyan/agent-review-panel — opt-in multi-agent adversarial review at PR/plan boundaries,/roundtable:agent-review-panel; token-heavy). - uv-tool CLIs —
ai.shinstallscode-review-graph(backs the opt-in code-review-graph MCP),graphifyy(safishamsi/graphify — turns code/docs/media into a queryable knowledge graph;ai.shalso runsgraphify installto register the/graphifyskill), andspecify(GitHub Spec Kit, used by thespecalias). - Auto-format hook —
format.shformats every file an agent edits (Pint/Ruff/Prettier) via a PostToolUse hook. - Session visibility —
ccusage(bun global) appends today's spend + burn rate to the statusline every session. - Config security audit —
claude-auditruns AgentShield (npx ecc-agentshield scan) over~/.claudeto catch leaked secrets, over-broad permissions, hook-injection, and risky MCP servers in the harness config itself — the one piece worth cherry-picking from ECC. On-demand only (nothing always-on); add--opusfor the deep red/blue/auditor multi-agent pass. - Project context —
claude-initdrops aCLAUDE.mdtemplate into any repo;rules-initdrops path-scoped.claude/rules/(TypeScript/PHP/Python/tests) that load only when matching files are touched.
Most of this is native to Claude Code — the layer here just turns it on, makes it visible, and adds one lightweight persistent store:
- Auto memory is enabled in
settings.json(autoMemoryEnabled). Claude writes its own learnings to~/.claude/projects/<repo>/memory/MEMORY.md(only ~200 lines load per session); browse/edit with/memory. - Statusline (
statusline.sh) shows a live context-usage bar + session cost so you see compaction coming. Pair with/contextand/cost. - Path-scoped rules (
rules-init) keep heavy instructions out of context until a matching file is opened. - cavemem (installed by
fresh.sh, wired byai.sh) is a local, compressed persistent-memory MCP (SQLite + FTS5 + local vector search — no keys, no network) that survives/compactand gives cross-session recall. View it withmemview(cavemem viewer). - Token discipline lives in
AGENTS.md: delegate fan-out to subagents, read file ranges not whole files, keep the MCP set lean (/mcp), and downshift the model for routine work. - Opt-in:
caveman-oninstalls the caveman skill, which compresses Claude's output (~65%, reasoning and code preserved); it changes output style, so toggle per session with/caveman.
Two paths for building whole features/apps:
- Supervised — GitHub Spec Kit (
spec→specify init, then/speckit.*) to spec first, plan mode +/planto design, then/shipto gate and commit. - Autonomous — the Ralph loop (
ralph-init) runs a freshclaude -pper iteration against aprd.jsonbacklog (TDD → commit → repeat), andclaude-auto(cauto) is a headless, budget-capped runner. - Hands-off, from a feature list —
autobuild(autobuild-initdrops afeatures.mdtemplate) is Ralph's missing front-end: it plans aprd.jsonbacklog from a plain feature list, runs the Ralph loop in an isolated branch, and opens a draft PR. Composesclaude-auto+ralph.sh+gwt— one loop, not a second one. Dry-run self-check:AB_DRY_RUN=1 autobuild features.md.
Safe automation ("don't make Claude angry"). Run unattended loops on a throwaway worktree, route them to API billing (
ANTHROPIC_API_KEY) so they draw from the Agent-SDK/API budget instead of the interactive subscription caps, and keep the--max-budget-usd/--max-turnscaps. For sanctioned unattended work, prefer Anthropic's Claude Code Routines (pushes only toclaude/*branches).
Ranked by token cost (browser tools are expensive, so the default is the lean one):
- Default — Agent Browser: a
CLI (~1,400 tokens/snapshot, ~93% less than Playwright MCP). Installed as a thin
skill by
ai.sh; runnpx agent-browser installonce to fetch Chrome. - E2E tests — Playwright CLI (
npx playwright): no MCP tool-def tax; use it to author/run standard test suites. - Opt-in — Playwright MCP + Chrome DevTools MCP:
browser-onregisters both (interactive control + network/console/perf debugging);browser-offafter. Playwright MCP alone adds ~13.7k tokens at startup, hence opt-in.
Session base overhead is ~20–30k tokens before you type (system prompt + CLAUDE.md every turn + MCP schemas every turn + skill frontmatter). This setup keeps it lean:
- Always-on by design:
filesystem+context7MCP, a shortCLAUDE.md→AGENTS.md, skill frontmatter (~100 tokens each; gstack adds ~2–3k for its 23 skills), auto memory (≤25k cap). - Off by default (opt-in):
github,playwright,chrome-devtoolsMCP (toggle withgithub-on/browser-on), and Superpowers (installed but disabled —superpowers-ononly for heavy sessions; it preloads ~22k tokens). - Levers without losing quality: delegate fan-out to subagents, use
cavememfor durable memory (not a bloatedCLAUDE.md),caveman-onfor output compression, and watch/context+/cost. Audit with/contextand toggle off anything you're not using this session.
- awesome-claude-code and awesome-claude-code-skills — curated indexes of skills, hooks, commands, and MCP servers.
- ECC / everything-claude-code
— a huge harness (261 skills / 64 agents). We cherry-picked the security-review
gate rather than installing it; if you want the kitchen sink,
/plugin marketplace add affaan-m/everything-claude-code+/plugin install ecc@ecc(mind the context cost — check/contextafter).
Lefthook runs format/lint on every commit — yours and the agents' — not just Claude's edits. Drop the starter config into a project:
hooks # copies templates/lefthook.yml and runs `lefthook install`It auto-formats staged files with Pint / Ruff / Prettier (whichever apply) and
re-stages the fixes, so nothing unformatted lands. See templates/lefthook.yml.
Warp is the terminal and Starship the
prompt. cmux handles parallel agent sessions. The Starship config lives under
config/ and symlinks into ~/.config.
| Path | What it does |
|---|---|
fresh.sh |
Main bootstrap — orchestrates the whole install |
ssh.sh |
Generates an SSH key and adds it to the agent |
clone.sh |
Clones your repositories (empty template) |
ai.sh |
Sets up the AI agent layer (symlinks + MCP) |
Brewfile |
All Homebrew formulae, casks, and MAS apps |
.zshrc |
Zsh / Oh My Zsh config, Herd + tool init, ~/.env |
.gitconfig |
Global git config (delta, sensible defaults, identity) |
.gitignore_global |
Global ignore rules (wired via .gitconfig) |
aliases.zsh |
Shell aliases (loaded via $ZSH_CUSTOM) |
path.zsh |
$PATH additions (loaded via $ZSH_CUSTOM) |
.env.example |
Template for ~/.env secrets (API keys) |
bin/gwt |
Git worktree helper for parallel agents |
bin/claude-auto |
Headless, budget-capped Claude runner for automation/CI |
bin/mcp-toggle |
Enable/disable an opt-in MCP server on demand (keeps context lean) |
config/ |
App configs symlinked into ~/.config (starship, zed) |
templates/ |
Drop-in project files (CLAUDE.md, lefthook.yml, ralph/, features.md, claude-rules/) |
.macos |
macOS system defaults |
ai/ |
Versioned AI agent configs + hooks + skills (see above) |
dotfiles # cd into the dotfiles repo
update # sync this machine: pull + brew bundle/upgrade + refresh AI layer (bin/dotup)
reloadshell # reload Oh My Zsh after editing config
brew bundle # install anything newly added to the Brewfile
./ai.sh # re-apply agent configs after editing ai/
gwt new <branch> # spin up a worktree for a parallel agent
boost # add Laravel Boost to the current project
hooks # install Lefthook pre-commit hooks in this project
claude-init # drop a CLAUDE.md template into this project
rules-init # drop path-scoped .claude/rules into this project
spec # GitHub Spec Kit (specify init, then /speckit.* commands)
graph-init # build code-review-graph + install graph auto-update hooks here
ralph-init # drop the autonomous Ralph build loop into this project
autobuild-init # drop a features.md template for autobuild
autobuild f.md # feature list -> plan -> Ralph loop -> draft PR (unattended)
cauto "..." # headless, budget-capped Claude run for automation
memview # open the cavemem persistent-memory viewer
github-on # enable the (opt-in) github MCP for this session; github-off after
browser-on # enable Playwright + Chrome DevTools MCP; browser-off after
superpowers-on # enable the Superpowers plugin for a heavy session; superpowers-off after
caveman-off # silence terse-output mode for a session (on by default)
claude-audit # security-audit ~/.claude (AgentShield): secrets, perms, hook-injection
gstack-upgrade # update gstack to the latest /gstack-* commandsRun update (alias for bin/dotup) to bring a machine fully
up to date in one command: it pulls the repo, installs anything new from the
Brewfile, upgrades installed packages, cleans up, and refreshes the AI layer.
What updates how:
| Thing | How it updates |
|---|---|
.zshrc, aliases, starship.toml, .gitconfig, ai/* |
Live on git pull — they're symlinks into the repo. Just exec zsh to reload. |
| Homebrew packages | update installs new Brewfile entries and upgrades existing ones. It does not remove packages you deleted — prune with brew bundle cleanup --file ~/.dotfiles/Brewfile --force. |
.macos system defaults |
Not auto-applied (it can restart apps). Re-apply with source ~/.dotfiles/.macos when it changes. |
- A
brewcask fails to install: check the exact name on formulae.brew.sh; some apps change cask IDs. herd/phpnot found: start Herd.app once so it injects its shell config, thenreloadshell.- Agent configs missing: re-run
./ai.sh; it logs each symlink it creates. - MCP servers not registered: they only register if the
claudeCLI is installed — run./ai.shagain after the Brewfile install completes.
Want to base your own dotfiles on this? Fork the repo, then:
- Edit
.macos— set your computer name (COMPUTER_NAME), timezone, and locale near the top. More options live in Mathias Bynens' script. - Trim/extend the
Brewfile(cask search). - Add your aliases in
aliases.zshand$PATHtweaks inpath.zsh(auto-loaded because$ZSH_CUSTOMpoints here). - List the repos you want cloned in
clone.sh. - Tailor the agent instructions in
ai/AGENTS.md.
This repo deliberately uses a simple symlink + Brewfile approach rather than a dedicated manager (chezmoi, stow, yadm). It's easy to read and extend; reach for one of those tools only if you need cross-platform templating or encrypted, multi-machine secret sync.
Forked from driesvints/dotfiles. Inspiration from the GitHub does dotfiles project, Zach Holman, and Mathias Bynens. Sourabh Bajaj's Mac Setup Guide was invaluable, and the minimal Zsh theme is by @subnixr.
Thanks to everyone who open-sources their dotfiles. 💛
