什麼是 Dotfile
在 Unix 家族(Linux、macOS)裡,檔名以 . 開頭的檔案會被預設隱藏。這個慣例延伸出一整類檔案:使用者層級的工具設定檔,就叫 dotfile。
最常見的幾個例子:
~/.zshrc— zsh 互動 shell 設定~/.gitconfig— Git 使用者、別名、diff tool~/.ssh/config— SSH 連線規則~/.vimrc/~/.config/nvim/— 編輯器設定~/.config/*— 比較新的工具改走 XDG Base Directory,集中放這裡
dotfiles的用處:透過有結構的管理並快速設定你好你的環境。zsh 一啟動就去讀 .zshrc、Git 跑任何指令前都會讀 .gitconfig。這些檔案構成你整個命令列體驗的「核心」。

為什麼需要 Dotfiles Repo
一次用一台機器的時候,dotfile 躺在~目錄就好。但現實是:
- 換新機:新 MacBook 到手,要重灌 shell 設定、git 別名、ssh config、偏好鍵盤速度、Dock 行為……手動設一輪半天起跳
- 多機同步:桌機、筆電、遠端 server 三份
.zshrc會慢慢模糊,最後沒人知道哪份是對的 - 手動改 config 容易忘:半年後想不起為什麼某個 alias 是這樣寫
解法是把整包設定丟進 Git repo。這就是 Configuration as Code:你的偏好變成版控文字檔,跟基礎設施即程式碼(IaC)是同一個邏輯,只是 scope 落在個人工作站。
第一次建 repo 會花一兩天,但這是一次性投資。之後每次換機都是複利回報 — git clone + 一個腳本,90% 環境就回來了。
我的 repo 公開在:https://github.com/Natsusaka0505/dotfiles,歡迎 clone 或 fork。
Repo 結構

dotfiles/
├── shell/zsh/ # .zshenv / .zshrc / .zprofile / aliases.zsh
├── git/ # .gitconfig / .gitignore_global
├── homebrew/Brewfile # brew / cask / tap 清單
├── ssh/config # SSH host 設定(不含私鑰)
├── macos/defaults.sh # Finder / Dock / 鍵盤 / 截圖等系統偏好
├── iterm2/ # color scheme等設定
├── install.sh # 主安裝腳本
└── README.md
每個目錄對應一個關注點:shell / git / 套件 / ssh / 系統偏好 / terminal 外觀。分得夠細,但不分到讓你找不到東西。
Install 腳本拆解
整包 repo 的靈魂是 install.sh。它用最直接快速的方式解決問題 — symlink,不引入 chezmoi、stow 這類額外工具。
關鍵是這個 link() 輔助函式:
Loading...
邏輯:
- 檢查目標位置是否已經存在「非 symlink」的檔案 — 有就備份成
.bak - 建立 symlink 指回 repo
- 之後
$HOME/.zshrc實際上指向$HOME/dotfiles/shell/zsh/.zshrc,編輯任何一邊都是改版控裡的檔案
整個腳本分成 8 段,每段一件事:
- 裝 Homebrew
brew bundle跑 Brewfile- 裝 Oh My Zsh
- clone zsh-autosuggestions / zsh-syntax-highlighting / powerlevel10k
- 建立 symlinks(
.zshenv、.gitconfig、.gitignore_global、.ssh/config) - 套用 macOS defaults
- 裝 fzf shell 整合
- 下載並匯入 iTerm2 Dracula 配色
set -e 放在最上面,任何一段失敗整個腳本就停,不會留半組裝狀態。

Brewfile — 一鍵裝所有套件
brew bundle 是 Homebrew 內建功能,讀 Brewfile 一次把 CLI / GUI / 字體全部裝好。
節錄:
Loading...
維護方式也一句話:舊機用 brew bundle dump --force 匯出當前狀態覆蓋檔案,新機用 brew bundle --file=... 還原。
Shell 層:zsh + Oh My Zsh + Powerlevel10k
這是整套設定的「體感來源」。核心巧思在 .zshenv:
Loading...
zsh 啟動時一定會讀 ~/.zshenv(唯一無條件會讀的檔案)。只要在這裡把 ZDOTDIR 指向 repo,之後的 .zshrc、.zprofile、aliases.zsh 都從 repo 載入 — ~目錄只需要一個 symlink,不用每個檔案都 symlink。
.zshrc 主要做四件事:
Loading...
- Powerlevel10k:快速、可高度客製的 prompt(
p10k configure互動式走一次) - zsh-autosuggestions:根據歷史灰字補全,按 → 接受
- zsh-syntax-highlighting:指令即時上色,打錯會變紅
- fzf:
Ctrl+R模糊搜歷史、Ctrl+T模糊挑檔案
aliases.zsh 集中放別名:
Loading...
Git 設定
~/.gitconfig symlink 過來,內容包含使用者、預設分支、push / pull 行為、[alias] 區塊、以及用 VS Code 當 editor / diff tool:
Loading...
.gitignore_global 讓全域忽略 .DS_Store、*.swp 這類跨 repo 雜訊,不用每個 repo 都寫一遍。
SSH 設定
~/.ssh/config 只放「client 行為」,不放私鑰:
Host *
AddKeysToAgent yes
UseKeychain yes
IdentityFile ~/.ssh/id_ed25519
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/id_ed25519
UseKeychain yes 讓 macOS 把金鑰 passphrase 存進 Keychain,重開機也不用再輸入。install.sh 會在建 symlink 後把 ~/.ssh 改成 700、config 改成 600,否則 SSH 會拒絕使用。
macOS defaults.sh
macOS 的系統偏好大多可以用 defaults write 腳本化。這個檔案收了我常用的幾條:
Loading...
末尾 killall Finder Dock SystemUIServer 重啟相關 app 套用。
Secrets 策略
永遠不要 commit 的東西:
~/.ssh/id_*(私鑰)- API token、AWS credential
.env
這個 repo 裡只放 ssh/config(行為設定)。私鑰產生方式寫在 README 的「腳本無法自動處理的項目」:
Loading...
.gitignore 也把 install.sh 產生的 *.bak、.DS_Store、.zsh_history、p10k 使用者設定擋掉。
新機首日指令
Loading...
喝杯咖啡回來(可能還沒喝完XD),環境就全好了。

未來可能的升級路線
我現在這套 bash + symlink 簡單直接,但有幾個方向可以優化:
- chezmoi:模板引擎 + secrets 整合(1Password / age 加密)。適合多機器有差異(work vs personal)、想把
.env也納入版控的場景 - fish shell:自帶 autosuggestion / syntax highlight,設定比 zsh 簡單。代價是 POSIX 不相容,部分腳本要翻譯
- starship prompt:跨 shell 的統一 prompt,Rust 寫的、秒開,取代 p10k
- mise:一個工具取代 nvm + pyenv + goenv,專案層級
.mise.toml自動切版本
目前還用不到這些複雜度,但 repo 長期會往這個方向演進。
完整 repo 歡迎到 https://github.com/Natsusaka0505/dotfiles。有更好的做法也請留訊息交流。