Skip to content
 
 

Repository files navigation

Introduction

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.

What you get

  • Homebrew packages and casks from a single Brewfile
  • Zsh + Oh My Zsh, a Starship prompt, and $PATH setup
  • Terminal: Warp with the JetBrains Mono Nerd Font
  • Modern CLI tooling: rg, ast-grep, fd, fzf, eza, zoxide, git-delta, lazygit, direnv, plus btop, yazi, glow, jless, dust, duf, procs, sd, gping, zellij
  • Smart shell: atuin (fuzzy Ctrl-R history), fzf-tab (fuzzy Tab completion), a fastfetch greeting, and "use the modern tool" nudges that remind you to reach for rg/fd/dust/… when you type the old command
  • Zsh autosuggestions + syntax highlighting + you-should-use alias 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 .macos system defaults

Requirements

  • 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)

A Fresh macOS Setup

These instructions set up a brand-new Mac. If you instead want to build your own dotfiles from this repo, see Customizing below.

1. Back up your old Mac (if migrating)

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?

2. Set up an SSH key

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.

3. Clone and install

🛑 Run as your normal user, not root. If your prompt ends in # (e.g. sh-3.2#) you're root — type exit until it ends in %. Homebrew refuses to run as root, the CLT install dialog won't appear for root, and symlinks would land in /var/root instead of your home directory. Never run fresh.sh as root.

ℹ️ A brand-new Mac has no git yet. The first git command triggers the Xcode Command Line Tools installer — click Install in the dialog (or run xcode-select --install) and wait for it to finish before continuing. The clone that triggered it does not run; re-issue it afterwards. Verify with git --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

Troubleshooting: the CLT installer dialog never appears

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 softwareupdate doesn'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:

  1. Install Xcode Command Line Tools, Oh My Zsh, and Homebrew
  2. Symlink .zshrc and .gitconfig into your home directory
  3. Install everything in the Brewfile
  4. Create project directories (~/Herd, ~/Code/{Personal,Clients,Cogneiss})
  5. Install the global Laravel installer (if Herd's composer is available)
  6. Clone your repositories (edit clone.sh first — it ships empty)
  7. Symlink config/ into ~/.config and set up the AI agent layer via ai.sh
  8. Apply .macos system defaults (this reloads the shell at the end)

4. Finish up

  1. Start Herd.app and complete its install process (provides PHP/Node/DBs). Then install the global Laravel installer (Herd's composer is only on $PATH after Herd runs once):
    composer global require laravel/installer   # so `laravel new` works
  2. Copy the secrets template and fill in your keys:
    cp ~/.dotfiles/.env.example ~/.env && $EDITOR ~/.env
  3. 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
  4. Restart your Mac to finalize everything.

5. Verify

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 ~/.dotfiles references in fresh.sh and ai.sh.

AI Agent Layer

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 planner and code-reviewer subagents run on Opus where the extra reasoning pays off. Use /model to downshift to Haiku for trivial work or up to Opus for hard problems.

Secrets

API keys live in ~/.env (git-ignored), which .zshrc sources automatically on shell start. Start from .env.example. Nothing secret is ever committed.

Productivity workflows

Laravel Boost (real project context for agents)

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:install

Parallel agents with git worktrees

Worktrees 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.

Subagents, commands & skills

The agent layer ships reusable Claude Code building blocks (all symlinked into ~/.claude by ai.sh):

  • Subagents (ai/claude/agents/) — code-reviewer and planner (Opus), test-writer and debugger (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 to planner) and /ship (full gate: verify → review → security-review → commit).
  • Skills — verify runs stack-aware lint/test/type-check gates. ai.sh also installs (via npx skills) agent-browser (token-lean browser CLI), Anthropic's frontend-design, Vercel's web-design-guidelines, ast-grep (structural code search), find-skills (discover/install skills), ui-ux-pro-max (design suite, 7 skills), and impeccable (frontend polish/critique).
  • Vendored skills (cherry-picked from affaan-m/ECC, not the whole bundle) — continuous-learning-v2 watches 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), and agent-eval (guidance for head-to-head agent benchmarking — the CLI installs separately).
  • Capability map — AGENTS.md carries 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 with gstack-upgrade.
  • Plugins — ai.sh installs feature-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-off to silence for a session), and roundtable (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.sh installs code-review-graph (backs the opt-in code-review-graph MCP), graphifyy (safishamsi/graphify — turns code/docs/media into a queryable knowledge graph; ai.sh also runs graphify install to register the /graphify skill), and specify (GitHub Spec Kit, used by the spec alias).
  • Auto-format hook — format.sh formats 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-audit runs AgentShield (npx ecc-agentshield scan) over ~/.claude to 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 --opus for the deep red/blue/auditor multi-agent pass.
  • Project context — claude-init drops a CLAUDE.md template into any repo; rules-init drops path-scoped .claude/rules/ (TypeScript/PHP/Python/tests) that load only when matching files are touched.

Memory & context management

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 /context and /cost.
  • Path-scoped rules (rules-init) keep heavy instructions out of context until a matching file is opened.
  • cavemem (installed by fresh.sh, wired by ai.sh) is a local, compressed persistent-memory MCP (SQLite + FTS5 + local vector search — no keys, no network) that survives /compact and gives cross-session recall. View it with memview (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-on installs the caveman skill, which compresses Claude's output (~65%, reasoning and code preserved); it changes output style, so toggle per session with /caveman.

Autonomous & spec-driven delivery

Two paths for building whole features/apps:

  • Supervised — GitHub Spec Kit (spec → specify init, then /speckit.*) to spec first, plan mode + /plan to design, then /ship to gate and commit.
  • Autonomous — the Ralph loop (ralph-init) runs a fresh claude -p per iteration against a prd.json backlog (TDD → commit → repeat), and claude-auto (cauto) is a headless, budget-capped runner.
  • Hands-off, from a feature list — autobuild (autobuild-init drops a features.md template) is Ralph's missing front-end: it plans a prd.json backlog from a plain feature list, runs the Ralph loop in an isolated branch, and opens a draft PR. Composes claude-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-turns caps. For sanctioned unattended work, prefer Anthropic's Claude Code Routines (pushes only to claude/* branches).

Browser automation

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; run npx agent-browser install once 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-on registers both (interactive control + network/console/perf debugging); browser-off after. Playwright MCP alone adds ~13.7k tokens at startup, hence opt-in.

Token budget

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 + context7 MCP, a short CLAUDE.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-devtools MCP (toggle with github-on / browser-on), and Superpowers (installed but disabled — superpowers-on only for heavy sessions; it preloads ~22k tokens).
  • Levers without losing quality: delegate fan-out to subagents, use cavemem for durable memory (not a bloated CLAUDE.md), caveman-on for output compression, and watch /context + /cost. Audit with /context and toggle off anything you're not using this session.

References / going further

  • 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 /context after).

Pre-commit hooks (Lefthook)

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.

Terminal

Warp is the terminal and Starship the prompt. cmux handles parallel agent sessions. The Starship config lives under config/ and symlinks into ~/.config.

What's in here

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)

Day-to-day

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-* commands

Keeping a machine in sync

Run 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.

Troubleshooting

  • A brew cask fails to install: check the exact name on formulae.brew.sh; some apps change cask IDs.
  • herd/php not found: start Herd.app once so it injects its shell config, then reloadshell.
  • Agent configs missing: re-run ./ai.sh; it logs each symlink it creates.
  • MCP servers not registered: they only register if the claude CLI is installed — run ./ai.sh again after the Brewfile install completes.

Customizing

Want to base your own dotfiles on this? Fork the repo, then:

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.

Thanks To...

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. 💛

About

Get started with your own dotfiles.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages