<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:media="http://search.yahoo.com/mrss/"><channel><title>一鍵搞定新 Mac - Bobo 的學思山丘</title><description>用 Homebrew Bundle、dotfiles、defaults write 腳本，四層自動化策略讓新 Mac 設定從半天縮短到 30 分鐘。不是工程師也能上手。</description><link>https://bobochen.dev/</link><item><title>新 Mac 開箱後，我怎麼 30 分鐘裝好所有東西</title><link>https://bobochen.dev/blog/mac-setup-automation-brewfile-dotfiles-guide/</link><guid isPermaLink="true">https://bobochen.dev/blog/mac-setup-automation-brewfile-dotfiles-guide/</guid><description>用 Homebrew Bundle、dotfiles、defaults write 腳本，四層自動化策略讓新 Mac 設定從半天縮短到 30 分鐘。不是工程師也能上手。</description><pubDate>Fri, 13 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&gt; 這是「一鍵搞定新 Mac」系列的第一篇，帶你建立整套自動化策略的全景圖。後續文章會針對每一層深入展開。

買了新 Mac，開心拆箱、過完設定精靈之後，接下來通常是最痛苦的時刻——一個一個裝回你熟悉的軟體、調回你習慣的設定。

Chrome、VS Code、iTerm2、Line、Notion⋯⋯光是想就累了。更別說那些藏在系統偏好裡的小設定：Dock 要自動隱藏、Finder 要顯示隱藏檔、觸控板的滑動方向⋯⋯

如果你有不只一台 Mac（公司的、家裡的），或是每隔幾年就會換一次電腦，這篇就是寫給你的。

我會用四個層級，帶你從「手動裝到哭」進化到「一行指令全搞定」。

## 全景圖：四層自動化策略

在開始之前，先看一下全貌。Mac 的個人化設定其實散落在四個地方：

| 層級     | 管什麼                   | 工具                  | 難度 |
| -------- | ------------------------ | --------------------- | ---- |
| 軟體安裝 | App、CLI 工具            | Homebrew Bundle       | ★☆☆  |
| 設定檔   | Shell、Git、編輯器設定   | Dotfiles + Git        | ★★☆  |
| 系統偏好 | Dock、Finder、鍵盤快捷鍵 | `defaults write` 腳本 | ★★☆  |
| 機敏資料 | SSH 金鑰、密碼、token    | 每台重產 + `*.local` 檔  | ★☆☆  |

每一層獨立處理，組合起來就是一套完整的自動化 setup。

## 第一層：Homebrew Bundle — 軟體一鍵安裝

[Homebrew](https://brew.sh/) 是 macOS 上最主流的套件管理工具。即使你不是工程師，只要會在終端機貼指令，就能用它一次裝完所有軟體。

**在舊電腦上匯出清單**：

```bash
brew bundle dump --file=~/Brewfile --describe
```

這會產生一個 `Brewfile`，記錄你目前裝了什麼：

```ruby
# CLI 工具
brew &quot;git&quot;           # 版本控制
brew &quot;node&quot;          # JavaScript runtime
brew &quot;zsh&quot;           # Shell

# GUI 應用程式（透過 cask）
cask &quot;google-chrome&quot;
cask &quot;visual-studio-code&quot;
cask &quot;iterm2&quot;
cask &quot;raycast&quot;
cask &quot;notion&quot;
cask &quot;line&quot;

# Mac App Store 的 App（透過 mas）
mas &quot;Xcode&quot;, id: 497799835
mas &quot;Keynote&quot;, id: 409183694
```

&gt; **兩個之後會踩的坑，先記著**：① 如果 `dump` 出來的清單裡有 `vscode &quot;...&quot;` 行，建議刪掉——VS Code 自己的 Settings Sync 已經在管擴充套件，留著會兩邊重複（本系列有一篇專門講怎麼清掉這些白工）。② 上面的 `mas` 行（Mac App Store 的 App）在較新的 macOS 上 `mas install` 會需要 sudo，跑全自動腳本時可能卡住；保守做法是 Brewfile 只管 `cask`，App Store 的 App 先到商店登入再手動裝。

**在新電腦上一鍵安裝**：

```bash
# 先裝 Homebrew（新電腦必須）
/bin/bash -c &quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)&quot;

# 然後一行搞定所有軟體
brew bundle --file=~/Brewfile
```

就這樣。CLI 工具、GUI App、甚至 Mac App Store 的軟體，全部一次裝回來。

### 3 分鐘快速上手

裝完 Homebrew 後，你只需要記住這幾個指令：

```bash
brew install &lt;套件名&gt;     # 安裝 CLI 工具
brew install --cask &lt;app&gt; # 安裝 GUI App
brew list                 # 看裝了什麼
brew update &amp;&amp; brew upgrade  # 更新所有套件
brew bundle dump --file=~/Brewfile  # 匯出目前的軟體清單
brew bundle --file=~/Brewfile       # 從清單一鍵安裝
```

**最小可用流程**：

1. 打開「終端機」（在 Spotlight 搜尋 &quot;Terminal&quot;）
2. 貼上 Homebrew 安裝指令，等它跑完
3. 執行 `brew install --cask google-chrome` 試試看——Chrome 會自動下載安裝，不用開瀏覽器下載 .dmg

&gt; **給非工程師的小提醒**：`Brewfile` 就是一份「軟體清單」，純文字格式。你可以用任何文字編輯器打開它，手動新增或刪除不需要的軟體。

## 第二層：Dotfiles — 設定檔版本控制

macOS（和大部分 Unix 系統）的應用程式設定檔都放在家目錄，檔名以 `.` 開頭（所以叫 dotfiles），例如：

- `.zshrc` — Shell 的設定（別名、環境變數）
- `.gitconfig` — Git 設定（使用者名稱、預設編輯器）
- `.ssh/config` — SSH 連線設定

這些檔案平常看不到（macOS 預設隱藏），但它們決定了你的工作環境長什麼樣子。

### 最簡單的做法：Git repo + 手動 symlink

```bash
# 1. 建立 dotfiles 資料夾
mkdir ~/dotfiles &amp;&amp; cd ~/dotfiles
git init

# 2. 把設定檔搬進來
cp ~/.zshrc ~/dotfiles/
cp ~/.gitconfig ~/dotfiles/

# 3. 建立 symlink（讓系統讀到正確位置）
ln -sf ~/dotfiles/.zshrc ~/.zshrc
ln -sf ~/dotfiles/.gitconfig ~/.gitconfig

# 4. 推到 GitHub 保存
git add -A &amp;&amp; git commit -m &quot;initial dotfiles&quot;
```

### 進階：用 chezmoi 管理

如果你有多台電腦、或是設定檔裡有些值每台不同（例如工作用的 Git email vs 個人 email），[chezmoi](https://github.com/twpayne/chezmoi) 是目前功能最完整的 dotfiles 管理工具。

```bash
# 安裝
brew install chezmoi

# 初始化（第一台電腦）
chezmoi init
chezmoi add ~/.zshrc
chezmoi add ~/.gitconfig
chezmoi cd  # 進入 chezmoi 管理的資料夾
git add -A &amp;&amp; git commit -m &quot;initial&quot; &amp;&amp; git push

# 在新電腦上，一行搞定
sh -c &quot;$(curl -fsLS get.chezmoi.io)&quot; -- init --apply your-github-username
```

### chezmoi 3 分鐘快速上手

```bash
chezmoi add &lt;檔案&gt;      # 把檔案加入管理
chezmoi edit &lt;檔案&gt;     # 編輯受管理的檔案
chezmoi apply           # 把所有變更套用到系統
chezmoi diff            # 預覽變更（不實際套用）
chezmoi update          # 從 GitHub 拉最新版本並套用
chezmoi cd              # 進入 chezmoi 的 source 資料夾
```

**最小可用流程**：

1. `chezmoi init` — 初始化
2. `chezmoi add ~/.zshrc` — 加入你最重要的設定檔
3. `chezmoi cd` → `git add -A &amp;&amp; git commit -m &quot;add zshrc&quot; &amp;&amp; git push` — 推到 GitHub
4. 換台電腦 → `chezmoi init --apply your-github-username` — 一行還原

chezmoi 的殺手級功能是**模板**——同一份 `.gitconfig` 可以根據機器自動填入不同的 email。但這是進階用法，先把基本流程跑通就很夠用了。

另一個輕量選擇是 [GNU Stow](https://www.gnu.org/software/stow/)，它只做一件事：根據資料夾結構自動建立 symlink。沒有模板、沒有加密，但也因此幾乎不用學。

## 第三層：macOS 系統偏好 — defaults write 腳本

macOS 的系統偏好設定（Dock 大小、Finder 行為、觸控板⋯⋯）其實都存在 plist 檔案裡，可以用 `defaults` 指令讀寫。

把你喜歡的設定寫成一個 shell script，換電腦時跑一次就好：

```bash
#!/bin/bash
# macos-defaults.sh — 我的 macOS 偏好設定

# === Dock ===
defaults write com.apple.dock autohide -bool true          # Dock 自動隱藏
defaults write com.apple.dock tilesize -int 48              # 圖示大小
defaults write com.apple.dock minimize-to-application -bool true  # 最小化到 App 圖示

# === Finder ===
defaults write com.apple.finder ShowPathbar -bool true      # 顯示路徑列
defaults write com.apple.finder ShowStatusBar -bool true    # 顯示狀態列
defaults write com.apple.finder AppleShowAllFiles -bool true  # 顯示隱藏檔

# === 鍵盤 ===
defaults write NSGlobalDomain KeyRepeat -int 2              # 按鍵重複速度（越小越快）
defaults write NSGlobalDomain InitialKeyRepeat -int 15      # 按鍵重複延遲

# === 觸控板 ===
defaults write com.apple.AppleMultitouchTrackpad TrackpadThreeFingerDrag -bool true  # 三指拖曳

# === 截圖 ===
defaults write com.apple.screencapture location -string &quot;~/Screenshots&quot;  # 截圖存到指定資料夾
defaults write com.apple.screencapture type -string &quot;png&quot;    # 截圖格式

# 重新啟動受影響的服務
killall Dock
killall Finder
killall SystemUIServer

echo &quot;macOS 偏好設定已套用！部分設定需要登出再登入才會生效。&quot;
```

我把用了十幾年的 Mac 設定全部匯出，檔案竟然有 5.3MB。
![用了十幾年的 Mac 匯出 defaults，檔案大小 5.3MB](mac-setup-automation-brewfile-dotfiles-guide-fig-2.webp)

匯出的 macos-defaults-backup.plist 內容竟然有 14 萬多行！
![macos-defaults-backup.plist 內容超過 14 萬行](mac-setup-automation-brewfile-dotfiles-guide-fig-1.webp)

（這正是為什麼**別**直接拿 `defaults read` 的全量匯出當備份——這 5.3MB、14 萬行裡絕大多數是各個 app 的暫存狀態，雜訊遠多於訊號。一份你看得懂的手寫 `defaults.sh` 反而更可靠、更好維護。本系列後面有一篇專門拆解「5.3MB 的 plist 為什麼不如 130 行的 shell script」。）

### 怎麼發現更多可設定的項目？

```bash
# 匯出目前所有設定（超長，但很有參考價值）
defaults read &gt; ~/current-defaults.txt

# 查看特定 App 的設定
defaults read com.apple.dock
```

推薦參考 [mathiasbynens/dotfiles](https://github.com/mathiasbynens/dotfiles) 的 `.macos` 檔案，裡面有幾百行精心整理的設定，是這個領域的經典。你不需要全用，挑你需要的就好。

## 第四層：機敏資料 — 小心處理

SSH 金鑰、API token、密碼這類東西**不應該放在 Git repo 裡**。但與其急著找一個「同步機密」的工具，我更建議先問一個問題：**這東西能不能重新產生？** 答案會決定你要不要費工去加密、去搬移。

我把機密分成兩桶：

- **桶 1：可以重新產生**——SSH 私鑰、GPG 簽章金鑰、GitHub token、大多數 API token。
  這類東西**每台新機重產一組就好**，不要搬舊的。對 SSH key 來說這本來就是資安最佳實踐：私鑰永遠不離開那台機器，哪台退役就只撤銷那一把。
- **桶 2：不可以重新產生**——換了就回不來的東西（某些不可重發的 license、2FA 備份碼……）。
  這才是真正要小心保存的，放在 `*.local` 檔案裡（例如 `~/.gitconfig.local` 放 email、`~/.zshenv.local` 放 token）。這些檔**不進 Git、每台手動建**。

**SSH 金鑰怎麼處理（重產派做法）**：新電腦不要從舊電腦搬 `~/.ssh/`。裝好 `gh` 後跑 `gh auth login`、選 SSH，它會幫你**產一把全新的 key 並自動把公鑰上傳到 GitHub**——一步同時搞定認證又免搬私鑰。（這步是 private repo 在新機的第一道關卡，本系列後面有專篇細講。）

&gt; **我自己不用 1Password**（也不用其他商業密碼管理器）。如果你已經在用 1Password / Bitwarden，它們確實能同步密碼、也支援 SSH Agent，照用沒問題；但它**不是必需品**。光是「可重產的每台重產、不可重產的放 `*.local`」，就能覆蓋大多數人的需求。
&gt;
&gt; 至於免每次重打 SSH key 密碼——用 **macOS 內建的鑰匙圈（Keychain）** 就好：`ssh-add --apple-use-keychain ~/.ssh/id_ed25519`，不必為了這個裝密碼管理器。

&gt; **原則**：如果一個檔案裡有密碼或 token，它就不該出現在 GitHub 上，即使是 private repo。chezmoi 的 [age](https://github.com/FiloSottile/age) 加密只有在你的「桶 2」長大到有「不可重產**又**必須版控」的機密時才需要——桶 2 是空的，你連 age 都不用碰。

## 組合技：一鍵 Setup 腳本

把前面四層串起來，就是一個完整的新電腦 setup 腳本：

```bash
#!/bin/bash
# install.sh — 新 Mac 一鍵配置

set -e  # 遇到錯誤就停止

echo &quot;=== Step 1: 安裝 Homebrew ===&quot;
/bin/bash -c &quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)&quot;
eval &quot;$(/opt/homebrew/bin/brew shellenv)&quot;   # Apple Silicon：把 brew 加進當前 shell

echo &quot;=== Step 2: GitHub 認證 + 產一把新 SSH key ===&quot;
# 這步要先做：dotfiles 放 private repo 的話，沒先認證根本 clone 不下來。
# gh auth login 選 SSH 會自動產一把新 key 並上傳公鑰到 GitHub，一步搞定認證又免搬私鑰。
brew install gh chezmoi
gh auth login   # → GitHub.com → SSH → &quot;Generate a new SSH key?&quot; → Yes

echo &quot;=== Step 3: 套用 dotfiles（順手把 Brewfile 一起拉下來）===&quot;
chezmoi init --apply your-github-username
# 或者如果用 Stow：
# cd ~/dotfiles &amp;&amp; stow zsh git ssh

echo &quot;=== Step 4: 安裝所有軟體 ===&quot;
brew bundle --file=&quot;$(chezmoi source-path)/Brewfile&quot;

echo &quot;=== Step 5: 套用 macOS 偏好設定 ===&quot;
chmod +x &quot;$(chezmoi source-path)/macos-defaults.sh&quot;
&quot;$(chezmoi source-path)/macos-defaults.sh&quot;

echo &quot;=== Done! ===&quot;
echo &quot;記得手動處理：&quot;
echo &quot;  1. 建立 ~/.gitconfig.local（email）和 ~/.zshenv.local（GITHUB_TOKEN 等 secrets）&quot;
echo &quot;  2. 登入 iCloud、VS Code Settings Sync 等 App 內建同步&quot;
echo &quot;  3. 登出再登入讓所有設定生效&quot;
```

&gt; 注意 **Step 2 的順序**：很多人（包括早期的我）會把「裝軟體」放在最前面，結果新機要 clone 自己的 **private** dotfiles repo 時，卡在沒有認證。先用 `gh auth login`（選 SSH、產新 key）把認證和金鑰一次搞定，後面才會順。這個「新機第一步認證的雞生蛋」本系列後面有專篇細講。

## 別忘了這些 App 自帶的同步功能

有些軟體有內建的設定同步，善用它們可以省更多事：

| 軟體        | 同步方式                               |
| ----------- | -------------------------------------- |
| VS Code     | 內建 Settings Sync（登入 GitHub 即可） |
| Chrome      | 登入 Google 帳號同步書籤、擴充套件     |
| Raycast     | 內建 Cloud Sync                        |
| 1Password   | 雲端同步                               |
| Claude Code | 複製 `~/.claude/` 資料夾               |

## 我的建議：從 Brewfile 開始就好

如果上面看起來很多，不用一次全做。我的建議是：

1. **今天就做**：跑 `brew bundle dump --file=~/Brewfile`，把軟體清單匯出來
2. **這週做**：建一個 `dotfiles` Git repo，先放 `.zshrc` 和 `.gitconfig`
3. **有空再做**：慢慢累積 `macos-defaults.sh`，遇到什麼設定就加什麼

不需要一開始就完美。每次你調了一個設定、裝了一個新工具，順手更新 dotfiles repo，半年後你就會有一套很完整的自動化配置。

下次換電腦，你會感謝現在的自己。</content:encoded><media:content url="https://bobochen.dev/_astro/cover.CsQeQ1bL.webp" medium="image"/><category>macOS</category><category>Homebrew</category><category>dotfiles</category><category>自動化</category><category>效率工具</category><enclosure url="https://bobochen.dev/_astro/cover.CsQeQ1bL.webp" length="0" type="image/png"/></item><item><title>終端機不可怕：給非工程師的 macOS Terminal 入門</title><link>https://bobochen.dev/blog/macos-terminal-beginners-guide-not-scary/</link><guid isPermaLink="true">https://bobochen.dev/blog/macos-terminal-beginners-guide-not-scary/</guid><description>終端機不是工程師專屬工具。這篇用生活化比喻帶你認識 5 個基本指令，從打開 Terminal 到實際操作，讓你不再對黑底白字的畫面感到害怕。</description><pubDate>Fri, 13 Mar 2026 00:00:00 GMT</pubDate><content:encoded>你一定在電影裡看過這個畫面：駭客關著燈、戴著連帽外套，面前一片黑底白字的螢幕，游標瘋狂閃爍，手指敲得劈哩啪啦響，幾秒後螢幕跳出一行大大的「ACCESS GRANTED」。

那片看起來很神祕的黑畫面，其實就是**終端機（Terminal）**——而且你的 Mac 裡就內建了一個。

也正因為電影都這樣演，很多人第一次打開它、看到游標在黑底白字上一閃一閃，腦中只會冒出一個念頭：「這是不是只有高手能碰？我隨便打錯一個字，會不會把整台電腦搞壞？」

不會。而且它遠比電影演的還要平易近人——終端機說穿了，只是另一種跟電腦溝通的方式，在某些情況下，還比用滑鼠點來點去快得多。

這篇寫給完全沒用過終端機的人：設計師、行銷、PM、或者任何想裝 Homebrew 卻被第一步「打開終端機」嚇到的朋友。

## 終端機到底是什麼？

你平常用 Mac，打開 Finder 瀏覽檔案、拖拉資料夾、雙擊開啟 App——這些都是透過圖形介面（GUI）在跟電腦溝通。

終端機（Terminal）是另一種溝通方式：用打字的。

如果圖形介面是「去餐廳看菜單、用手指點餐」，終端機就是「直接跟廚師說：我要一份炒飯、不要蔥、加辣」。

結果一樣，都能吃到飯。只是溝通的方式不同。

為什麼有人偏好用說的？因為有些事情用說的比較快。你不用翻好幾頁菜單，不用等服務生過來，直接開口就搞定。終端機也是這樣——很多操作一行指令就完成了，用滑鼠可能要點五六下。

## 怎麼打開終端機

Mac 內建就有終端機，不用額外安裝。

**方法一：Spotlight 搜尋**
按 `Cmd + 空白鍵`（就是你平常搜尋東西的快捷鍵），輸入 `Terminal`，按 Enter。

就這樣。它會打開一個視窗，裡面有一行字和一個閃爍的游標。那行字大概長這樣：

```
bobo@MacBook-Pro ~ %
```

這表示「你是 bobo，目前在家目錄，可以開始輸入指令了」。`%` 後面就是你打字的地方。

**方法二：從 Finder 開啟**
打開 Finder → 應用程式 → 工具程式 → 終端機。

**進階選擇：iTerm2**
Mac 內建的 Terminal 完全夠用，但如果你之後用得比較多，可以試試 [iTerm2](https://iterm2.com/)。它是免費的替代終端機，功能更豐富（分割畫面、搜尋歷史指令等等）。不急，之後再說。

## 5 個最基本的指令

接下來的每個指令，我都會告訴你「這等於在 Finder 裡做什麼」，讓你有個對照。

### 1. `pwd` — 我現在在哪裡？

```bash
pwd
```

輸出結果像這樣：

```
/Users/bobo
```

`pwd` 是 &quot;print working directory&quot; 的縮寫，意思是「顯示我目前在哪個資料夾」。

**Finder 對照**：就是你看 Finder 視窗上方的路徑列——告訴你現在打開的是哪個資料夾。

這個指令完全安全，它只是「看一下」，不會改變任何東西。迷路的時候打一下，就知道自己在哪了。

### 2. `ls` — 這裡有什麼東西？

```bash
ls
```

輸出可能長這樣：

```
Desktop    Documents  Downloads  Music     Pictures
```

`ls` 是 &quot;list&quot; 的縮寫，意思是「列出目前資料夾裡有什麼」。

**Finder 對照**：就是你打開一個資料夾後，看到裡面所有檔案和子資料夾的清單。

加個參數可以看到更多細節：

```bash
ls -la
```

這會顯示檔案大小、修改日期、權限等資訊。`-l` 是「用詳細清單顯示」，`-a` 是「連隱藏檔也顯示」。

同樣完全安全，只是在看，不會動到任何檔案。

### 3. `cd` — 移動到另一個資料夾

```bash
cd Documents
```

`cd` 是 &quot;change directory&quot; 的縮寫，意思是「切換到某個資料夾」。

**Finder 對照**：就是你在 Finder 裡雙擊一個資料夾打開它。

幾個常用的寫法：

```bash
cd Documents          # 進入目前資料夾裡的 Documents
cd ~/Desktop          # 直接跳到桌面（~ 代表你的家目錄）
cd ..                 # 回到上一層（就像按 Finder 的「返回」按鈕）
cd                    # 不加任何東西，直接回到家目錄
```

那個 `~` 符號代表你的家目錄（通常是 `/Users/你的使用者名稱`）。你可以把它想成「我家的地址」，不管你在哪裡，`cd ~` 都能帶你回家。

### 4. `mkdir` — 建立新資料夾

```bash
mkdir my-project
```

`mkdir` 是 &quot;make directory&quot; 的縮寫，意思是「在目前位置建立一個新資料夾」。

**Finder 對照**：就是在 Finder 裡按右鍵 →「新增檔案夾」，然後打個名字。

想一次建好多層？加個 `-p`：

```bash
mkdir -p projects/2026/march
```

這會一次建出三層資料夾，就算 `projects` 和 `2026` 還不存在也沒關係。在 Finder 裡你得一層一層建，終端機一行搞定。

### 5. `cp` — 複製檔案

```bash
cp notes.txt notes-backup.txt
```

`cp` 是 &quot;copy&quot; 的縮寫。上面這行的意思是「把 notes.txt 複製一份，叫做 notes-backup.txt」。

**Finder 對照**：就是選一個檔案 → `Cmd + C` → `Cmd + V`，然後改名。

想複製整個資料夾？加個 `-r`（recursive，遞迴的意思，就是「連裡面的東西也一起複製」）：

```bash
cp -r my-project my-project-backup
```

## 哪些指令是安全的？哪些要小心？

這大概是新手最擔心的問題了。讓我直接列清楚。

### 唯讀、安全的指令（隨便打都不會壞）

| 指令             | 做什麼                                                            |
| ---------------- | ----------------------------------------------------------------- |
| `pwd`            | 顯示目前路徑                                                      |
| `ls`             | 列出檔案清單                                                      |
| `cat 檔案名稱`   | 顯示檔案內容（cat 是 &quot;concatenate&quot; 的縮寫，但通常就拿來看檔案用） |
| `which 程式名稱` | 查某個程式安裝在哪裡                                              |
| `man 指令名稱`   | 看某個指令的說明書（按 `q` 離開）                                 |

這些指令只會「看」，不會「改」。就算打錯了，頂多是出現一行錯誤訊息，不會發生什麼壞事。

### 要小心的指令

| 指令            | 為什麼要小心                                       |
| --------------- | -------------------------------------------------- |
| `rm 檔案名稱`   | 刪除檔案，而且不會進垃圾桶，直接消失               |
| `rm -rf 資料夾` | 刪除整個資料夾和裡面所有東西，一樣不進垃圾桶       |
| `sudo 指令`     | 用管理員權限執行，可以動系統檔案。會要求輸入密碼   |
| `mv`            | 移動或更名檔案。如果目的地已有同名檔案，會直接覆蓋 |

最重要的一條規則：**`rm` 刪除的檔案不會進垃圾桶**。在 Finder 裡刪東西你還能從垃圾桶撈回來，但 `rm` 是真的刪掉。所以用之前多看一眼，確定你刪的是對的檔案。

`sudo` 的意思是 &quot;superuser do&quot;——用最高權限執行。有些安裝指令需要它，但如果你不確定一個指令在幹嘛，加上 `sudo` 之前請三思。它就像你拿到了整棟大樓的萬能鑰匙，能開任何門，當然也能搞砸任何房間。

## 從網路上複製指令時，請注意這些事

裝軟體、跟著教學做的時候，免不了要從網頁上複製指令貼到終端機。這裡有幾個保護自己的習慣：

**1. 先讀再貼**

不要看到指令就無腦複製貼上。至少掃一眼裡面有沒有 `rm`、`sudo`、或是你看不懂的部分。如果看不懂整行在幹嘛，Google 一下或問 AI 都好。

**2. 小心隱藏字元**

有些網站複製文字時會帶入看不見的字元。安全起見，可以先貼到純文字編輯器（像「記事本」或 VS Code）確認內容，再貼到終端機。

**3. 注意指令來源**

官方文件、GitHub 上的知名專案，通常是安全的。但隨便某個論壇裡的一行指令？稍微謹慎一點。

**4. 不確定就加 `echo`**

在指令前面加上 `echo`，它只會「印出這行字」而不會真的執行。例如：

```bash
echo rm -rf ~/Downloads/temp
```

這只會顯示 `rm -rf ~/Downloads/temp` 這串文字，不會真的刪除任何東西。先看一下指令長什麼樣子，確認沒問題再拿掉 `echo` 執行。

## 實戰練習：動手試試看

理論講夠了，來實際操作。打開終端機，跟著做一次：

**第一步：確認你在哪裡**

```bash
pwd
```

你應該會看到類似 `/Users/你的名字` 的路徑。

**第二步：建立一個練習用的資料夾**

```bash
mkdir terminal-practice
```

**第三步：進入這個資料夾**

```bash
cd terminal-practice
```

再打一次 `pwd` 確認——你應該會看到路徑變成 `/Users/你的名字/terminal-practice`。

**第四步：建立一個文字檔**

```bash
echo &quot;哈囉，這是我用終端機建立的第一個檔案！&quot; &gt; hello.txt
```

`echo` 會把引號裡的文字「輸出」，`&gt;` 的意思是「把輸出寫進檔案裡」。這行合在一起就是「建立一個叫 hello.txt 的檔案，內容是那句話」。

**Finder 對照**：就像你打開文字編輯器，打一行字，然後存檔。

**第五步：確認檔案建好了**

```bash
ls
```

你應該會看到 `hello.txt`。

**第六步：查看檔案內容**

```bash
cat hello.txt
```

終端機會印出：`哈囉，這是我用終端機建立的第一個檔案！`

**第七步：複製一份備份**

```bash
cp hello.txt hello-backup.txt
```

再打一次 `ls`，你會看到兩個檔案。

**恭喜，你剛剛用終端機完成了建資料夾、建檔案、看內容、複製檔案。** 整個過程沒有碰到滑鼠。

想在 Finder 裡確認嗎？打開 Finder，進入你的家目錄，你會看到 `terminal-practice` 資料夾就在那裡——終端機和 Finder 看到的是同一個世界，只是觀看的角度不同。

## 清理練習檔案（選做）

如果你想刪掉練習用的檔案和資料夾：

```bash
cd              # 先回到家目錄
rm -r terminal-practice   # 刪除整個練習資料夾
```

注意：這裡用了 `rm -r`，它會刪除資料夾和裡面所有東西，而且不會進垃圾桶。因為只是練習檔案，刪掉沒關係。但對於重要的檔案，務必確認清楚再刪。

## 常見問題

**Q：打錯指令會怎樣？**
A：通常只會出現一行錯誤訊息，像是 `command not found`（找不到這個指令）或 `No such file or directory`（沒有這個檔案或資料夾）。電腦不會爆炸，你不會搞壞什麼。按上方向鍵（↑）可以叫出上一條指令，修改後重新執行。

**Q：怎麼取消正在執行的指令？**
A：按 `Ctrl + C`。這是終端機裡的「我不要了，停下來」按鈕。

**Q：畫面太亂了怎麼辦？**
A：輸入 `clear` 或按 `Cmd + K`，畫面就會清乾淨。指令歷史還在，只是畫面變乾淨了。

**Q：怎麼看之前打過什麼指令？**
A：按上方向鍵（↑）可以一條一條往回翻。或者輸入 `history` 看完整紀錄。

## 下一步：裝 Homebrew

如果你是因為想安裝 Homebrew 才點進這篇文章，那恭喜——你已經準備好了。

Homebrew 是 macOS 上最主流的套件管理工具，可以讓你用一行指令安裝各種軟體，不用再去官網下載 .dmg 檔案。裝法就是打開終端機、貼一行指令、等它跑完。

我在[新 Mac 開箱後，我怎麼 30 分鐘裝好所有東西](/blog/mac-setup-automation-brewfile-dotfiles-guide)裡詳細寫了 Homebrew 的使用方式，以及怎麼用它一鍵安裝所有軟體。

現在你已經不怕終端機了，那篇裡的每一行指令你都看得懂。

---

終端機真的沒那麼可怕。它就是一個打字版的 Finder——你用文字告訴電腦要做什麼，電腦用文字回答你。

一開始可能會覺得慢，因為你需要記指令。但用一陣子之後，你會發現很多事情用終端機做比用滑鼠快得多。而且，當你需要照著教學安裝某個工具、或是跟工程師溝通的時候，你會慶幸自己懂這些基本功。

五個指令而已。`pwd`、`ls`、`cd`、`mkdir`、`cp`。記住這五個，你就已經可以在終端機裡自由移動了。</content:encoded><media:content url="https://bobochen.dev/_astro/cover.C11QAwD8.webp" medium="image"/><category>macOS</category><category>終端機</category><category>入門</category><category>Homebrew</category><enclosure url="https://bobochen.dev/_astro/cover.C11QAwD8.webp" length="0" type="image/png"/></item><item><title>從零開始的 Mac 開發環境：Brewfile 完全指南</title><link>https://bobochen.dev/blog/brewfile-beginner-guide-mac-dev-setup/</link><guid isPermaLink="true">https://bobochen.dev/blog/brewfile-beginner-guide-mac-dev-setup/</guid><description>什麼是 Brewfile？怎麼建第一份？哪些工具每個開發者都該裝？一篇搞懂 Homebrew 的套件清單管理，換電腦再也不用一個一個手動安裝。</description><pubDate>Fri, 13 Mar 2026 00:00:00 GMT</pubDate><content:encoded>如果你剛拿到一台新 Mac，或者想把開發環境「版本控制」起來，Brewfile 是你該認識的第一個工具。

## Homebrew 是什麼？

[Homebrew](https://github.com/Homebrew/brew) 是 macOS 上最主流的套件管理工具，讓你用一行指令安裝 CLI 工具、桌面應用程式、甚至 VS Code extensions。

安裝 Homebrew：

```bash
/bin/bash -c &quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)&quot;
```

裝完之後，安裝軟體就是一行指令的事：

```bash
brew install git        # CLI 工具
brew install --cask firefox  # 桌面 App
```

## Brewfile 是什麼？

Brewfile 就是一份「軟體清單」，把你所有用 Homebrew 安裝的東西記錄在一個檔案裡。換電腦時，一行指令就能全部裝回來。

你可以把它想成「開發環境的 package.json」。

## 3 分鐘快速上手

### Step 1：產生你的第一份 Brewfile

```bash
brew bundle dump --file=~/Brewfile
```

這會掃描你目前已安裝的所有 Homebrew 套件，自動產生一份 Brewfile。

### Step 2：看看裡面有什麼

```bash
cat ~/Brewfile
```

你會看到四種類型的項目：

```ruby
tap &quot;homebrew/cask&quot;          # 第三方套件來源
brew &quot;git&quot;                   # CLI 工具
cask &quot;firefox&quot;               # 桌面 App
vscode &quot;dbaeumer.vscode-eslint&quot;  # VS Code 擴充（可選）
```

### Step 3：在新電腦上還原

把 Brewfile 複製到新電腦，然後：

```bash
brew bundle install --file=~/Brewfile
```

就這樣，所有工具一次裝完。

## 我推薦每個開發者都該有的基礎工具

以下是我自己 Brewfile 裡最常用的工具，依用途分類：

### Git 相關

```ruby
brew &quot;git&quot;          # 版本控制
brew &quot;gh&quot;           # GitHub CLI，PR、issue 都在終端搞定
brew &quot;lazygit&quot;      # Git 的 TUI 介面，超直覺
```

### 終端效率

```ruby
brew &quot;fzf&quot;          # 模糊搜尋，找檔案、切分支都靠它
brew &quot;ripgrep&quot;      # 比 grep 快 10 倍的搜尋
brew &quot;zoxide&quot;       # 智慧 cd，記住你常去的目錄
brew &quot;starship&quot;     # 好看又實用的 shell prompt
brew &quot;tmux&quot;         # 終端分割、session 管理
```

### 開發工具

```ruby
brew &quot;fnm&quot;          # Node.js 版本管理（比 nvm 快）
brew &quot;jq&quot;           # JSON 處理
brew &quot;direnv&quot;       # 自動載入 .envrc 環境變數
brew &quot;just&quot;         # 比 Makefile 好讀的 task runner
```

### 桌面 App

```ruby
cask &quot;visual-studio-code&quot;    # 編輯器
cask &quot;iterm2&quot;                # 終端機
cask &quot;rectangle&quot;             # 視窗管理
cask &quot;alfred&quot;                # 啟動器
```

## 日常維護指令

```bash
# 產生/更新 Brewfile（加 --force 覆寫舊檔）
brew bundle dump --force --file=~/Brewfile

# 安裝 Brewfile 裡的所有套件
brew bundle install --file=~/Brewfile

# 檢查哪些已安裝但不在 Brewfile 裡
brew bundle cleanup --file=~/Brewfile

# 更新所有套件
brew update &amp;&amp; brew upgrade
```

## 一個小提醒

`brew bundle dump` 預設會把 VS Code extensions 也列進去。如果你已經開了 VS Code 的 Settings Sync，這些行就是多餘的，加 `--no-vscode` 跳過：

```bash
brew bundle dump --force --no-vscode --file=~/Brewfile
```

這部分我在[另一篇文章](/blog/brewfile-vscode-cleanup-settings-sync)有詳細說明。

## 下一步

Brewfile 搞定之後，你可能會想：那 `.zshrc`、`.gitconfig` 這些 dotfiles 怎麼辦？推薦搭配 chezmoi 一起使用，把整個開發環境都版本控制起來。這部分我在系列的下一篇會詳細介紹。</content:encoded><media:content url="https://bobochen.dev/_astro/cover.Bo3go1O6.webp" medium="image"/><category>Homebrew</category><category>macOS</category><category>開發環境</category><category>入門</category><category>效率</category><enclosure url="https://bobochen.dev/_astro/cover.Bo3go1O6.webp" length="0" type="image/png"/></item><item><title>我的 Brewfile 公開：一個全端工程師裝了哪 50 個工具</title><link>https://bobochen.dev/blog/my-brewfile-50-tools-fullstack-engineer/</link><guid isPermaLink="true">https://bobochen.dev/blog/my-brewfile-50-tools-fullstack-engineer/</guid><description>公開我的完整 Brewfile，按分類介紹 50 個開發、終端機、生產力工具，附上選擇理由和實際使用情境，讓你直接複製修改。</description><pubDate>Fri, 13 Mar 2026 00:00:00 GMT</pubDate><content:encoded>每次看到別人的桌面截圖或是終端機配置文，我都會忍不住多看幾眼——不是看外觀，是想知道他裝了什麼。

工程師的工具箱很私密，卻又很值得分享。每個工具的選擇背後，都是一段「踩坑 → 尋找替代品 → 找到真愛」的故事。有些工具你可能天天用但從沒想過有更好的替代品，有些你根本不知道存在。

所以我決定把自己的 Brewfile 整個公開。這不是「最佳工具清單」——是我一個全端工程師，每天實際在用的 50 個工具，附上我為什麼選它、拿它做什麼。

如果你剛好在整理自己的開發環境，或是想看看別人的工具箱裡有什麼寶物，這篇就是寫給你的。

## 開發環境基礎

這些是不管做什麼專案都需要的地基。

### git

不用多說，版本控制的唯一選擇。Homebrew 裝的版本通常比 macOS 內建的新很多，支援更多功能。

### node

我的主力語言是 TypeScript，所以 Node.js 是必裝的。不過我實際上不太直接用 Homebrew 裝的版本，而是透過 mise 來管理——等一下會講到。

### python

寫腳本、跑資料處理、偶爾訓練個小模型。Python 也是透過 mise 管版本，但 Homebrew 裝一個當系統預設還是方便。

### go

用 Go 寫過幾個 CLI 工具和 API server。Go 的編譯速度和部署的簡單程度讓我很喜歡——一個 binary 丟上去就跑了，不用煩惱 runtime。

### rust

說實話，Rust 我還在學習階段。但越來越多好用的 CLI 工具都是 Rust 寫的（後面會出現一大堆），裝個 Rust 工具鏈備著也好。

### [mise](https://github.com/jdx/mise)

原本用 nvm 管 Node 版本、pyenv 管 Python 版本，各自一套指令、各自一個設定檔，搞到頭很大。mise 一個工具搞定所有語言的版本管理，一個 `.mise.toml` 走天下。從 asdf 轉過來的，速度快非常多。

### zsh + [starship](https://github.com/starship/starship)

macOS 預設就是 zsh，我之前用 oh-my-zsh 用了好幾年，後來覺得啟動速度越來越慢，加的 plugin 又多到自己都搞不清楚。換成 starship 之後，prompt 設定用一個 `starship.toml` 就搞定，啟動速度飛快，跨平台還能共用設定。

### cmake

偶爾需要從原始碼編譯一些 C/C++ 的東西。不常用，但需要的時候沒有會很痛苦。

## 終端機工具

這一區是我最愛的部分。這些工具讓終端機從「堪用」變成「好用到不想離開」。

### [Warp](https://www.warp.dev/)

原本是 iTerm2 的忠實用戶，用了大概五年。轉到 Warp 是因為它的 AI 整合和 block-based 的輸出概念——每個指令的輸出是獨立的區塊，可以單獨複製、摺疊、搜尋。加上內建的 AI 可以直接問「怎麼用 ffmpeg 轉檔」，不用再開瀏覽器。

### [bat](https://github.com/sharkdp/bat)

取代 `cat`。最大的好處是自動語法高亮和行號，看設定檔、看程式碼都舒服很多。我在 `.zshrc` 裡直接 `alias cat=bat`。

### [eza](https://github.com/eza-community/eza)

取代 `ls`。支援 Git 狀態顯示、圖示、樹狀結構。`eza --tree --level=2 --git` 是我最常用的指令之一，一眼就能看到專案結構和哪些檔案有改動。原本用 exa，但它停止維護了，社群 fork 成了 eza。

### [fd](https://github.com/sharkdp/fd)

取代 `find`。語法直覺到不行——`fd &quot;\.md$&quot;` 就能找到所有 Markdown 檔案，不用再記 `find . -name &quot;*.md&quot;` 這種反人類語法。速度也快非常多。

### [ripgrep](https://github.com/BurntSushi/ripgrep)（rg）

取代 `grep`。快到離譜，自動忽略 `.gitignore` 裡的檔案，預設就是遞迴搜尋。在大型專案裡搜程式碼，ripgrep 跟 grep 的速度差距是秒跟分鐘的差距。

### [zoxide](https://github.com/ajeetdsouza/zoxide)

取代 `cd`。它會記住你去過的目錄，之後只要打 `z blog` 就能跳到 `/Users/bobochen/Desktop/github/bobo52310/bobo-blog-2026`。不用再打完整路徑，也不用設一堆 alias。

### [fzf](https://github.com/junegunn/fzf)

模糊搜尋神器。`Ctrl+R` 搜歷史指令、`Ctrl+T` 搜檔案、搭配其他指令做互動式選取。裝了就回不去了。

### [btop](https://github.com/aristocratos/btop)

取代 `htop`，又取代了 `top`。CPU、記憶體、網路、磁碟一目瞭然，介面漂亮到可以當桌布。當 Docker container 吃掉一堆記憶體時，我第一個開的就是它。

### jq

JSON 的瑞士刀。API 回傳一坨 JSON，用 `curl ... | jq &apos;.data[0].name&apos;` 就能精準抓到你要的欄位。寫 shell script 處理 JSON 資料時更是離不開它。

### [httpie](https://httpie.io/)

取代 `curl` 來做 API 測試。語法更人性化：`http POST api.example.com/users name=Bobo`，自動格式化 JSON 輸出、自動語法高亮。curl 我還是會用，但快速測 API 的時候 httpie 真的舒服很多。

## Git 相關

Git 本身已經很強了，但這些工具讓它更好用。

### [lazygit](https://github.com/jesseduffield/lazygit)

TUI 的 Git 客戶端。interactive rebase、解 merge conflict、看 diff、cherry-pick，全部在終端機裡用鍵盤操作完成。自從用了 lazygit，我幾乎不再用 `git add -p` 或是開 VS Code 的 Git 面板了。

### [gh](https://cli.github.com/)

GitHub 官方的 CLI 工具。開 PR、看 CI 狀態、review code、管理 issue，全部在終端機裡搞定。`gh pr create`、`gh run watch` 是我每天都會用的指令。

### [delta](https://github.com/dandavison/delta)

讓 `git diff` 的輸出變漂亮。side-by-side 對照、語法高亮、行號，設好 `.gitconfig` 之後所有 diff 都會自動套用。一次設定，永久享受。

### git-lfs

大檔案版本控制。設計師丟給我的 PSD、Figma 匯出的大圖、影片素材，都用 git-lfs 追蹤，避免 repo 肥到推不動。

### git-flow

雖然現在很多團隊改用 trunk-based development，但我有些專案還是用 git-flow 的分支模型。這個 CLI 工具讓 feature/release/hotfix 的分支操作標準化。

## 編輯器與 IDE

### [VS Code](https://code.visualstudio.com/)

主力編輯器，沒什麼好說的。Extension 生態系太強了，幾乎什麼語言、什麼框架都有支援。

### [Cursor](https://cursor.sh/)

AI-first 的程式編輯器，基於 VS Code 的 fork。我現在大約 60% 的時間用 Cursor、40% 用 VS Code。Cursor 在需要 AI 輔助寫程式的時候特別好用——Composer 功能可以讓 AI 直接改多個檔案，比 Copilot 更激進也更方便。

### [neovim](https://neovim.io/)

快速編輯設定檔、在 SSH 進去的遠端機器上改東西。不是主力編輯器，但在終端機裡需要改個檔案的時候，neovim 的啟動速度和鍵盤操作效率是無可取代的。

## 容器與雲端

### [OrbStack](https://orbstack.dev/)

取代 Docker Desktop。同樣的功能，但啟動速度快非常多、吃的記憶體少非常多。原本 Docker Desktop 動不動吃掉 4-6 GB RAM，換成 OrbStack 之後降到 1-2 GB。這大概是我這份清單裡 CP 值最高的替換。

### kubectl

Kubernetes 的 CLI 工具。管理 K8s 叢集、部署、查看 pod 狀態都靠它。

### [k9s](https://github.com/derailed/k9s)

Kubernetes 的 TUI 管理工具，跟 lazygit 之於 git 一樣的角色。看 pod log、exec 進 container、看 resource 使用量，全部用鍵盤操作，比 `kubectl` 打一堆指令快多了。

### terraform

Infrastructure as Code。雲端資源全部用程式碼定義，可以版本控制、可以 code review、可以重複建立。用過就回不去手動點 console 了。

### awscli

AWS 的 CLI 工具。管 S3、查 CloudWatch log、操作 Lambda，日常雲端操作都靠它。

## 生產力工具

這些不是開發工具，但對工作效率的影響一樣巨大。

### [Raycast](https://www.raycast.com/)

取代 macOS 內建的 Spotlight。啟動 app、計算機、剪貼簿歷史、視窗管理、snippet 展開、搜尋文件⋯⋯Raycast 一個打十個。裝了之後 Spotlight 就再也沒開過了。我特別愛它的 clipboard history 和 window management——不用再另外裝視窗管理工具。

### [Arc](https://arc.net/)

主力瀏覽器。Space 功能可以把工作和個人的分頁完全隔開，sidebar 的分頁管理也比傳統的 tab bar 好用。原本用 Chrome 用了十幾年，轉過來之後完全回不去。

### [Notion](https://www.notion.so/)

知識庫、專案管理、文件協作的主力工具。我的部落格文章草稿、side project 的規劃、讀書筆記全部放在 Notion。

### [Obsidian](https://obsidian.md/)

個人筆記和知識圖譜。跟 Notion 的差別是：Obsidian 是純本地的 Markdown 檔案，不依賴任何雲端服務，啟動速度快、離線也能用。我用它做每日筆記和永久筆記，Notion 則拿來做需要協作的東西。

### [1Password](https://1password.com/)

密碼管理器。所有帳號密碼、SSH key、API token、信用卡資訊都放在裡面。CLI 版的 `op` 還可以在 shell script 裡安全地取用 secret，不用把密碼寫在程式碼裡。

### [CleanShot X](https://cleanshot.com/)

取代 macOS 內建截圖。標注、馬賽克、滾動截圖、錄 GIF、OCR 文字辨識都有。寫技術文章的時候截圖標注特別好用，省了一堆後製的時間。

### [Karabiner-Elements](https://github.com/pqrs-org/Karabiner-Elements)

鍵盤自訂工具。我把 Caps Lock 改成了 Hyper key（同時按下 Ctrl+Option+Cmd+Shift），搭配 Raycast 的快捷鍵設定，一顆鍵就能觸發各種操作。這個設定改變了我整個鍵盤的使用方式。

### [IINA](https://iina.io/)

macOS 上最好的影片播放器。原生 UI、支援幾乎所有格式、觸控板手勢操作。取代 VLC 之後就沒回去了。

## 通訊與協作

### [Slack](https://slack.com/)

工作溝通主力。大部分團隊和社群都在 Slack 上。

### [Discord](https://discord.com/)

技術社群和開源專案的討論主要在 Discord。參與的幾個開源社群都有自己的 Discord server。

### Line

台灣的國民通訊軟體，跟朋友家人聯繫還是離不開它。

### [Zoom](https://zoom.us/)

視訊會議。雖然 Google Meet 也很常用，但 Zoom 的穩定度和功能還是比較完整，特別是錄影和虛擬背景。

### [Figma](https://www.figma.com/)

設計協作工具。跟設計師溝通、看設計稿、抓標注和間距都在 Figma 上。就算是自己做 side project，我也會先在 Figma 畫 wireframe。

## 其他好用的

這些工具各自解決一個小痛點，但加在一起讓整個 Mac 體驗好非常多。

### ffmpeg

影音處理的瑞士刀。轉檔、壓縮、截圖、合併影片、抽音軌，一行指令搞定。GUI 軟體能做的它都能做，而且可以寫成腳本批次處理。

### [ImageOptim](https://imageoptim.com/)

圖片壓縮。部落格文章的圖片上傳前都會先丟進去壓一下，通常可以減少 50-70% 的檔案大小而幾乎看不出畫質差異。

### [Keka](https://www.keka.io/)

解壓縮工具。支援的格式比內建的封存工具多很多，7z、RAR、TAR 都能處理。

### [MonitorControl](https://github.com/MonitorControl/MonitorControl)

外接螢幕亮度和音量控制。用 Mac 接外接螢幕的人一定懂那個痛——內建的亮度鍵只能控制筆電螢幕。MonitorControl 讓你用鍵盤直接調外接螢幕的亮度，跟內建螢幕一樣方便。

### [mas](https://github.com/mas-cli/mas)

Mac App Store 的 CLI 工具。搭配 Brewfile 使用，可以把 App Store 裡買的 App 也納入自動化安裝。

## 完整 Brewfile

說了這麼多，這是我的完整 Brewfile。你可以直接複製一份，把不需要的刪掉、加上你自己的工具：

```ruby
# ============================================
# Bobo&apos;s Brewfile
# 最後更新：2026-03-13
# ============================================

# --- Taps ---
tap &quot;homebrew/bundle&quot;

# === 開發環境基礎 ===
brew &quot;git&quot;
brew &quot;node&quot;
brew &quot;python&quot;
brew &quot;go&quot;
brew &quot;rust&quot;
brew &quot;mise&quot;                   # 多語言版本管理
brew &quot;starship&quot;               # 跨平台 shell prompt
brew &quot;cmake&quot;

# === 終端機工具 ===
brew &quot;bat&quot;                    # 取代 cat，語法高亮
brew &quot;eza&quot;                    # 取代 ls，Git 整合
brew &quot;fd&quot;                     # 取代 find，語法直覺
brew &quot;ripgrep&quot;                # 取代 grep，超快搜尋
brew &quot;zoxide&quot;                 # 取代 cd，智慧跳轉
brew &quot;fzf&quot;                    # 模糊搜尋
brew &quot;btop&quot;                   # 系統監控 TUI
brew &quot;jq&quot;                     # JSON 處理
brew &quot;httpie&quot;                 # HTTP 測試

# === Git 相關 ===
brew &quot;lazygit&quot;                # Git TUI 客戶端
brew &quot;gh&quot;                     # GitHub CLI
brew &quot;git-delta&quot;              # 更好的 diff
brew &quot;git-lfs&quot;                # 大檔案版本控制
brew &quot;git-flow&quot;               # Git-flow 分支模型

# === 容器與雲端 ===
brew &quot;kubectl&quot;                # Kubernetes CLI
brew &quot;k9s&quot;                    # Kubernetes TUI
brew &quot;terraform&quot;              # Infrastructure as Code
brew &quot;awscli&quot;                 # AWS CLI

# === 其他 CLI 工具 ===
brew &quot;ffmpeg&quot;                 # 影音處理
brew &quot;mas&quot;                    # Mac App Store CLI

# === GUI 應用程式 (cask) ===

# 編輯器與 IDE
cask &quot;visual-studio-code&quot;
cask &quot;cursor&quot;

# 終端機
cask &quot;warp&quot;

# 容器
cask &quot;orbstack&quot;               # 取代 Docker Desktop

# 瀏覽器
cask &quot;arc&quot;

# 生產力
cask &quot;raycast&quot;                # 取代 Spotlight
cask &quot;notion&quot;
cask &quot;obsidian&quot;
cask &quot;1password&quot;
cask &quot;cleanshot&quot;              # 截圖工具
cask &quot;karabiner-elements&quot;     # 鍵盤自訂

# 通訊
cask &quot;slack&quot;
cask &quot;discord&quot;
cask &quot;line&quot;
cask &quot;zoom&quot;
cask &quot;figma&quot;

# 工具
cask &quot;iina&quot;                   # 影片播放器
cask &quot;imageoptim&quot;             # 圖片壓縮
cask &quot;keka&quot;                   # 解壓縮
cask &quot;monitorcontrol&quot;         # 外接螢幕控制
cask &quot;neovim&quot;                 # 終端機編輯器
```

## 幾個選擇背後的思路

回頭看這份清單，我發現自己的選擇有幾個共同的模式：

**能用鍵盤就不用滑鼠。** lazygit、k9s、neovim、Raycast——都是鍵盤優先的工具。不是故意要走 hardcore 路線，是因為手不用離開鍵盤真的快很多。

**Rust 寫的 CLI 工具通常比較好。** bat、eza、fd、ripgrep、zoxide、starship、delta——全部是 Rust 寫的。速度快、binary 小、不需要裝 runtime。這不是 Rust 信仰，是實際體驗的結論。

**花錢買好工具是值得的。** CleanShot X、1Password、Raycast Pro——這些付費工具每天幫我省下的時間遠超過它們的價格。工程師的時薪換算一下，一個月省 30 分鐘就值回票價了。

**不怕換工具。** iTerm2 → Warp、Docker Desktop → OrbStack、Chrome → Arc、oh-my-zsh → starship。只要新工具明顯更好，學習成本就是值得的投資。

## 最後

這份 Brewfile 不是標準答案——每個人的工作流程不同，需要的工具也不同。但我相信看看別人的工具箱，一定能發現幾個你沒想過但其實很需要的東西。

如果你也有一份自己的 Brewfile，或是有什麼工具覺得「不能沒有它」，歡迎留言分享。最好的工具推薦，永遠來自實際在用的人。</content:encoded><media:content url="https://bobochen.dev/_astro/cover.COCWNXh1.webp" medium="image"/><category>macOS</category><category>Homebrew</category><category>開發工具</category><category>效率工具</category><category>全端工程師</category><enclosure url="https://bobochen.dev/_astro/cover.COCWNXh1.webp" length="0" type="image/png"/></item><item><title>你的 Brewfile 是不是也在做白工？我清掉了 76 行才發現的事</title><link>https://bobochen.dev/blog/brewfile-vscode-cleanup-settings-sync/</link><guid isPermaLink="true">https://bobochen.dev/blog/brewfile-vscode-cleanup-settings-sync/</guid><description>整理 Brewfile 時發現 76 行在備份 VS Code Extensions，但 VS Code Settings Sync 早就在處理了。記錄確認方式、清理指令，以及「兩個工具做同一件事」這個維護陷阱。</description><pubDate>Fri, 13 Mar 2026 00:00:00 GMT</pubDate><content:encoded>每隔一段時間我會整理開發環境，這次翻出 Brewfile 來瘦身，結果發現一個蠻傻的問題：**我的 Brewfile 一直在備份 VS Code Extensions，但 VS Code 自己早就有 Settings Sync 了。**

## 事情是怎麼發現的

我用 `brew bundle dump` 產生 Brewfile 備份開發環境，檔案有 202 行，其中 76 行長這樣：

```
vscode &quot;dbaeumer.vscode-eslint&quot;
vscode &quot;esbenp.prettier-vscode&quot;
vscode &quot;astro-build.astro-vscode&quot;
...（再 73 行）
```

看到這一大坨就想：等等，這些不是 VS Code 登入 GitHub 帳號就會自動同步嗎？

## 確認 Settings Sync 有沒有在運作

其實很簡單，看這個資料夾有沒有內容：

```bash
ls ~/Library/Application\ Support/Code/User/sync/
```

如果裡面有 `extensions`、`settings`、`keybindings` 這些子目錄，就代表 Settings Sync 正在運作。如果是空的，去 VS Code 按 `Cmd+Shift+P` 搜尋 `Settings Sync: Turn On` 開啟就好。

## 清理方式

確認 Settings Sync 有在跑之後，一行指令清掉所有 `vscode` 行：

```bash
grep -v &apos;^vscode&apos; Brewfile &gt; Brewfile.tmp &amp;&amp; mv Brewfile.tmp Brewfile
```

之後每次 dump 記得加 `--no-vscode`：

```bash
brew bundle dump --force --no-vscode
```

## 結果

Brewfile 從 202 行瘦到 117 行，少了 38%。不是什麼驚天動地的優化，但重點是：**這 76 行從來沒有發揮過作用**——我每次換電腦都是靠 VS Code Settings Sync 還原 extensions，Brewfile 裡的 `vscode` 行根本沒人理。

## 反思：工具的職責要分清楚

這件事的本質是**兩個工具在做同一件事，但你只信任其中一個**。

Homebrew 的職責是管理系統層級的軟體安裝（CLI 工具、app、服務），VS Code Settings Sync 的職責是管理編輯器的狀態（extensions、設定、快捷鍵）。`brew bundle dump` 預設會把 VS Code extensions 也撈進來，看起來很貼心，但實際上這份清單永遠不會是你真正用來還原 extensions 的來源。

這讓我想到一個更廣的原則：**備份和同步不是越多越好，重複備份只會製造維護負擔和錯誤的安全感**。

另外順便整理了 Brewfile 裡其他用不到的工具（`hugo`、`cocoapods`、`php` 等），但那是另一個故事了。</content:encoded><media:content url="https://bobochen.dev/_astro/cover.BKSgCMJt.webp" medium="image"/><category>Homebrew</category><category>VSCode</category><category>開發環境</category><category>macOS</category><category>效率</category><enclosure url="https://bobochen.dev/_astro/cover.BKSgCMJt.webp" length="0" type="image/png"/></item><item><title>Brewfile + chezmoi + dotfiles：Mac 開發環境的完整備份策略</title><link>https://bobochen.dev/blog/brewfile-chezmoi-dotfiles-backup-strategy/</link><guid isPermaLink="true">https://bobochen.dev/blog/brewfile-chezmoi-dotfiles-backup-strategy/</guid><description>Brewfile 管軟體、chezmoi 管 dotfiles、VS Code Settings Sync 管編輯器——三個工具各司其職，讓你換電腦只需要四個步驟就能還原整個開發環境。</description><pubDate>Fri, 13 Mar 2026 00:00:00 GMT</pubDate><content:encoded>Brewfile 解決了「裝什麼軟體」，但你的 `.zshrc`、`.gitconfig`、SSH key 呢？這篇聊聊怎麼用 Brewfile + [chezmoi](https://github.com/twpayne/chezmoi) 把整個開發環境版本控制起來，以及每個工具的職責邊界在哪裡。

## 問題：你的開發環境有幾層？

一個完整的開發環境其實有三層：

| 層級       | 內容                               | 負責工具              |
| ---------- | ---------------------------------- | --------------------- |
| 軟體安裝   | CLI 工具、桌面 App                 | Homebrew (Brewfile)   |
| 系統設定   | dotfiles、shell config、Git config | chezmoi               |
| 編輯器狀態 | Extensions、Settings、Keybindings  | VS Code Settings Sync |

很多人（包括以前的我）把所有東西塞在同一個備份機制裡，結果就是職責不清、維護困難。

## 各工具的職責邊界

### Homebrew / Brewfile — 只管「裝什麼」

```bash
brew bundle dump --force --no-vscode --file=~/Brewfile
```

Brewfile 只負責記錄軟體清單，不管設定。加 `--no-vscode` 是因為 VS Code extensions 有自己的同步機制。

### chezmoi — 只管「設定檔」

[chezmoi](https://github.com/twpayne/chezmoi) 是一個 dotfiles 管理工具，它不直接在 `$HOME` 建 symlink，而是用一個獨立的 source directory 管理，透過 `chezmoi apply` 把設定檔「部署」到正確位置。

#### 3 分鐘快速上手

```bash
# 安裝
brew install chezmoi

# 初始化（會建立 ~/.local/share/chezmoi）
chezmoi init

# 把現有 dotfile 加入管理
chezmoi add ~/.zshrc
chezmoi add ~/.gitconfig
chezmoi add ~/.config/starship.toml

# 看看 chezmoi 管了哪些檔案
chezmoi managed

# 編輯某個設定檔
chezmoi edit ~/.zshrc

# 看差異
chezmoi diff

# 套用變更到 $HOME
chezmoi apply
```

核心觀念：你永遠在 chezmoi 的 source directory 裡編輯，然後 `apply` 到 `$HOME`。這樣 source directory 就是一個乾淨的 Git repo，可以推到 GitHub。

### VS Code Settings Sync — 只管「編輯器」

登入 GitHub 帳號就自動同步 extensions、settings、keybindings、snippets。不需要任何額外設定。

## 三者的協作流程

### 初次設定（在你的主力機器上）

```bash
# 1. 產生 Brewfile
brew bundle dump --force --no-vscode --file=~/Brewfile

# 2. 初始化 chezmoi 並加入 dotfiles
chezmoi init
chezmoi add ~/.zshrc
chezmoi add ~/.gitconfig
chezmoi add ~/.config/starship.toml
# ...加入你需要的設定檔

# 3. 把 Brewfile 也交給 chezmoi 管理
cp ~/Brewfile $(chezmoi source-path)/
chezmoi add ~/Brewfile

# 4. 推到 GitHub
cd $(chezmoi source-path)
git remote add origin git@github.com:yourname/dotfiles.git
git add -A &amp;&amp; git commit -m &quot;initial dotfiles + Brewfile&quot;
git push -u origin main

# 5. VS Code Settings Sync — 確認已開啟就好
```

### 換到新電腦時

```bash
# 1. 裝 Homebrew
/bin/bash -c &quot;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)&quot;

# 2. 裝 chezmoi 並從 GitHub 拉下設定
brew install chezmoi
chezmoi init --apply yourname

# 3. 用 Brewfile 安裝所有軟體
brew bundle install --file=$(chezmoi source-path)/Brewfile

# 4. 開 VS Code → 登入 GitHub → Settings Sync 自動還原
```

四個步驟，整個開發環境就回來了。

## chezmoi 的進階功能

chezmoi 不只是 symlink 工具，它還支援：

### 模板（Templates）— 不同機器用不同設定

```bash
# 在 .zshrc.tmpl 裡用條件判斷
{{ if eq .chezmoi.hostname &quot;work-mac&quot; }}
export KUBECONFIG=~/.kube/config-work
{{ else }}
export KUBECONFIG=~/.kube/config-personal
{{ end }}
```

### Secrets 管理 — 敏感資訊不進 Git

```bash
# 搭配 1Password CLI 或 macOS Keychain
chezmoi add --template ~/.ssh/config
# 在模板裡引用 Keychain
{{ keyring &quot;ssh-key-passphrase&quot; &quot;my-account&quot; }}
```

### 自動化腳本 — 安裝後自動執行

```bash
# 建立 run_once_install.sh，chezmoi apply 時自動跑一次
#!/bin/bash
# 設定 macOS 預設值
defaults write com.apple.dock autohide -bool true
defaults write com.apple.finder AppleShowAllFiles -bool true
killall Dock Finder
```

## 什麼不該放進 chezmoi

- **大型二進位檔**：放 Git LFS 或雲端
- **機密資訊**：用 template + keyring，不要明文
- **暫時性設定**：`.env.local` 這種專案層級的不用管
- **IDE workspace 設定**：VS Code Settings Sync 管就好

## 反思：為什麼職責分離很重要

以前我用一個巨大的 setup script 做所有事，三百多行的 `setup.sh`，安裝軟體、複製設定檔、設 macOS defaults，全塞在一起。

問題是：每次只想改一個 `.zshrc` 設定，都要跑整個 script，還怕改壞其他東西。

拆成三個工具之後，每個工具只管一件事：

- 想加新軟體 → 改 Brewfile，跑 `brew bundle`
- 想改 shell 設定 → `chezmoi edit ~/.zshrc`，跑 `chezmoi apply`
- 想裝新 VS Code extension → 直接在 VS Code 裝，Settings Sync 自動處理

**改動範圍小 = 信心大 = 更敢改。**</content:encoded><media:content url="https://bobochen.dev/_astro/cover.DACx7mmR.webp" medium="image"/><category>chezmoi</category><category>dotfiles</category><category>Homebrew</category><category>macOS</category><category>開發環境</category><enclosure url="https://bobochen.dev/_astro/cover.DACx7mmR.webp" length="0" type="image/png"/></item><item><title>chezmoi 實戰：一份 dotfiles 管理三台不同用途的 Mac</title><link>https://bobochen.dev/blog/chezmoi-dotfiles-multi-machine-setup/</link><guid isPermaLink="true">https://bobochen.dev/blog/chezmoi-dotfiles-multi-machine-setup/</guid><description>用 chezmoi 管理多台 Mac 的差異化 dotfiles：模板語法、age 加密、多機同步工作流程，以及實際踩過的坑。</description><pubDate>Fri, 13 Mar 2026 00:00:00 GMT</pubDate><content:encoded>你已經有一份 dotfiles repo 了，用 symlink 或 [GNU Stow](https://www.gnu.org/software/stow/) 管著 `.zshrc`、`.gitconfig` 那些檔案。在一台電腦上，這套做法沒什麼問題。

但第二台電腦出現的時候，問題就來了。

## 手動 symlink 在多台電腦的崩潰時刻

我有三台 Mac：

| 機器            | 用途                  | 差異                                 |
| --------------- | --------------------- | ------------------------------------ |
| MacBook Pro 14&quot; | 公司開發機            | 公司 email、VPN 設定、內部工具 PATH  |
| MacBook Air M3  | 個人 side project     | 個人 email、部落格相關工具           |
| Mac mini        | 家裡的 homelab server | 沒有 GUI app、多了 Docker 相關 alias |

三台機器 90% 的設定是一樣的（zsh 習慣、vim 設定、git alias），但那 10% 的差異讓我痛苦不堪：

- **`.gitconfig` 的 email 不一樣**：公司的要用 `bobo@company.com`，個人的用 `bobo@gmail.com`
- **`.zshrc` 的 PATH 不一樣**：公司電腦有 `/opt/internal-tools/bin`，個人電腦有 `~/.local/bin`
- **alias 不一樣**：homelab 多了一堆 Docker 快捷指令，工作機有 `kubectl` 相關 alias
- **有些設定檔根本不該出現在某些機器上**：公司的 VPN config 不該存在個人電腦

用 symlink 的話怎麼辦？開 branch？太累了。用 `if` 判斷 hostname？散落在各檔案裡，維護是地獄。

這就是 [chezmoi](https://github.com/twpayne/chezmoi) 要解決的問題。

## chezmoi 的核心概念

chezmoi 的設計哲學很簡單：**你的 dotfiles 是「原始碼」，你的 home 目錄是「編譯結果」。**

這兩個概念很重要：

- **Source state**（原始碼）：存在 `~/.local/share/chezmoi/` 裡，就是你的 dotfiles repo。檔案可以是模板、加密檔、腳本。
- **Destination state**（編譯結果）：就是你的 `$HOME`，也就是實際被使用的設定檔。

chezmoi 做的事情就是把 source state **編譯**成 destination state。中間經過模板渲染、解密、條件判斷，最後才寫入你的 home 目錄。

&gt; [!NOTE]
&gt; 順帶一提：`chezmoi` 念作 `[ʃɛ mwa]`（近「雪・ㄇㄨㄚ」），是法文 **chez moi「我家」**。難怪它的 destination state 就是你的 `$HOME`——工具名字本來就是「我家」。👉 [名字的由來與發音](/blog/chezmoi-name-pronunciation-chez-moi/)

這跟 symlink 最大的不同是：**實際的設定檔不是 symlink，而是真正的檔案。** 所以即使 chezmoi 壞了、你把 repo 刪了，你的設定檔還是好好的在那裡。

## 安裝與初始化

```bash
# 安裝
brew install chezmoi

# 初始化（會在 ~/.local/share/chezmoi 建立 git repo）
chezmoi init

# 如果你已經有 dotfiles repo
chezmoi init https://github.com/your-username/dotfiles.git
```

把現有的設定檔加入管理：

```bash
# 加入 .zshrc
chezmoi add ~/.zshrc

# 加入 .gitconfig
chezmoi add ~/.gitconfig

# 加入整個 .config/starship.toml
chezmoi add ~/.config/starship.toml
```

加入之後，chezmoi 會把檔案複製一份到 source 目錄。你可以用 `chezmoi cd` 跳進去看：

```bash
chezmoi cd
ls -la
# 你會看到 dot_zshrc, dot_gitconfig 這些檔案
# chezmoi 用前綴來表示檔案屬性：dot_ = 以 . 開頭
```

## 模板語法實戰

這是 chezmoi 最強的地方。你可以把設定檔變成 Go template，根據每台機器的變數產生不同的內容。

### 第一步：設定每台機器的變數

編輯 `~/.config/chezmoi/chezmoi.toml`（每台機器各自設定，不進 repo）：

```toml
# MacBook Pro（公司機）
[data]
  machine_type = &quot;work&quot;
  email = &quot;bobo@company.com&quot;
  git_signing_key = &quot;ABCDEF1234567890&quot;

# MacBook Air（個人機）
[data]
  machine_type = &quot;personal&quot;
  email = &quot;bobo@gmail.com&quot;
  git_signing_key = &quot;1234567890ABCDEF&quot;

# Mac mini（homelab）
[data]
  machine_type = &quot;homelab&quot;
  email = &quot;bobo@gmail.com&quot;
```

你可以用 `chezmoi data` 確認目前機器的變數：

```bash
chezmoi data
# {
#   &quot;machine_type&quot;: &quot;work&quot;,
#   &quot;email&quot;: &quot;bobo@company.com&quot;,
#   ...
# }
```

### 實戰一：.gitconfig 根據機器填入不同 email

先把 `.gitconfig` 轉成模板：

```bash
chezmoi add --template ~/.gitconfig
```

然後編輯模板：

```bash
chezmoi edit ~/.gitconfig
```

模板內容：

```toml
[user]
  name = Bobo Chen
  email = {{ .email }}
{{ if .git_signing_key }}
  signingkey = {{ .git_signing_key }}
{{ end }}

[commit]
{{ if .git_signing_key }}
  gpgsign = true
{{ end }}

[core]
  editor = vim
  autocrlf = input

[alias]
  st = status
  co = checkout
  br = branch
  lg = log --oneline --graph --all
  unstage = reset HEAD --

[pull]
  rebase = true

{{ if eq .machine_type &quot;work&quot; }}
[url &quot;git@github-work:&quot;]
  insteadOf = https://github.com/company-org/
{{ end }}
```

在公司電腦上，`chezmoi apply` 之後產出的 `.gitconfig` 會有公司 email 和 signing key；在個人電腦上就是個人 email。同一份模板，不同結果。

### 實戰二：.zshrc 根據機器載入不同的 PATH 和 alias

```bash
chezmoi add --template ~/.zshrc
chezmoi edit ~/.zshrc
```

```bash
# === 共用區塊 ===
export EDITOR=&quot;vim&quot;
export LANG=&quot;en_US.UTF-8&quot;

# Homebrew
eval &quot;$(/opt/homebrew/bin/brew shellenv)&quot;

# 共用 PATH
export PATH=&quot;$HOME/.local/bin:$PATH&quot;

# 共用 alias
alias ll=&quot;ls -la&quot;
alias g=&quot;git&quot;
alias gs=&quot;git status&quot;
alias gp=&quot;git push&quot;

{{ if eq .machine_type &quot;work&quot; -}}
# === 公司專用 ===
export PATH=&quot;/opt/internal-tools/bin:$PATH&quot;
export KUBECONFIG=&quot;$HOME/.kube/company-config&quot;
alias k=&quot;kubectl&quot;
alias kns=&quot;kubectl config set-context --current --namespace&quot;
alias vpn-up=&quot;sudo openconnect --config=$HOME/.vpn/company.conf&quot;
{{ end -}}

{{ if eq .machine_type &quot;personal&quot; -}}
# === 個人專用 ===
export PATH=&quot;$HOME/.cargo/bin:$PATH&quot;
alias blog=&quot;cd ~/Desktop/github/bobo-blog-2026 &amp;&amp; npm run dev&quot;
alias deploy=&quot;cd ~/Desktop/github/bobo-blog-2026 &amp;&amp; npm run build&quot;
{{ end -}}

{{ if eq .machine_type &quot;homelab&quot; -}}
# === Homelab 專用 ===
alias dc=&quot;docker compose&quot;
alias dps=&quot;docker ps --format &apos;table {{`{{`}}.Names{{`}}`}}\t{{`{{`}}.Status{{`}}`}}\t{{`{{`}}.Ports{{`}}`}}&apos;&quot;
alias dlogs=&quot;docker logs -f&quot;
alias dprune=&quot;docker system prune -af&quot;
{{ end -}}

# 共用的 zsh 設定
autoload -Uz compinit &amp;&amp; compinit
```

注意模板語法裡 `{{-` 後面的 `-` 是為了去掉多餘的空行。這是 Go template 的小技巧。

### 實戰三：用 chezmoi init 互動式設定變數

如果你不想手動寫 `chezmoi.toml`，可以用 `.chezmoidata.toml` 搭配 `init` 的 prompt 功能。在 source 目錄建立 `.chezmoi.toml.tmpl`：

```toml
[data]
  machine_type = {{ promptStringOnce . &quot;machine_type&quot; &quot;Machine type (work/personal/homelab)&quot; | quote }}
  email = {{ promptStringOnce . &quot;email&quot; &quot;Git email address&quot; | quote }}
```

這樣在新機器上跑 `chezmoi init` 時，它會互動式問你這些問題，然後自動產生 `chezmoi.toml`。

## 加密敏感檔案

dotfiles 裡總有些敏感的東西：SSH config 裡的 host 資訊、`.env` 裡的 API key。這些你不想明文推上 GitHub。

chezmoi 內建支援 [age](https://github.com/FiloSottile/age) 加密（也支援 gpg，但 age 更簡單）。

### 設定 age 加密

```bash
# 安裝 age
brew install age

# 產生 key pair
age-keygen -o ~/.config/chezmoi/key.txt
# 它會輸出 public key，記下來

# Public key: age1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

在 `~/.config/chezmoi/chezmoi.toml` 加上：

```toml
encryption = &quot;age&quot;

[age]
  identity = &quot;~/.config/chezmoi/key.txt&quot;
  recipient = &quot;age1xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx&quot;
```

### 加密 SSH config

```bash
# 把 SSH config 加入 chezmoi 並加密
chezmoi add --encrypt ~/.ssh/config
```

加密後的檔案在 source 目錄裡會是 `private_dot_ssh/encrypted_private_config.age`，看到的是亂碼。推上 GitHub 也安全。

在另一台電腦上，只要你有同一把 `key.txt`（可以透過 1Password 或 iCloud Keychain 安全地搬移），`chezmoi apply` 會自動解密。

### 我通常會加密的檔案

```bash
chezmoi add --encrypt ~/.ssh/config
chezmoi add --encrypt ~/.config/gh/hosts.yml    # GitHub CLI token
chezmoi add --encrypt ~/.npmrc                  # npm registry token
```

## 多機器工作流程

日常操作其實就三個步驟，非常順暢：

### 在 A 電腦改設定

```bash
# 1. 編輯設定檔（chezmoi 會開你的 $EDITOR）
chezmoi edit ~/.zshrc

# 2. 預覽差異（不會真的套用）
chezmoi diff

# 3. 確認沒問題，套用到 home 目錄
chezmoi apply

# 4. 推上 repo
chezmoi cd
git add -A
git commit -m &quot;feat: add docker aliases for homelab&quot;
git push
```

### 在 B 電腦同步

```bash
# 一行搞定：git pull + apply
chezmoi update
```

就這樣。`chezmoi update` 會自動 `git pull` 然後重新套用所有設定。因為每台機器有自己的 `chezmoi.toml`，模板會根據當地變數產出正確的內容。

### 如果你想先看看會改什麼

```bash
# 只 pull，不 apply
chezmoi git pull

# 看看差異
chezmoi diff

# 確認後再 apply
chezmoi apply
```

## 常見踩坑

### 踩坑一：忘記 chezmoi add 新檔案

這是最常犯的錯。你直接編輯了 `~/.zshrc`，改完很開心，結果下次 `chezmoi apply` 又被覆蓋回去。

**正確做法**：永遠用 `chezmoi edit` 編輯，或者改完之後用 `chezmoi re-add` 把變更收回 source：

```bash
# 手動改了 ~/.zshrc 之後
chezmoi re-add ~/.zshrc
# 這會把 destination 的變更反向同步回 source
```

也可以用 `chezmoi merge` 做三方合併，但大多時候 `re-add` 就夠了。

### 踩坑二：模板語法錯誤

模板寫錯的時候，`chezmoi apply` 會直接噴錯，但錯誤訊息有時不太直觀。

**debug 技巧**：用 `chezmoi execute-template` 測試模板片段：

```bash
# 測試一段模板語法
echo &apos;{{ if eq .machine_type &quot;work&quot; }}work mode{{ else }}personal mode{{ end }}&apos; | chezmoi execute-template

# 測試整個檔案
chezmoi execute-template &lt; ~/.local/share/chezmoi/dot_zshrc.tmpl

# 查看某個檔案 apply 後的結果（不寫入）
chezmoi cat ~/.zshrc
```

常見的模板錯誤：

```bash
# 錯：忘記 end
{{ if eq .machine_type &quot;work&quot; }}
something
# 對：
{{ if eq .machine_type &quot;work&quot; }}
something
{{ end }}

# 錯：字串沒加引號
{{ if eq .machine_type work }}
# 對：
{{ if eq .machine_type &quot;work&quot; }}
```

### 踩坑三：macOS 更新後 defaults 被重設

macOS 大版本更新有時會重設一些系統偏好設定。這不是 chezmoi 的問題，但你可以用 chezmoi 的 `run_` script 來處理。

在 source 目錄建立 `run_onchange_macos-defaults.sh.tmpl`：

```bash
#!/bin/bash
# chezmoi:template:hash
# macOS defaults — 每次內容變更時重新執行

# Dock
defaults write com.apple.dock autohide -bool true
defaults write com.apple.dock tilesize -int 48

# Finder
defaults write com.apple.finder AppleShowAllFiles -bool true
defaults write com.apple.finder ShowPathbar -bool true

{{ if eq .machine_type &quot;work&quot; }}
# 公司電腦額外設定
defaults write com.apple.screensaver askForPassword -int 1
defaults write com.apple.screensaver askForPasswordDelay -int 0
{{ end }}

killall Dock Finder
```

`run_onchange_` 前綴表示只有腳本內容變更時才重新執行。加上 `chezmoi:template:hash` 確保模板渲染後的結果被 hash，而不是模板本身。

## 我的 chezmoi 目錄結構

```
~/.local/share/chezmoi/
├── .chezmoi.toml.tmpl              # init 時的互動問答
├── .chezmoiignore                  # 忽略規則（可用模板！）
├── dot_zshrc.tmpl                  # .zshrc 模板
├── dot_gitconfig.tmpl              # .gitconfig 模板
├── dot_vimrc                       # .vimrc（不需要模板，三台都一樣）
├── private_dot_ssh/
│   ├── encrypted_private_config.age # SSH config（加密）
│   └── config.d/                    # SSH config 片段
├── dot_config/
│   ├── starship.toml               # Starship prompt 設定
│   ├── private_gh/
│   │   └── encrypted_hosts.yml.age # GitHub CLI token（加密）
│   └── karabiner/
│       └── karabiner.json          # 鍵盤改鍵
├── run_onchange_macos-defaults.sh.tmpl  # macOS 系統偏好
├── run_onchange_install-packages.sh.tmpl # Brewfile 安裝
└── .chezmoiignore
```

`.chezmoiignore` 也可以用模板語法，根據機器類型忽略不同檔案：

```
README.md
LICENSE

{{ if ne .machine_type &quot;work&quot; }}
# 非工作機不需要這些
dot_config/private_vpn
{{ end }}

{{ if eq .machine_type &quot;homelab&quot; }}
# homelab 不需要 GUI 相關設定
dot_config/karabiner
{{ end }}
```

## 從 symlink 遷移到 chezmoi

如果你目前用 GNU Stow 或手動 symlink，遷移很簡單：

```bash
# 1. 初始化 chezmoi
chezmoi init

# 2. 把現有的設定檔加入
chezmoi add ~/.zshrc
chezmoi add ~/.gitconfig
chezmoi add ~/.vimrc
chezmoi add ~/.config/starship.toml

# 3. 刪除舊的 symlink（chezmoi add 已經複製了真實檔案）
# stow -D your-stow-package

# 4. 把需要差異化的檔案轉成模板
chezmoi chattr +template ~/.zshrc
chezmoi chattr +template ~/.gitconfig

# 5. 編輯模板，加入條件判斷
chezmoi edit ~/.zshrc
```

## 值不值得？

老實說，如果你只有一台電腦，chezmoi 有點 overkill。純 Git + symlink 就很夠了。

但如果你有兩台以上的機器，或是你的設定檔需要根據環境有差異，chezmoi 的 template 系統和加密功能真的會讓你的生活輕鬆很多。我的使用體感：

- **初始設定時間**：大約 1-2 小時（把現有 dotfiles 遷移過去）
- **日常維護時間**：接近零（改設定 → `chezmoi edit` → push → 另一台 `chezmoi update`）
- **新機器 setup 時間**：`chezmoi init --apply your-repo` 一行搞定

投資報酬率？以我三台電腦的使用頻率來說，大概第二週就回本了。</content:encoded><media:content url="https://bobochen.dev/_astro/cover.CkiC03ZU.webp" medium="image"/><category>chezmoi</category><category>dotfiles</category><category>macOS</category><category>自動化</category><category>開發環境</category><enclosure url="https://bobochen.dev/_astro/cover.CkiC03ZU.webp" length="0" type="image/png"/></item><item><title>Mackup vs chezmoi vs 手寫 script：macOS 設定備份工具怎麼選？</title><link>https://bobochen.dev/blog/mackup-vs-chezmoi-vs-defaults-sh-comparison/</link><guid isPermaLink="true">https://bobochen.dev/blog/mackup-vs-chezmoi-vs-defaults-sh-comparison/</guid><description>三種主流的 macOS 設定備份方案，設計哲學完全不同：symlink 派、copy 派、script 派。沒有最好的工具，只有最適合你的工具。</description><pubDate>Fri, 13 Mar 2026 00:00:00 GMT</pubDate><content:encoded>想備份 macOS 的設定，Google 一下大概會出現三個主流方案：Mackup、chezmoi、手寫 shell script。

每個都說自己好用，但設計哲學完全不同。選錯了，換起來很麻煩。

這篇不是「哪個贏」，而是「你是哪種人就選哪個」。

## 三種方案的核心差異

先用一張表看懂本質差異：

|                  | Mackup                     | chezmoi               | 手寫 script           |
| ---------------- | -------------------------- | --------------------- | --------------------- |
| **備份機制**     | Symlink（符號連結）        | Copy + Template       | `defaults write` 指令 |
| **備份對象**     | App 設定檔（plist/config） | dotfiles（.zshrc 等） | macOS 系統偏好        |
| **儲存位置**     | iCloud / Dropbox / Git     | Git repo              | Git repo              |
| **多機差異**     | 難處理                     | 原生支援 template     | 需手動 if/else        |
| **macOS Sonoma** | ⚠️ Symlink 已知 bug        | ✅ 完全相容           | ✅ 相容               |
| **Secrets 管理** | ❌ 無                      | ✅ 內建加密           | ❌ 手動/有風險        |
| **學習曲線**     | 低                         | 中                    | 低                    |
| **GitHub Stars** | ~15k                       | ~18.5k                | N/A                   |
| **維護狀態**     | 趨緩                       | 非常活躍              | 你自己維護            |

---

## Mackup — Symlink 派

[Mackup](https://github.com/lra/mackup) 的邏輯很直觀：

1. 把 App 的設定檔從原本位置**移動**到 iCloud/Dropbox
2. 在原本位置建立一個**符號連結**指向雲端位置
3. 換電腦時，從雲端 restore，重建 symlink

```bash
brew install mackup

# 備份
mackup backup

# 還原
mackup restore
```

### 為什麼吸引人

支援超過 360 個 App，包含 VSCode、Sublime Text、Alfred、iTerm2、Karabiner 等常用工具。對非技術用戶來說，「一行指令搞定所有 App 設定」的概念非常吸引人。

### 實際踩到的坑

**Symlink 是雙面刃**。因為 App 直接讀寫雲端位置，設定變更會即時同步——聽起來很好，但：

- **⚠️ macOS Sonoma (14+) 已知 bug**：升級到 Sonoma 後 symlink 會壞掉，這是目前 Mackup 最大的問題。很多用戶因此遷移到其他方案。
- **iCloud 同步延遲**：App 開啟時設定檔還在同步中，可能讀到舊版本
- **多機同時修改**：在公司電腦改了設定，回家電腦還沒同步就開啟 App，可能產生衝突
- **App 不尊重 symlink**：現代 App（如 iTerm2、Fantastical）有時會直接覆寫 symlink 而不是跟隨它
- **維護趨緩**：近年 PR 積累，部分 App 的備份設定已過時

### 適合的人

- **需要注意**：如果你已經在 macOS Sonoma (14+) 上，Mackup 的 symlink 問題可能讓你踩坑
- 如果用的是 Sonoma 以前的版本，或願意手動處理相容性問題，Mackup 在備份 GUI App 設定這件事仍有優勢
- 主要需求是備份 **GUI App 設定**（而非 CLI dotfiles）
- 只用一台電腦，不需要多機差異

---

## chezmoi — Copy 派

[chezmoi](https://github.com/twpayne/chezmoi) 的設計哲學完全不同：**不用 symlink，改用 copy**。

它有一個獨立的 source directory（預設 `~/.local/share/chezmoi`），你在那邊管理「設定檔的原始版本」，執行 `chezmoi apply` 才會把檔案**複製**到實際位置。

```bash
brew install chezmoi

# 把現有 dotfile 加入管理
chezmoi add ~/.zshrc
chezmoi add ~/.gitconfig

# 看差異
chezmoi diff

# 套用
chezmoi apply
```

### 為什麼值得花時間學

**Template 系統**是 chezmoi 最強的地方。同一份 source，可以根據機器不同輸出不同內容：

```
# ~/.local/share/chezmoi/dot_gitconfig.tmpl
[user]
    name = Bobo Chen
    email = {{ if eq .chezmoi.hostname &quot;work-mac&quot; }}bobo@company.com{{ else }}bobo@personal.com{{ end }}
```

公司電腦和個人電腦，自動用不同的 Git email。這件事用 Mackup 幾乎做不到。

其他亮點：

- **加密 secrets**：支援 1Password、Bitwarden、age 加密，私鑰也可以版控
- **跨平台**：同一份 dotfiles 可以用在 macOS 和 Linux
- **Git 原生**：source directory 直接就是一個 git repo

### 學習曲線

chezmoi 的檔案命名有一套規則（`dot_zshrc` 對應 `~/.zshrc`、`private_` 前綴代表 600 權限⋯⋯），需要花一點時間熟悉。但一旦上手，這套系統非常彈性。

### 適合的人

- 有多台電腦，需要**差異化設定**（公司 vs 個人）
- 需要版控**加密的 secrets**
- 想要一套 dotfiles 同時支援 macOS + Linux
- 不排斥花一個下午把系統學清楚

---

## 手寫 script — Script 派

不依賴任何工具，就是一個 shell script，跑 `defaults write` 指令：

```bash
#!/bin/bash

# 鍵盤速度
defaults write NSGlobalDomain KeyRepeat -int 2
defaults write NSGlobalDomain InitialKeyRepeat -int 15

# Dock
defaults write com.apple.dock autohide -bool true
defaults write com.apple.dock tilesize -int 48

# Finder
defaults write com.apple.finder AppleShowAllFiles -bool true
defaults write com.apple.finder ShowPathbar -bool true

# 重啟服務
killall Dock Finder 2&gt;/dev/null || true
```

這個方案特別針對 **macOS 系統偏好設定**（不是 App 設定檔，也不是 dotfiles）。知名範本：[mathiasbynens/dotfiles](https://github.com/mathiasbynens/dotfiles) 的 `.macos` 檔案，社群很多人拿來當起點。

### 優點

- **零依賴**：只要有 bash 就能跑
- **完全可讀**：每行都看得懂在幹嘛，有問題很容易 debug
- **零隱私風險**：只設定你明確選擇的項目
- **跨版本穩定**：你控制每個設定，macOS 升級不會意外覆蓋

### 缺點

- **不備份 App 設定**：只管得了 `defaults write` 能設定的範圍
- **需要手動維護**：新發現的好設定要自己加進去
- **沒有衝突偵測**：不知道現在的設定跟 script 有沒有差異

### 適合的人

- 只需要備份 **macOS 系統偏好設定**（不需要備份 App 設定）
- 重視可讀性和控制感
- 不想引入額外依賴

---

## 三個方案怎麼組合用？

這三個方案並不互斥，很多人混著用。不過考量到 Mackup 在 Sonoma 的問題，我現在建議的組合是：

```
系統偏好設定    → 手寫 defaults.sh（Dock、Finder、鍵盤速度）
dotfiles 管理   → chezmoi（.zshrc、.gitconfig、App config 檔）
GUI App 設定    → 視情況：部分 App 的 config 檔也可以用 chezmoi 管
```

如果你的 Mackup 目前跑得好，繼續用沒問題。但如果是全新設定，我不會再推薦 Mackup 作為主要方案。

## 我的建議

**剛開始 / 只需要系統設定**：從手寫 `defaults.sh` 入手。學習成本最低，讓你先搞懂 `defaults` 系統怎麼運作，也不會有隱私風險。

**現代 macOS（Sonoma+）的 App 設定備份**：直接用 chezmoi。把 App 的 config 檔（很多 App 支援 XDG config dir 或 `~/.config/`）加進 chezmoi 管理，比 Mackup 的 symlink 更穩定。

**有多台電腦 / 有 Linux 機器**：花時間學 chezmoi。前期投資值得，template 系統會讓你的 dotfiles 真正「活起來」。

**已在用 Mackup 且沒問題**：繼續用就好，不用急著換。但如果你在 Sonoma 上遇到 symlink 問題，這時候是遷移到 chezmoi 的好時機。

---

## 反思

選工具之前，先想清楚你要備份的是什麼：

- **macOS 系統設定**（Dock、鍵盤速度）→ `defaults.sh`
- **CLI 工具的設定檔**（`.zshrc`、`.gitconfig`）→ chezmoi
- **GUI App 的設定**（Alfred、Karabiner）→ Mackup

把這三層分清楚，就不會再被「哪個方案最好」的問題困擾了。</content:encoded><media:content url="https://bobochen.dev/_astro/cover.DrrpTa7_.webp" medium="image"/><category>macOS</category><category>dotfiles</category><category>chezmoi</category><category>Mackup</category><category>開發環境</category><enclosure url="https://bobochen.dev/_astro/cover.DrrpTa7_.webp" length="0" type="image/png"/></item><item><title>macOS defaults 備份別踩坑：為什麼 5.3MB 的 plist 不如 130 行的 shell script</title><link>https://bobochen.dev/blog/macos-defaults-export-plist-pitfalls/</link><guid isPermaLink="true">https://bobochen.dev/blog/macos-defaults-export-plist-pitfalls/</guid><description>用 defaults export 備份 Mac 設定聽起來很方便，但打開 plist 一看：5.3MB、1363 個 domain、GPS 座標、廣告 ID、session token。這篇聊為什麼手寫 defaults.sh 才是正確姿勢。</description><pubDate>Fri, 13 Mar 2026 00:00:00 GMT</pubDate><content:encoded>最近在整理我的 dotfiles，準備讓新電腦能「一鍵安裝」。用的是 [chezmoi](https://github.com/twpayne/chezmoi) 管設定檔、Brewfile 管軟體安裝，整套流程已經跑得很順了。

但有一件事我一直沒搞定：macOS 的系統偏好設定。

每次換電腦，Dock 要重新設、Finder 要重新調、鍵盤重複速度要重新改⋯⋯這些瑣碎的設定加起來，大概要花半小時到一小時。

所以我想：不如用 `defaults export` 把整台電腦的設定匯出成 plist，跟 dotfiles 放在一起不就好了？

## 背景

一個完整的 macOS 開發環境大概有這三層：

| 層級           | 內容                               | 負責工具            |
| -------------- | ---------------------------------- | ------------------- |
| 軟體安裝       | CLI 工具、桌面 App                 | Homebrew (Brewfile) |
| 系統設定       | dotfiles、shell config、Git config | chezmoi             |
| macOS 偏好設定 | Dock、Finder、鍵盤速度⋯            | ???                 |

前兩層我都解決了，第三層一直是空的。`defaults export` 看起來就是那個完美答案。

## 發現過程

我跑了這個指令把全部 domain 匯出：

```bash
# 把所有 domain 的 user defaults 一次 dump 出來
# 注意：defaults export -g 只會匯出 NSGlobalDomain「一個」domain，不是全部；
# 要看到全部 domain 得用無參數的 defaults read（或對 defaults domains 列出的每個 domain 逐一 export）
defaults read &gt; ~/macos-defaults-backup.txt
```

得到一個 **5.3MB** 的備份檔。

把它加進 dotfiles repo 之前，我先用 Claude Code 分析了一下內容。這一看嚇了一跳。

### 裡面到底有什麼？

這個 plist 包含 **1,363 個 domain**，大致分成四類：

**1. 系統全域設定（你真正想要的）**

```
Apple Global Domain → AppleInterfaceStyle = Dark
                    → KeyRepeat = 2
                    → InitialKeyRepeat = 15
```

Dock 大小、鍵盤速度、深色模式之類的設定。大概佔不到 5%。

**2. Apple 原生 App 設定（部分有用）**

```
com.apple.dock   → autohide = true, tilesize = 48
com.apple.finder → ShowPathbar = true
```

Finder、Dock、Safari 的開發者工具⋯⋯這些也是你會想帶到新機的設定。

**3. 第三方 App 的私有資料（大量雜訊）**

Microsoft Edge 的 A/B test flight flags（上千個實驗旗標）、Mixpanel tracking tokens、各種 app 的 session 狀態⋯⋯這些佔了整個檔案 90% 以上的體積，而且搬到新機器上完全沒意義。

**4. 機敏資料（不該公開的東西）**

這是最嚇人的部分：

| 資料類型           | 內容範例                          |
| ------------------ | --------------------------------- |
| 廣告 ID            | `advertisingId = 112e622f...`     |
| 搜尋 client ID     | `searchClientId = 30754106...`    |
| GPS 座標           | `location = &quot;339550.0&amp;5376927.4&quot;` |
| Session tokens     | 多個 App 的登入 token             |
| iCloud sync tokens | Apple 服務的同步 token            |

如果我就這樣 push 到 public GitHub repo⋯⋯嗯，不敢想。

## 具體數據 / 結果

| 方案                    | 檔案大小 | Domain 數 | 可讀性                | 隱私風險            |
| ----------------------- | -------- | --------- | --------------------- | ------------------- |
| `defaults export` plist | 5.3 MB   | 1,363     | 極差（二進位 + 雜訊） | 高（含 GPS、token） |
| 手寫 `defaults.sh`      | 3 KB     | ~15       | 極佳（每行有註解）    | 零                  |

5.3MB 的全量匯出，不如 130 行的手寫 script。

我的 `macos/defaults.sh` 長這樣（節錄）：

```bash
#!/bin/bash

# 加快鍵盤重複速度
defaults write NSGlobalDomain KeyRepeat -int 2
defaults write NSGlobalDomain InitialKeyRepeat -int 15

# 停用自動修正（寫程式不需要）
defaults write NSGlobalDomain NSAutomaticSpellingCorrectionEnabled -bool false

# 自動隱藏 Dock
defaults write com.apple.dock autohide -bool true
defaults write com.apple.dock tilesize -int 48

# 顯示隱藏檔案
defaults write com.apple.finder AppleShowAllFiles -bool true

# 顯示路徑列
defaults write com.apple.finder ShowPathbar -bool true

# 重啟相關服務
killall Dock 2&gt;/dev/null || true
killall Finder 2&gt;/dev/null || true
```

每一行都看得懂在幹嘛，而且只設定我「真正在意」的東西。

### 那原始 plist 要怎麼用？

我把它留在 repo 裡，但標記為「查閱用參考」而不是「直接匯入用」。如果換了新電腦後發現少了什麼設定，可以在 plist 裡搜尋對應的 key，然後手動加到 `defaults.sh`。

```bash
# 在 plist 裡找特定設定
grep -i &quot;screenshot&quot; ~/macos-defaults-backup.plist
```

同時把它加進 `.gitignore`，不 commit 到 public repo：

```bash
echo &quot;macos-defaults-backup.plist&quot; &gt;&gt; .gitignore
```

## 反思

### 技術面

`defaults export` 就像 `mysqldump` 不加 `--where`——它忠實地把所有東西都倒出來，但大部分你不需要，有些還有害。

正確做法是**手動挑選**你在意的設定，寫成一個 shell script。好處：

- **可讀**：每行有註解，未來的自己看得懂在幹嘛
- **可控**：只動你確定知道效果的設定，不會有意外
- **安全**：不會意外洩漏隱私資料
- **可移植**：不同 macOS 版本之間相容性更好（全量 plist 有時候會帶入跟版本綁定的設定）

如果想參考別人精選的設定，[mathiasbynens/dotfiles](https://github.com/mathiasbynens/dotfiles) 的 `.macos` 是業界常用的參考範本。

### 心態面

工程師很容易有「既然能自動化，就全部自動化」的衝動。但有些事情，**精心挑選比全量匯出更有價值**。

dotfiles 的精髓不是「把舊電腦複製一份」，而是「把你的偏好用程式碼表達出來」。就像你不會把整個 `node_modules` commit 進 repo，你也不該把整台電腦的 defaults 無腦倒出來。

### 有趣發現

- Microsoft Edge 光是 A/B test 的 flight flags 就是一整面字串，佔了 plist 裡面巨大的篇幅
- 我發現自己裝了一個叫 `AnswerDesign.EyeLoveU` 的番茄鐘 App，設定是 work 20min / rest 5min，完全不記得什麼時候裝的
- plist 裡面有 `com.bobo52310.notionboard.settings`——是我自己開發的 App，看到自己的 bundle ID 出現在系統 defaults 裡面，有種奇妙的感覺</content:encoded><media:content url="https://bobochen.dev/_astro/cover.CXHCR2lo.webp" medium="image"/><category>macOS</category><category>dotfiles</category><category>chezmoi</category><category>開發環境</category><enclosure url="https://bobochen.dev/_astro/cover.CXHCR2lo.webp" length="0" type="image/png"/></item></channel></rss>