https://github.com/26zl/macsmith
Forge a fresh Mac into a complete dev box, and keep it sharp. One-command install of Homebrew, Starship, language toolchains, and opt-in devops/netsec/crypto profiles. 'update' keeps everything current.
https://github.com/26zl/macsmith
apple-silicon automation cli developer-experience development devops dotfiles dotfiles-macos homebrew macos oh-my-zsh productivity setup-script shell starship sysadmin terminal zsh
Last synced: 24 days ago
JSON representation
Forge a fresh Mac into a complete dev box, and keep it sharp. One-command install of Homebrew, Starship, language toolchains, and opt-in devops/netsec/crypto profiles. 'update' keeps everything current.
- Host: GitHub
- URL: https://github.com/26zl/macsmith
- Owner: 26zl
- License: mit
- Created: 2025-10-08T13:45:34.000Z (8 months ago)
- Default Branch: main
- Last Pushed: 2026-05-01T21:10:25.000Z (about 2 months ago)
- Last Synced: 2026-05-01T23:32:25.806Z (about 2 months ago)
- Topics: apple-silicon, automation, cli, developer-experience, development, devops, dotfiles, dotfiles-macos, homebrew, macos, oh-my-zsh, productivity, setup-script, shell, starship, sysadmin, terminal, zsh
- Language: Shell
- Homepage:
- Size: 2.43 MB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# macsmith
```text
\ \ \
\ \ \
_ _ _ _\_\_\___
_ __ ___ __ _ ___ ___ _ __ ___ (_) |_| |__ | |
| '_ ` _ \ / _` |/ __/ __| '_ ` _ \| | __| '_ \ | |
| | | | | | (_| | (__\__ \ | | | | | | |_| | | | **|_________|
|_| |_| |_|\__,_|\___|___/_| |_| |_|_|\__|_| |_| * * **
* ** *
⚒ forge your Mac ⚒ * *
```
**Forge a fresh Mac into a complete dev box — and keep it sharp.**
One command installs Homebrew, Starship, language toolchains, and optional sysadmin profiles. A second command (`update`) keeps everything current.
[](https://github.com/26zl/macsmith/actions/workflows/macos-test.yml)
[](https://github.com/26zl/macsmith/actions/workflows/checks.yml)
[](https://github.com/26zl/macsmith/actions/workflows/security.yml)
[](https://opensource.org/licenses/MIT)

---
## Install
Pin to a release (recommended):
```bash
curl -fsSL https://raw.githubusercontent.com/26zl/macsmith//bootstrap.sh \
| MACSMITH_REF= zsh
```
Or clone and review:
```bash
git clone https://github.com/26zl/macsmith.git
cd macsmith
./install.sh
./dev-tools.sh # optional language toolchains
```
Pick a tag from [Releases](https://github.com/26zl/macsmith/releases).
## Daily use
```text
update [target] # upgrade everything (default) or a single target: brew/node/python/ruby/rust/swift/go/dotnet/nix/mas (try: update help)
verify # health-check every installed tool
versions # print versions on one screen
doctor # diagnose common setup issues (read-only)
upgrade # pull the latest macsmith release (SHA-256 verified against the release checksum)
sys-install # re-run install.sh (add/remove sysadmin profiles, pick up core updates)
dev-tools # re-run dev-tools.sh (add/remove language toolchains)
uninstall-profile # brew-uninstall a sysadmin profile's packages (power-user/crypto/netsec/devops/databases)
uninstall-nix # bundled macOS Nix uninstaller (--dry-run / --yes)
uninstall-macsmith # remove macsmith itself (keeps Homebrew, language tools, your customizations)
reload # reload ~/.zprofile and ~/.zshrc after editing either
```
## What you get
Everything optional is behind a y/n prompt with a sensible default (press Enter to accept). Defaults shown in brackets.
**Installed automatically** (core shell foundation):
- Xcode Command Line Tools, Homebrew, Starship prompt, zsh-syntax-highlighting, zsh-autosuggestions (both via Homebrew, no Oh My Zsh), FZF
- The `macsmith` maintenance binary at `~/.local/bin/macsmith`
- A managed `~/.zshrc` (your existing one is backed up with a timestamp)
**Asked per tool during `./install.sh`**:
- macOS package sources: `mas` **[N]**, `MacPorts` **[N]**, `Nix` **[N]**
- Sysadmin profiles: power-user CLI **[Y]** (btop, ripgrep, bat, gh, lazygit, tmux, neovim, …), crypto/secrets **[Y]** (age, sops, gnupg, pinentry-mac), netsec **[N]** (nmap, masscan, iperf3, Wireshark), devops/SRE **[N]** (kubectl, Terraform via HashiCorp tap, ansible, awscli, orbstack, …), databases **[N]** (mysql, postgresql)
**Asked per tool during `./dev-tools.sh`**:
- Languages **[Y]**: Python (pyenv + pipx + uv), Node (nvm + pnpm + bun), Ruby (chruby + ruby-install), Rust (rustup), Go
- Languages **[N]**: Swift (swiftly), Java (openjdk), .NET SDK, Conda/Miniforge, deno
- JVM extras batch **[N]**: Kotlin, Scala, Clojure, Gradle, Maven, Groovy
**Maintenance**: `update` keeps every formula, cask, and language runtime current; `verify` shows gaps. Project-local files (`package.json`, `go.mod`, `.swift-version`, …) are never touched.
## What changes on your machine
Concrete footprint before you commit to `curl | zsh`. Everything destructive to existing files creates a timestamped backup first.
**Always written** (critical install, no prompt):
- `~/.zshrc` — **overwritten** with macsmith's shell config. Previous file saved to `~/.zshrc.backup.YYYYMMDD_HHMMSS`. User-defined `alias`/`export` lines are harvested into `~/.zshrc.local` (secret-shaped exports — `*_TOKEN`, `*_SECRET`, `*_KEY` — are deliberately skipped).
- `~/.zprofile` — managed block appended between `# FINAL PATH CLEANUP` and `# End macsmith managed block` markers. Previous file saved to `~/.zprofile.backup.YYYYMMDD_HHMMSS`.
- `~/.local/bin/` — adds 3 binaries: `macsmith`, `uninstall-nix-macos`, `uninstall-macsmith`.
- `~/.local/share/macsmith/` — created. Stores install-state marker, version file, and mirror of all repo scripts (used by `upgrade` and `uninstall-macsmith`).
- `~/.config/starship.toml` — written **only if missing**. Existing configs are never overwritten.
- **Homebrew** — installed at `/opt/homebrew` (Apple Silicon) or `/usr/local` (Intel) if not already present. The Homebrew installer itself requests `sudo`.
**Written only if you say yes** (per-tool `[Y]`/`[N]` prompt):
- **Homebrew packages**, by profile:
- `power-user` **[Y]**: 24 formulae (btop, ripgrep, bat, gh, lazygit, tmux, neovim, chezmoi, …)
- `crypto/secrets` **[Y]**: 4 formulae (age, sops, gnupg, pinentry-mac)
- `netsec` **[N]**: 3 formulae + 1 cask (nmap, masscan, iperf3, Wireshark app) — strictly network-layer tools; web-app / DB-exploit scanners are deliberately excluded
- `devops/SRE` **[N]**: 17 formulae + 3 casks (kubectl, Terraform via `hashicorp/tap`, ansible, awscli, docker, orbstack, google-cloud-sdk, multipass, …)
- `databases` **[N]**: 2 formulae (mysql, postgresql@17)
- **Language toolchains** (via `./dev-tools.sh`, each one its own `[Y]`/`[N]` prompt):
- Python → `~/.pyenv/`
- Node.js → `~/.nvm/`
- Ruby → `~/.rubies/`, `~/.local/share/chruby/`, `~/.local/share/ruby-install/`
- Rust → `~/.rustup/`, `~/.cargo/`
- Swift → `~/.swiftly/`
- .NET → `/usr/local/share/dotnet/` (via brew cask; `sudo` for first install)
- Java (OpenJDK), Go, Conda/Miniforge, uv, bun, pnpm, deno — individual prompts
- **MacPorts** → `/opt/local/`. Every install and every update needs `sudo`.
- **Nix** → `/nix/` APFS volume + `/etc/nix/` + `LaunchDaemons` + `_nixbld1..32` users + `nixbld` group + edits to `/etc/synthetic.conf` and `/etc/fstab`. **System-wide, daemon-based, `sudo` required, 10–20 min.** Largest footprint of anything we offer.
**Never touched**:
- Existing Homebrew formulae/casks you installed yourself (`update` only upgrades; never uninstalls).
- Project-local files (`package.json`, `Gemfile`, `go.mod`, `.swift-version`, `.python-version`, `.nvmrc`, …).
- System Ruby at `/usr/bin/ruby`, system Python, macOS defaults, login items.
- `~/.ssh/`, `~/.gnupg/`, `~/.aws/`, and everything in `~/.config/` except `starship.toml` when it's missing.
- `/Applications/`, `/Library/`, `/System/`.
**Reversing it**:
- `uninstall-macsmith` — removes the 3 binaries, `~/.local/share/macsmith/`, the managed `.zprofile` block, and offers to restore `~/.zshrc` from the oldest non-macsmith backup. Does NOT touch Homebrew or language toolchains.
- `uninstall-profile ` — `brew uninstall` a sysadmin profile's formulae + casks.
- `uninstall-nix` — full Nix removal including the APFS volume (the volume-delete step always requires typing `yes` — `--yes` on everything else, never there).
- Language toolchains: removed by their own tools (`rm -rf ~/.pyenv`, `brew uninstall go`, `rustup self uninstall`, …).
## Why not just …
| Tool | macsmith adds |
| --- | --- |
| **`brew bundle`** | Language version managers, shell config, an `update` that understands every ecosystem |
| **`chezmoi`** | macsmith installs chezmoi itself for dotfile sync — they're orthogonal |
| **`nix-darwin`** | No Nix language to learn; imperative but idempotent |
| **Your own dotfiles repo** | A starting point + a maintenance loop. Fork it |
## Options
- `MACSMITH_REF=` — pin the bootstrap to a specific release (reproducible installs)
- `MACSMITH_UPDATE_CHECK=1` — opt in to a daily update check on shell start (off by default)
- `NONINTERACTIVE=1` — auto-answer "yes" to every prompt (for CI / unattended re-runs)
- `MACSMITH_FIX_RUBY_GEMS=1` — auto-fix Ruby gem permissions during `update` (on by default; set `0` to disable)
## Your own customizations
macsmith manages `~/.zshrc`. Put your aliases and exports in `~/.zshrc.local` — it's sourced last so your edits survive reinstalls. Fresh installs also harvest existing `alias`/`export` lines from your old `~/.zshrc` into `~/.zshrc.local` automatically; secret-shaped exports (`*_TOKEN`, `*_SECRET`, `*_KEY`, …) are deliberately skipped — grab those from the timestamped backup next to your new `~/.zshrc`.
**Prompt themes:** `starship preset --list` to browse, `starship preset -o ~/.config/starship.toml` to apply. Examples: `tokyo-night`, `gruvbox-rainbow`, `pastel-powerline`, `catppuccin-powerline`, `pure-preset`.
## Ghostty terminal (optional)
```bash
brew install --cask ghostty
mkdir -p ~/.config/ghostty
cp "Ghostty config.txt" ~/.config/ghostty/config
cp background/terminal-background.png ~/.config/ghostty/terminal-background.png
```
The bundled config auto-installs macsmith's terminfo over SSH, so `xterm-ghostty: unknown terminal type` never appears on remote hosts.
## Troubleshooting
**Garbled glyphs in the VS Code integrated terminal** (random characters render as the wrong bitmap — `Read` → `�ead`, broken powerline separators, mangled spinner emoji). This is the WebGL renderer's glyph-atlas getting corrupted by the Nerd Font / powerline glyphs and emoji that Starship and other tools emit — not a shell-config bug. Fix it in VS Code's `settings.json`:
```jsonc
"terminal.integrated.gpuAcceleration": "canvas",
"terminal.integrated.fontFamily": "MesloLGS NF"
```
`canvas` drops the buggy WebGL texture atlas while keeping 2D acceleration; pinning the font to an installed Nerd Font stops fallback rendering. Open a fresh terminal (or **Developer: Reload Window**) to apply. If it still corrupts, step down to `"gpuAcceleration": "off"` (pure DOM rendering, no GPU atlas at all).
## Requirements
macOS 13 Ventura or later. Apple Silicon or Intel. That's it.
## Uninstalling
Two bundled scripts, both defensive with `--dry-run` and `--yes` flags. Run `--dry-run` first to see exactly what will change.
### Remove macsmith itself
`uninstall-macsmith` removes what macsmith installed (binaries in `~/.local/bin/`, `~/.local/share/macsmith/`, the managed PATH block in `~/.zprofile`) and offers to restore `~/.zshrc` from the oldest non-macsmith-managed backup (skips `.zshrc.backup.*` files that look like they were made by a prior macsmith run so you get your original pre-macsmith config, not a macsmith template). Also offers to remove `~/.config/starship.toml`. It **keeps** Homebrew, any installed formulae/casks, language toolchains (pyenv/nvm/chruby/rustup/swiftly/go/…), `~/.zshrc.local`, and every file you created.
```bash
uninstall-macsmith --dry-run # show what will change
uninstall-macsmith # interactive
uninstall-macsmith --yes # non-interactive
```
### Remove Nix (macOS)
`uninstall-nix` cleanly removes a multi-user Nix install: launch daemons, `_nixbld*` users, `/etc/nix`, `/etc/synthetic.conf`, `/etc/fstab`, and the `Nix Store` APFS volume. Auto-detects the Determinate Systems installer and prefers `sudo /nix/nix-installer uninstall` when present.
```bash
uninstall-nix --dry-run
uninstall-nix
uninstall-nix --yes
```
Both scripts are installed to `~/.local/bin/` by `./install.sh`. From a clone, you can also run `./scripts/uninstall-macsmith.sh` or `./scripts/uninstall-nix-macos.sh` directly. **macOS-only.** The Nix script re-execs under `sudo`; the APFS volume deletion always requires interactive confirmation typed as `yes` — `--yes` on `uninstall-nix` skips the other prompts but never that one. Read the scripts before running. A reboot is recommended after uninstalling Nix.
## License
[MIT](LICENSE).
---
If macsmith saved you an afternoon, a ⭐ is the tip jar.
[](https://github.com/26zl/macsmith/stargazers)
[](https://github.com/26zl/macsmith/fork)