Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

188 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

dotfiles

macOS setup as code. Clone, run one command, and a bare Mac comes up as my machine — shell, git, editor, terminal, apps, and system preferences, all configured the way I like them.

Built to be idempotent (safe to re-run), interactive where it matters (you pick which apps), and honest about secrets (none live here — see SECRETS.md).


Quick start

# 1. Sign into 1Password first — secret + SSH restore depend on it.
# 2. Clone over HTTPS (a fresh Mac has no SSH key yet):
git clone https://github.com/martinlaws/dotfiles.git ~/dotfiles
cd ~/dotfiles

# 3. Run the one entrypoint:
sh setup

That's it. setup detects your architecture, installs Xcode Command Line Tools and Homebrew, then walks through each phase below. Run it again any time — it flips into update mode and refreshes rather than redoing first-time setup.

Bringing up a fresh Mac? Follow the interactive checklist at martinlaws.github.io/dotfiles — tick steps off as you go (progress saves in the browser, every command has a copy button). Same runbook in plain text: FIRST-RUN.md.


What it sets up

Phase What happens
1 · Foundation Xcode CLT, Homebrew, CLI tools from config/Brewfile, Node LTS pinned via fnm
2 · Dev config Symlinks shell / terminal / editor / ssh configs (via GNU Stow), generates ~/.gitconfig from a template, sets up SSH
3 · Apps & system Installs GUI apps from config/Brewfile.apps (all / by category / pick-and-choose), reinstalls editor extensions, applies opinionated macOS defaults
4 · Claude & tooling Restores my private Claude Code config into ~/.claude, builds the hey CLI from source, clones my repos (list in ~/.claude/repos.txt), and loads the chaos autosave agent (snapshots my knowledge repo to a safety branch)

A couple of steps stay manual by design — setup will prompt you:

  • Git identity — it asks for the name/email to stamp into ~/.gitconfig.
  • SSH key on GitHub — see the SSH note below; you'll paste a public key into github.com/settings/keys.

And after it finishes:

  • Restore secrets — follow SECRETS.md (1Password + vercel env pull).
  • Re-auth Claude Code — sign in once; it regenerates its own credentials.
  • gh auth login — re-authenticate the GitHub CLI; its token doesn't migrate.
  • Mac App Store apps — sign into the App Store, then brew bundle --file=config/Brewfile.mas.
  • Caps Lock → Esc — System Settings → Keyboard → Modifier Keys. (The one thing macOS won't let me script cleanly.)

The stack

Shellzsh + Starship prompt. History, navigation, and listing are upgraded with a modern CLI kit, each wired into .zshrc behind a command -v guard so the shell never errors if a tool isn't installed yet:

Tool What it does
atuin Shell history → searchable, synced SQLite (Ctrl-R)
zoxide cd that learns — z <partial> from anywhere
eza ls with icons, git status, tree view
bat cat with syntax highlighting
fzf Fuzzy finder (Ctrl-T / Ctrl-R / Alt-C)
ripgrep Fast recursive search (rg)
git-delta Git's pager + diff filter, made readable

Node — managed by fnm only. .zshrc runs fnm env --use-on-cd (auto-switch per directory), and setup pins lts-latest as the default so a fresh machine has a working node/npm immediately.

Git — sensible aliases, delta for diffs, zdiff3 conflict style, and a ~/.git-template that seeds every git init.


SSH: one key, in 1Password

There's no per-machine SSH key to manage. The committed ~/.ssh/config points SSH at the 1Password SSH agent (IdentityAgent), so a single key lives in 1Password and follows me to any machine — nothing private ever touches disk.

scripts/setup-ssh.sh checks the agent: if it already holds a key, setup skips key generation entirely. If 1Password isn't present (or the key hasn't been added yet), it falls back to minting a local ~/.ssh/id_ed25519 and prints the public half to add to GitHub. Either way you end up connected.

The same key also signs my git commits — via 1Password's op-ssh-sign, wired in the gitconfig template — so GitHub shows them Verified.


Layout

setup                  ← the only entrypoint:  sh setup
config/
  Brewfile             ← CLI formulae
  Brewfile.apps        ← GUI casks, grouped by category
  Brewfile.mas         ← Mac App Store apps (via mas)
  launchd/             ← LaunchAgent templates (chaos autosave)
dotfiles/              ← Stow packages, symlinked into ~
  shell/     .zshrc · .vimrc · .config/starship.toml
  git/       .gitconfig.template · .gitignore_global · .git-template/
  terminal/  .config/ghostty/config · .hyper.js
  editors/   VS Code settings
  ssh/       .ssh/config
  bin/       ~/.bin personal scripts (chaos autosave)
  wm/        .config/aerospace/aerospace.toml (window manager)
scripts/               ← one file per concern (+ lib/ helpers)
docs/                  ← interactive first-run checklist (GitHub Pages)
FIRST-RUN.md           ← step-by-step new-machine runbook
SECRETS.md             ← how to restore secrets (no secrets in here)

On secrets

Nothing sensitive lives in this repo — that's the whole point, and it's why I'm comfortable making it public. 1Password is the source of truth; runtime secrets land in per-project .env.local files (gitignored), and Vercel-managed projects pull their own. The full restore playbook is in SECRETS.md.

.gitignore blocks *.local and .claude/ as a backstop. Anything machine-specific goes in a .local file; anything private goes in a private repo. The public repo stays clean by construction.


Related

  • martinlaws/claude-config (private) — my Claude Code skills, agents, hooks, and memory; restored into ~/.claude by scripts/setup-claude.sh.

About

the basis for my mac setups

Resources

Stars

Watchers

Forks

Contributors

Languages