Personal, opinionated dotfiles for Laravel and PHP development on macOS. One script sets up Laravel Herd, Oh My Zsh, modern command-line tools, macOS preferences, and a version-controlled Claude Code configuration on a fresh Mac.
These dotfiles reflect my personal workflow and are meant to be forked and adapted to your own setup.
- Develop Laravel projects locally with Herd
- Navigate, search, and work faster with Oh My Zsh and modern command-line tools
- Keep Claude Code settings, agents, commands, hooks, rules, and skills version-controlled
- Keep Claude Code changes disciplined with Addy Osmani's agent-skills workflow and an automatic quality gate (Pint, PHPStan, Rector, Pest/PHPUnit)
- Install, update, and reconfigure the whole setup with one script each
Update macOS via System Settings → General → Software Update.
Install the Xcode Command Line Tools if Git is not available yet:
xcode-select --installGenerate a GitHub SSH key. Both this repository and tinkerbench are cloned over SSH:
ssh-keygen -t ed25519 -C "your@github-email.com"
ssh-add --apple-use-keychain ~/.ssh/id_ed25519
cat ~/.ssh/id_ed25519.pub | pbcopyAdd the copied public key at github.com/settings/keys.
The installer replaces existing files with symlinks in place; it does not back them up. It also clears five Claude
Code directories under ~/.claude/ (agents, commands, hooks, rules, skills) before linking them. Review
support/setup/clean-state.sh and preserve anything you need there first.
If you fork the repository, adjust these personal defaults first:
- Git identity in
home/.gitconfig - Absolute working directory in
home/.config/ghostty/config - Locale and time zone in
support/setup/macos/osx-defaults.sh, if they don't match yours
The macOS setup enables FileVault and the application firewall, disables hibernation, changes Finder and Dock
behavior, applies German regional settings, and configures several bundled applications. The installer asks for
confirmation before applying these preferences. Review
support/setup/macos/osx-defaults.sh if you do not want those choices.
Clone the repository to the path expected by the scripts and run the installer:
git clone git@github.com:moessimple/dotfiles.git ~/.dotfiles
cd ~/.dotfiles
bin/install.shFollow the prompts and restart the Mac when the installation finishes.
Authenticate GitHub CLI after installation:
gh auth login -s user:email -w
gh auth statusChoose SSH as the Git protocol during the browser flow.
The complete list of Homebrew formulae, applications, fonts, and Quick Look plugins is in
support/config/Brewfile. The setup also includes:
- Oh My Zsh, shell aliases, functions, paths, exports, and Git helpers
- Laravel Herd, MySQL, Mailpit, and development applications
- Global Composer and npm tools
- Claude Code configuration, skills, plugins, and MCP servers
- tinkerbench, installed at
~/Code/tinkerbench - Ghostty configuration and macOS preferences
Files under home/ mirror their locations below $HOME. For example, home/.zshrc is linked to
~/.zshrc, and home/.claude/skills is linked to ~/.claude/skills. Editing either path changes the file stored in
this repository.
The managed files cover the shell, Git, Ghostty, and Claude Code. Machine-specific shell configuration that should
not be committed belongs in ~/.extra.
These are the commands I use most often. The full list lives in home/.aliases,
home/.functions, and support/git/.
pruns Pest or PHPUnit.ppruns the test suite in parallel.pf <filter>runs tests matching a name.pwwatches files and reruns the test suite.quality [full]runs the PHP/Laravel quality gate (Pint, PHPStan, Rector, Pest/PHPUnit) by hand;quality statusshows the last recorded run.
commit [message]stages and commits the repository. Without a message, Claude generates one, falling back to Codex and then an interactive prompt.wipcommits everything with the messagewip.syncsynchronizes long-lived branches from anupstreamremote and force-pushes them toorigin.nahaborts an in-progress Git operation, discards local changes, and removes untracked files.
sync and nah are destructive commands. Use them only when that behavior is intended.
db <refresh|create|drop|list> [name]manages local MySQL databases.opendbopens the current project's database in a GUI client, using credentials from its.env.mf/mfafresh-migrates the current project's database, or all of its databases (main, test, and parallel test shards).codeopens VS Code.https://tinkerbench.testruns PHP snippets against Herd-linked projects.
/debugfinds and fixes the root cause of a bug through a reproduce-first diagnosis loop./prturns the current branch into a pull request, writing a why-and-outcome description (never from the diff or commit messages) and waiting for approval before creating it./review-prreviews a GitHub PR across five code axes plus whether it delivers what was promised, and delivers the verdict in the chat without posting to GitHub.
Two things keep changes disciplined without me having to think about it: Addy Osmani's agent-skills workflow (spec, plan, build, test, review, ship) and a quality gate that runs Pint, PHPStan, Rector, and Pest/PHPUnit against whatever Laravel/PHP project is being edited.
Update the repository and managed packages with:
bin/update.shThe update treats the repository's package and Claude Code declarations as the desired state. It removes undeclared Homebrew entries, global Composer and npm packages, Claude Code skills and plugins, and user-level MCP servers without asking. Project dependencies and project-level Claude Code integrations are not affected.
Reapply symlinks, services, Herd and tinkerbench setup, and macOS preferences without reinstalling packages with:
bin/reconfigure.shClaude Code settings, agents, commands, hooks, rules, and skills live under home/.claude/ and are linked into
~/.claude/ during installation.
Claude Code is the primary coding agent in this setup. This setup uses Codex only as a lightweight fallback and does
not treat it as a replacement for Claude Code or its full workflow. Codex reuses the same global instructions through
~/.codex/AGENTS.md.
Third-party skills are managed in
support/setup/claude/claude-skills.sh, while plugins and user-level MCP
servers are managed in support/setup/claude/claude-plugins.sh. Run
bin/update.sh after changing either file.
Use ~/.extra for machine-specific environment variables, secrets, aliases, or other shell configuration that should
not be committed. Open it with the extra alias.
Changes intended for every machine belong in this repository and can be synchronized through Git.
Run the repository's Bats tests from the root:
bin/test.shThe suite covers the Claude Code quality hooks and selected shell functions.
- Quality Gate Hooks
- Repository Architecture, for working on this repository with Claude Code
Inspired by Freek Van der Herten's dotfiles and Dries Vints's dotfiles, adapted for my own Laravel, Herd, and Claude Code workflow.
