讓台式機和筆記本的 Claude Code 共享同一套記憶文件,不再重複教 AI 同樣的事情
想像你有兩個助理 — 一個在辦公室(台式機),一個在外面跑(筆記本)。辦公室的助理每天幫你記錄「老闆喜歡 A 方案」「YouTube API 要用 OAuth」這些筆記。但外面的助理完全不知道這些,每次你找他做事,他都問:「欸,這個之前怎麼處理的?」你只能從頭教一遍。共享記憶就是讓兩個助理看同一本筆記本。
Thomas 有一台台式機(主力開發機)和一台筆記本(外出或躺在沙發上用的)。兩台都裝了 Claude Code。問題是:
這不是 Claude Code 的 bug — 它的記憶檔案(MEMORY.md 以及 .claude/ 目錄下的設定)是存在本機的。兩台電腦的本機是獨立的,自然不會互通。
把記憶檔案放進一個 Git repo,兩台電腦都讀寫同一個 repo,用 git push / git pull 同步。就這麼簡單。
如果你只有一台電腦,這份指南對你完全沒用。但如果你像 Thomas 一樣在多台機器之間切換使用 Claude Code,這篇會幫你省下大量重複教 AI 的時間。
在開始動手之前,先搞清楚整體架構。下面這張圖展示了兩台電腦如何透過 GitHub 共享 Claude Code 的記憶文件。
這就像兩個人共同編輯同一份 Google Docs。不同的是我們用 Git 來做版本控制,每個人修改後要手動「上傳」(push)和「下載」(pull)。不像 Google Docs 自動同步,但好處是有完整的版本歷史。
兩台電腦的目錄結構不同,以下是對照:
| 用途 | 台式機路徑 | 筆記本路徑 |
|---|---|---|
| 記憶 Repo 位置 | D:\Backup\Downloads\claude-sonnet-4-6\memories\ |
C:\Users\abc25\repos\downloads-config\ |
| Claude 項目記憶目錄 | ...\memories\(原生) |
...\memory\(Junction 指向 repo) |
| MEMORY.md | memories\MEMORY.md |
memory\MEMORY.md(Junction) |
整個方案只有三個關鍵動作:
git push,確保最新記憶上傳到 GitHubgit 和 gh(GitHub CLI)gh auth login 登入你的台式機上應該已經有一個 Git repo 包含了 Claude Code 的記憶文件。現在要做的是把它 clone 到筆記本。
# 先選擇一個放 repo 的位置
cd C:\Users\abc25\repos
# Clone 記憶 repo(用你自己的 GitHub 帳號名稱替換)
git clone https://github.com/YOUR_USERNAME/downloads-config.git
PowerShell
Clone 完成後,你在筆記本上就有了和台式機一模一樣的記憶文件。
這個 Repo 必須是 PRIVATE。記憶文件裡可能包含你的項目細節、文件路徑、甚至部分代碼片段。絕對不能公開。
# 查看 repo 的可見性
gh repo view YOUR_USERNAME/downloads-config --json visibility
# 應該輸出:
# {
# "visibility": "PRIVATE"
# }
PowerShell
立刻改成 Private:
gh repo edit YOUR_USERNAME/downloads-config --visibility private
改完後再繼續。這不是建議,這是必須做的。
# 進入 repo 目錄
cd C:\Users\abc25\repos\downloads-config
# 列出文件,應該能看到 MEMORY.md 等記憶文件
ls
# 檢查 git remote 是否正確
git remote -v
# origin https://github.com/YOUR_USERNAME/downloads-config.git (fetch)
# origin https://github.com/YOUR_USERNAME/downloads-config.git (push)
PowerShell
Junction 就像遊戲裡的傳送門。你走進 A 門(memory\ 目錄),但實際到達的是 B 房間(repos\downloads-config\)。Claude Code 以為它在讀寫 memory\,但檔案實際上存在 downloads-config\ repo 裡。對 Claude Code 來說完全透明,它根本不知道。
| 特性 | Junction | Symlink (mklink /D) |
|---|---|---|
| 需要管理員權限 | 不需要 | 需要(或開發者模式) |
| 支援跨磁碟 | 支援 | 支援 |
| 只限目錄 | 是(只能指向目錄) | 可指向檔案或目錄 |
| 只限本機 | 是(不能指向網路路徑) | 可指向網路路徑 |
對我們的需求來說,Junction 完全夠用 — 我們只需要把一個本機目錄指向另一個本機目錄。不需要管理員權限是一大優勢。
在筆記本上,打開 PowerShell:
# 確保目標路徑的上層目錄存在
# 假設 Claude Code 項目的 .claude 目錄在:
# C:\Users\abc25\.claude\projects\C--Users-abc25-Desktop\
# 如果 memory 目錄已存在,先備份再刪除
if (Test-Path "C:\Users\abc25\.claude\projects\C--Users-abc25-Desktop\memory") {
Rename-Item "...\memory" "...\memory_backup"
}
# 建立 Junction:
# -Path 是 Claude Code 要讀取的位置(門 A)
# -Target 是檔案實際存放的位置(房間 B = repo 目錄)
New-Item -ItemType Junction `
-Path "C:\Users\abc25\.claude\projects\C--Users-abc25-Desktop\memory" `
-Target "C:\Users\abc25\repos\downloads-config"
PowerShell
# 方法一:查看目錄屬性
Get-Item "C:\Users\abc25\.claude\projects\C--Users-abc25-Desktop\memory" | Select-Object Name, Attributes, Target
# 應該看到:
# Name : memory
# Attributes : Directory, ReparsePoint
# Target : {C:\Users\abc25\repos\downloads-config}
# 方法二:直接列出內容,應該看到 repo 的文件
ls "C:\Users\abc25\.claude\projects\C--Users-abc25-Desktop\memory"
# 應該看到 MEMORY.md 等文件
PowerShell
如果 ls memory 能看到和 ls repos\downloads-config 一模一樣的文件,Junction 就建立成功了。從此 Claude Code 讀寫 memory\ 目錄 = 讀寫 Git repo。
memory 目錄已存在且不為空,New-Item 會報錯。必須先刪除或重命名原目錄-Target 必須是絕對路徑,不能用相對路徑Remove-Item memory)不會刪除目標目錄裡的文件,放心操作Hooks 就像那種你離開房間會自動上鎖的門。你不用記得鎖門(push),它在你離開(結束對話)時自動幫你做。Claude Code 的 Hook 系統讓你可以在特定時機自動執行腳本。
Claude Code 支援在以下時機觸發自定義腳本:
| Hook 名稱 | 觸發時機 | 我們的用途 |
|---|---|---|
PreToolUse |
每次工具呼叫前 | (不使用) |
PostToolUse |
每次工具呼叫後 | (不使用) |
Notification |
發送通知時 | (不使用) |
Stop |
對話結束時 | 自動 git add + commit + push |
編輯 Claude Code 的設定檔 settings.json(位於 ~/.claude/settings.json):
{
"hooks": {
"Stop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "cd D:\\Backup\\Downloads\\claude-sonnet-4-6\\memories && git add -A && git diff --cached --quiet || git commit -m \"auto-sync memory $(date +%Y-%m-%d_%H:%M)\" && git push origin main 2>/dev/null || true"
}
]
}
]
}
}
settings.json(台式機)
| 片段 | 作用 |
|---|---|
cd D:\...\memories |
切到記憶 repo 目錄 |
git add -A |
把所有變更加入暫存區 |
git diff --cached --quiet |
檢查是否有實際變更(沒變就不 commit) |
|| git commit -m "..." |
有變更時才 commit(帶時間戳) |
git push origin main |
推送到 GitHub |
2>/dev/null || true |
忽略錯誤(例如沒有網路時不要崩潰) |
筆記本的設定幾乎一樣,只是路徑不同:
{
"hooks": {
"Stop": [
{
"matcher": "",
"hooks": [
{
"type": "command",
"command": "cd C:\\Users\\abc25\\repos\\downloads-config && git add -A && git diff --cached --quiet || git commit -m \"auto-sync memory $(date +%Y-%m-%d_%H:%M)\" && git push origin main 2>/dev/null || true"
}
]
}
]
}
}
settings.json(筆記本)
台式機和筆記本都需要設定 Stop Hook。誰最後結束對話,誰就負責 push 最新記憶。下次在另一台電腦開始工作時,記得先 git pull(或者也可以設一個啟動 hook 自動 pull)。
你也可以在開始對話前自動拉取最新記憶。但要注意,如果有 conflict,自動 pull 可能失敗。安全的做法是手動 git pull --rebase 後再啟動 Claude Code。
Thomas 的台式機有多個磁碟:D:\、G:\、Z:\ — 但筆記本上完全沒有這些盤符。如果記憶文件裡寫著「設定檔在 D:\Backup\...」,筆記本上的 Claude Code 會一臉茫然。
就像一個人在台北說「信義路二段100號」,另一個人在高雄聽不懂。你需要一張對照表:「台北的信義路 = 高雄的中山路」。路徑映射就是這張對照表,讓兩台電腦的 Claude Code 都能找到正確的資源位置。
在記憶文件中寫明兩台電腦的路徑對應關係:
| 資源 | 台式機 (Desktop) | 筆記本 (Laptop) |
|---|---|---|
| 工作區 (主目錄) | C:\Users\abc25\Desktop |
C:\Users\abc25\Desktop |
| 下載設定 Repo | D:\Backup\Downloads\claude-sonnet-4-6\ |
C:\Users\abc25\repos\downloads-config\ |
| 影片檔案 | G:\My Drive\Videos\ |
(不可用 - 無 G: 磁碟) |
| NAS 備份 | Z:\Archive\ |
(不可用 - 無 Z: 磁碟) |
最可靠的方式是用 hostname 判斷:
# 查看目前電腦名稱
hostname
# 台式機可能是:DESKTOP-ABC123
# 筆記本可能是:LAPTOP-XYZ789
PowerShell
在 MEMORY.md 中加入這段識別規則:
## 多機器識別
- hostname = DESKTOP-ABC123 → 台式機
- 直接存取 D:\, G:\, Z:\ 磁碟
- 所有本地資源可用
- hostname = LAPTOP-XYZ789 → 筆記本
- 只有 C:\ 磁碟
- D:\, G:\, Z:\ 資源需要透過台式機 WinRM 存取
- 或者等回到台式機再處理
MEMORY.md
如果筆記本上的 Claude Code 需要存取只在台式機上的文件(如 G:\ 上的影片),有兩個選項:
不要嘗試讓兩台電腦的路徑完全一致 — 那不現實。相反,讓 Claude Code 知道「我在哪台機器」和「這台機器能用什麼」就夠了。它會自動調整行為。
當兩台電腦同時修改了同一個文件的同一部分,Git 不知道該保留哪個版本,就會產生 merge conflict。最常見的場景:
MEMORY.md 的「已知問題」區塊,push 了MEMORY.md 的同一個區塊git pull — 衝突產生!git pull 之後,打開 MEMORY.md 會看到:
## 已知問題
<<<<<<< HEAD
- YouTube API 上傳有時候會 timeout,需要重試機制
- Token 過期處理已經完成
=======
- YouTube API 上傳超時問題已解決(加了 retry)
- 需要加入 Google Photos API 支援
>>>>>>> origin/main
MEMORY.md (衝突狀態)
就像兩個人在紙上同一行寫了不同的字。Git 不敢自作主張決定留誰的,所以它把兩個版本都標出來,問你:「老闆,你來決定。」<<<<<<< HEAD 是你本地的版本,>>>>>>> origin/main 是遠端的版本。
<<<<<<< 和 >>>>>>> 標記<<<<<<<、=======、>>>>>>>)合併後應該長這樣:
## 已知問題
- YouTube API 上傳超時問題已解決(加了 retry)
- Token 過期處理已經完成
- 需要加入 Google Photos API 支援
MEMORY.md (合併後)
# 將修改後的文件加入暫存
git add MEMORY.md
# 如果是 merge 衝突(git pull 預設)
git commit -m "resolve merge conflict in MEMORY.md"
# 如果是 rebase 衝突(git pull --rebase)
git rebase --continue
# 推送到遠端
git push origin main
PowerShell
git pull --rebasegit pull --rebase 再 push如果衝突搞得太亂,別慌。記憶文件不是代碼 — 丟了不會崩。最壞情況可以:
git stash 暫存本地更改git pull 拉取遠端版本記憶文件裡可能包含項目架構細節、文件路徑、部分代碼邏輯、API 使用模式。這些資訊如果公開,等於告訴全世界你的系統長什麼樣。
任何存放 Claude Code 記憶、設定、Token、配置的 repo,絕對不能是 Public。
# 列出你所有 repo 及其可見性
gh repo list --json name,visibility --limit 100
# 輸出範例:
# [
# {"name": "downloads-config", "visibility": "PRIVATE"}, ← 正確
# {"name": "my-blog", "visibility": "PUBLIC"}, ← 看情況
# {"name": "claude-memories", "visibility": "PUBLIC"} ← 危險!
# ]
PowerShell
# 立刻改為 Private
gh repo edit YOUR_USERNAME/claude-memories --visibility private
# 確認已改成功
gh repo view YOUR_USERNAME/claude-memories --json visibility
# {"visibility": "PRIVATE"}
PowerShell
API Keys、Tokens、密碼不應該出現在 Git repo 裡,即使是 Private repo。
| 類型 | 正確存放位置 | 錯誤做法 |
|---|---|---|
| API Keys | GCP Secret Manager / 環境變數 | 寫在 MEMORY.md 裡 |
| OAuth Token | GCP Secret Manager | 放在 repo 的 JSON 文件裡 |
| 密碼 | 密碼管理器 (e.g., 1Password) | 寫在任何文本文件裡 |
| client_secret.json | 本地 + .gitignore | push 到 GitHub |
Stop Hook 裡的 git push 命令永遠只會推送到該 repo 配置的 remote。確保 remote 指向的是 Private repo。
# 在記憶 repo 目錄下執行
cd D:\Backup\Downloads\claude-sonnet-4-6\memories
# 查看 remote URL
git remote -v
# origin https://github.com/YOUR_USERNAME/downloads-config.git
# 確認這個 repo 是 Private
gh repo view YOUR_USERNAME/downloads-config --json visibility
# {"visibility": "PRIVATE"}
PowerShell
git filter-branch 或 BFG Repo-Cleaner 清除歷史中的機密Junction(又稱 Hard Link for directories)不需要管理員權限,但只能指向本機目錄,不能指向文件,也不能指向網路路徑。Symlink(mklink /D)功能更強,但在 Windows 上需要管理員權限或開啟開發者模式。對於我們的需求(本機目錄指向本機目錄),Junction 完全夠用且更方便。
不會。Hook 裡的 git push origin main 只會推送到該 Git repo 配置的 origin remote。只要你的 remote 指向 Private repo,就不會推到 Public。你可以用 git remote -v 和 gh repo view --json visibility 來雙重確認。
MEMORY.md 確實可能衝突,因為兩台電腦可能修改同一段記憶。但其他文件(如各個項目的獨立設定檔)通常不會衝突,因為通常一次只在一台電腦上操作特定項目。建議:不要同時在兩台電腦開 Claude Code 對話,結束一台再開另一台。
如果你在筆記本上修改了記憶但忘記先 pull 台式機的更新,push 會被拒絕(rejected - non-fast-forward)。解決方法:
# 拉取遠端更新並 rebase 你的本地 commit
git pull --rebase origin main
# 如果沒有衝突,直接 push
git push origin main
# 如果有衝突,解決後:
git add .
git rebase --continue
git push origin main
如果你的 Google OAuth Token 每 7 天就過期,那是因為你的 GCP 專案的 OAuth 同意畫面 (OAuth consent screen) 還在 Testing 模式。Testing 模式下發出的 Refresh Token 只有 7 天壽命。解決方法:把同意畫面改成 Production 模式(發布應用程式 (Publish App))。個人用途不需要 Google 審查,改完立刻生效。詳見 Google OAuth 指南 Part 3。
最簡單的測試方法:
echo "test from laptop" > test-sync.txtgit add test-sync.txt && git commit -m "test sync" && git pushgit pulltest-sync.txt 且內容是 "test from laptop"