Personal macOS dotfiles and bootstrap scripts.
dotfiles/
├── home/ # stowed into $HOME
│ ├── .aliases
│ ├── .zshenv
│ └── .config/
│ ├── Brewfile
│ ├── direnv/
│ ├── ghostty/
│ ├── git/
│ ├── nix/
│ ├── zed/
│ └── zsh/
├── macos/
│ └── settings.sh # optional macOS defaults script
├── sandbox-image/
│ ├── Dockerfile
│ └── entrypoint.sh
├── vscode/ # stowed into VS Code's user config dir
│ ├── extensions.json
│ ├── keybindings.json
│ ├── mcp.json
│ └── settings.json
├── dotfiles # bootstrap and update script
└── sandbox # Docker-based project sandbox
- macOS only
- Admin access is helpful; some steps use
sudo - Give your terminal app Full Disk Access in System Settings -> Privacy & Security -> Full Disk Access
- If
gitis not available yet, runxcode-select --installfirst or letgittrigger Apple's Command Line Tools prompt
Clone the repo wherever you want. Both commands resolve their own location, so they do not require a fixed path.
mkdir -p ~/Code/personal
git clone https://github.com/urban/dotfiles.git ~/Code/personal/dotfiles
cd ~/Code/personal/dotfiles
./dotfiles initinit installs the bootstrap tools first, then stows the dotfiles. On a clean machine it will:
- install Xcode Command Line Tools if needed
- install Homebrew if needed
- install packages from
home/.config/Brewfile - install Python CLI tools with
uv - symlink
home/into$HOMEwith GNU Stow - symlink
vscode/into~/Library/Application Support/Code/User - install Nix if needed
- optionally run
macos/settings.sh
The script may prompt you to:
- back up files that would be replaced
- confirm system changes
- enter your password for
sudo
When it finishes, start a new shell so the stowed zsh config is loaded:
exec zshAfter that, dotfiles and sandbox are available as commands. home/.config/zsh/.zprofile adds the repo root to PATH when the dotfiles are stowed.
If you cloned over HTTPS, create an SSH key, add it to GitHub, then switch the repo remote to SSH.
From the repo root:
git remote set-url origin git@github.com:urban/dotfiles.gitIf you use services that need personal credentials, add them after setup. For example, vscode/mcp.json ships with blank values and needs your own API key.
dotfiles --help
dotfiles init
dotfiles update./dotfiles works from the repo root, and dotfiles works anywhere once the repo root is on PATH.
update is interactive. It can:
- pull the latest changes
- re-stow
home/ - re-stow
vscode/ - update Homebrew packages
sandbox runs a command in a Docker-based sandbox. Start Docker or OrbStack first.
sandbox
sandbox bash
sandbox node -v./sandbox works from the repo root, and sandbox works anywhere once the repo root is on PATH. Do not copy the script by itself; it expects sandbox-image/Dockerfile and sandbox-image/entrypoint.sh to live next to it in the repo.
What it does:
- creates a per-project
.sandbox/state directory - adds
/.sandbox/to the current project's.gitignore - creates persistent state dirs for bun, pnpm, GitHub CLI, and Codex
- creates a
sandbox-nix-storeDocker volume - builds the image from
sandbox-image/Dockerfile - runs the container with the current project mounted at
/app
On first run, the container entrypoint installs Nix and a few CLI tools, installs the latest npm and @openai/codex, prompts for Codex and GitHub auth if needed, configures Git author info, runs direnv allow when .envrc exists, then executes your command. With no command, it starts bash.