AI-first macOS setup for the laptop that drives devbox
One script installs everything that can be automated. An agent session, OMP or Claude Code with the
workstation-setup skill, walks you through the rest: sign-ins, approvals and keys. dot doctor is the acceptance
test for both.
🚀 Quick start · How it works · Commands · Files · Adding things
| Feature | What it gives you |
|---|---|
| One-command install | install.sh gets git, Homebrew and its bash, clones the repo and runs dot setup: shell, links, agents |
| Agent-guided rest | dot agent hands the manual steps to OMP or Claude Code; you click and approve, the agent verifies |
| Acceptance test | dot doctor checks the whole machine, and every ✗ comes with the command that fixes it |
| No private keys | SSH and commit signing go through the 1Password agent; ~/.ssh holds only .pub key selectors |
| Secrets in 1Password | Credential files are kept as 1Password Documents and restored with dot vault pull |
| Rendered identities | ~/.gitconfig and per-account SSH blocks come from devbox's identities.conf, never from git |
| Drift detection | dot doctor plus read-only --check modes for macOS defaults, Brewfiles and identities show what has moved |
Important
This repo is public and holds no secrets. A file that contains a credential gets a line in vault.list
and lives in 1Password; git identity is rendered from devbox's registry; no private key ever touches the disk.
Requires an Apple Silicon Mac on macOS 26+, an admin account, and the 1Password accounts that hold the SSH keys and
the Workstation vault.
# 1. Automated: Xcode CLT, clone to ~/projects/rozsival/dotfiles, Homebrew + its bash, then `dot setup`
# (bash -c, not curl | bash: the installers it starts read the terminal)
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/rozsival/dotfiles/main/install.sh)"
# 2. Guided: open Ghostty (it starts the new login shell), sign the harness in to your subscription, then start it
cd ~/projects/rozsival/dotfiles
omp login anthropic # Claude Pro/Max in the browser; for Claude Code instead: run `claude`, `/login`, `/exit`
bin/dot agent # or: bin/dot agent claude
# 3. Done when this passes
bin/dot doctorinstall.sh waits once for the Xcode CLT dialog, and Homebrew's installer and dot setup ask for your password.
dot setup is idempotent, but re-running one piece (dot brew, dot link, dot macos) is faster than running it all
again.
Warning
Run anything that can prompt for sudo or Touch ID in your own terminal: dot setup, dot brew, dot sync,
dot update and dot macos. An agent's shell has no TTY, so Homebrew's sudo fallback fails there and dot's own
sudo waits on a prompt no one sees.
flowchart LR
I["install.sh<br/>CLT, clone, Homebrew"] --> S["dot setup<br/>everything a script can do"]
S --> A["dot agent<br/>OMP / Claude Code<br/>+ workstation-setup skill"]
A <-->|" fix, re-check "| D["dot doctor<br/>acceptance test"]
Y(["you: sign-ins, approvals,<br/>1Password, App Store"]) -.-> A
Automated by install.sh: Xcode CLT → clone → Homebrew and its bash, which bin/dot runs on. Then by dot setup:
the Brewfile → Homebrew bash as the login shell → dot link → mise Node and rustup → the devbox clone and
its OMP preset, OMP, Claude Code, agent skills and moshi-hook → Touch ID for sudo → macOS defaults.
Guided by dot agent: the harness starts with setup/PROMPT.md and the
workstation-setup skill, runs dot doctor, and takes the failures in
phase order. It tells you exactly what to click or type, waits for you, then checks the result itself. It never reads a
secret's value.
Note
The harness needs a model before it can read the prompt, so sign it in first, in your own terminal. OMP:
omp login anthropic opens the browser for your Claude Pro/Max subscription; its preset (modelRoles) uses only
Anthropic models. Run omp login without an argument to pick another provider. Claude Code: run claude, complete
/login, then /exit. The other harness signs in later, in phase 7.
| # | Phase | What happens |
|---|---|---|
| 1 | 1Password | Sign in, Touch ID on, SSH agent and CLI integration on |
| 2 | Secret files | dot vault pull restores every vault.list file with its mode |
| 3 | devbox tooling | devbox install and devbox agent install: devbox and the omp/claude launchers on the PATH, gh shim, devbox-identities, .push.env |
| 4 | git & ssh identity | dot identities renders ~/.gitconfig, SSH blocks and allowed_signers |
| 5 | GitHub | gh auth login, SSH and signing checks, repos switched to SSH remotes |
| 6 | Tailscale & devbox | Tailnet login, herdr machine add devbox, devbox doctor laptop |
| 7 | Agents & phone | Login for the harness dot agent didn't start, Moshi pairing |
| 8 | Apps | dot brew, App Store apps via dot brew --mas, JetBrains IDEs, first-run approvals |
| 9 | Cloud & registries | gcloud, az, glab logins, only for what you use |
| 10 | Finish | dot doctor prints ✓ all checks passed |
dot is on the PATH once linked: ~/.local/bin/dot points at bin/dot, a bashly script built
from cli/. dot --help, dot <command> --help and dot help <command> show each command's options,
arguments, examples and environment variables (DOT_OP_ACCOUNT, DOT_OP_VAULT, DEVBOX_DIR). Tab completes
commands, options, allowed values and vault.list titles: the completion asks dot itself, so it never goes stale.
| Command | What it does |
|---|---|
dot setup |
Everything automatable; idempotent |
dot agent [omp|claude] |
Starts the guided setup in an agent harness (default: OMP) |
dot doctor |
Checks the whole machine and exits 1 while anything fails |
dot sync |
Fast-forwards this repo from origin, then dot link, dot brew and dot macos --check |
dot update |
Upgrades Homebrew, mise, OMP, Claude Code, skills and moshi-hook; clears completion caches. A failed step doesn't stop the rest; exits 1 at the end |
dot link [--dry-run] |
Symlinks home/ into ~, backing up what it replaces; copies seed/ where absent |
dot brew [--mas|--check|--cleanup] |
brew bundle for Brewfile or Brewfile.mas; lists what is missing, or installed but undeclared |
dot macos [--check] |
Applies macOS defaults, or reports drift without changing anything |
dot identities [--check] |
Renders git and SSH identity config from devbox's identities.conf |
dot vault [status|pull|push] [title…] |
Syncs the files in vault.list with 1Password Documents (default: status) |
Tip
Grant Ghostty App Management (System Settings → Privacy & Security). Without it macOS refuses Homebrew's changes to apps it did not install, and every such cask stops for Touch ID.
| Kind | Lives in | Mechanism | Examples |
|---|---|---|---|
| Tracked | home/ |
Symlinked file by file by dot link; editing in ~ edits the repo |
bash, shared git config, ~/.ssh/config, Ghostty, mise |
| Seeded | seed/ |
Copied once if absent; from then on the tool owns it | herdr |
| Rendered | nowhere in git | dot identities builds them from ~/.config/devbox/identities.conf |
~/.gitconfig, GitHub SSH blocks, allowed_signers, *.pub |
| Secret | 1Password Workstation vault |
dot vault pull/push, listed in vault.list |
identities.conf, secrets.env, GitHub App keys, .npmrc, OMP models.yml |
Changes travel through git. An edit to a tracked file is already in the repo: commit and push it. Another Mac
picks it up with dot sync, which refuses to run on uncommitted changes. dot doctor warns when the repo is ahead
of or behind origin. Seeded files never sync after the first copy, secrets go through dot vault, and dot macos
applies the defaults drift that dot sync reports.
Bash 5 from Homebrew, the same shell the devbox runs. Startup stays under 400 ms, and dot doctor measures it.
| File | Loaded by | Role |
|---|---|---|
env.sh |
Every shell, including agents' non-interactive | PATH with the devbox launchers first, then mise shims; no subprocesses |
interactive.sh |
Interactive shells | History, completion, starship prompt; slow … init output is cached |
aliases.sh |
Interactive shells | Only the aliases that history shows are in use |
~/.config/bash/local.sh |
Interactive shells | Machine-only lines; untracked |
Shared settings live in home/.config/git/config, which git reads as global from the XDG
path. Identity, signing and the per-account includeIf chain live in the rendered ~/.gitconfig, because devbox's
doctor laptop reads them with git config --global, which does not follow [include]. Agent sessions see neither:
their launcher points GIT_CONFIG_GLOBAL at the devbox agent config.
macos/defaults.sh mirrors this Mac's settings plus a security baseline: quarantine and disk-image
verification, hibernation and the firewall all on. Keys whose feature is gone in macOS 26/27 are dropped rather than
kept just in case. Everything works with SIP enabled, and dot macos --check is read-only.
devbox owns ~/.config/devbox/**, ~/.local/libexec/devbox-agent/**, ~/.local/libexec/devbox-identities and
~/.local/bin/devbox*. This repo never writes there, except to restore identities.conf and secrets.env from
1Password. It owns what devbox leaves to the laptop: ~/.ssh/config (tracked), the files dot identities renders
(~/.gitconfig, ~/.config/git/identities/*, ~/.ssh/config.d/identities, the id_*/signing_*.pub selectors,
allowed_signers) and the PATH line that puts the launchers first. devbox's laptop docs describe those files as
hand-written; here they are not. The OMP preset is devbox's (home/.omp/agent/config.yml), the same file the devbox
runs: dot setup copies it before OMP first starts, and dot doctor warns when the live file drifts from it.
| Path | Contents |
|---|---|
install.sh |
Fresh-Mac entry: Xcode CLT, clone, Homebrew + bash, dot setup |
bin/dot |
The CLI, generated by bashly; needs bash 4.2+, so Homebrew's |
cli/ |
Its source: bashly.yml, one partial per command, lib/ helpers |
Brewfile, Brewfile.mas |
Homebrew packages and casks; App Store apps |
home/ |
Symlinked into ~ file by file; includes the global dot agent skill |
seed/ |
Copied into ~ only when absent |
macos/defaults.sh |
macOS defaults; --check is read-only drift detection |
vault.list |
Secret files kept as 1Password Documents |
setup/PROMPT.md |
First message of the guided-setup session |
.agents/skills/ |
workstation-setup skill; .claude/skills/ symlinks it for Claude Code |
Makefile |
Repo tasks: make build (bashly), fmt, lint, check |
| To add | Do this |
|---|---|
| CLI or app | A line in Brewfile (App Store: Brewfile.mas), then dot brew |
dot command |
Edit cli/bashly.yml and the command's partial in cli/, then make build; update the dot skill |
| Third-party tap | Fully qualified entry with trusted: true, so only that formula is trusted |
| Dotfile | The file in home/ at its path relative to ~, then dot link |
| macOS setting | A pref line in macos/defaults.sh with this Mac's value, then dot macos --check |
| Secret file | A line in vault.list, then dot vault push <title> |
| Identity change | Edit ~/.config/devbox/identities.conf, then dot identities, devbox agent install, devbox sync identities and dot vault push devbox/identities.conf; a new app directory also needs its vault.list lines |
| Manual setup step | A dot doctor check with a fix hint, plus a phase entry in the workstation-setup skill |
Rules for agents changing this repo live in AGENTS.md.
| Item | Details |
|---|---|
| Maintainer | @rozsival (see CODEOWNERS) |
| Issues | GitHub Issues |
| Companion | devbox, the remote agent container this laptop drives |
| License | MIT |