SSD Nodes Learn 🎉 VPS $5.50/月起
指南 Matt Connor作者: Matt Connor · 已更新 2026-08-13

Compartment 離線加密記憶與金鑰遺失風險

Compartment 以 XChaCha20-Poly1305 加密 agent 記憶,embedding 也在本機處理。了解離線威脅模型的防護範圍,以及遺失 passphrase 後無法復原的後果。

Compartment 的不同之處

Compartment 是一種 agent 記憶儲存庫,會在建立每筆記錄的機器上進行加密,且不會連線至網路服務。它有兩項設計與其他 agent 記憶工具不同。Vault 是單一密封檔案,只能以您的 passphrase 開啟;embedding 步驟則在本機執行,因此記憶內容不會被傳送到其他地方轉換成向量。4.6.0 版於 10 August 2026 發布,採用 Apache-2.0 授權,並可從 PyPI 安裝。

這是關於威脅模型的聲明,因此本指南會依此看待。靜態加密搭配離線設計,可保護特定項目。但其他項目仍可能暴露,而這個落差正是第二天開始會遇到問題的地方。

本指南依據專案自己的文件與 release notes,並於 11 August 2026 閱讀。Compartment 除了命令列工具外,也提供桌面應用程式、macOS 的 menu bar 項目及 Windows 的通知區域圖示;此外,無法從自動化容器驅動 passphrase 提示。以下內容是文件所述的行為,不是本指南實際測量的結果。請先在備用機器上執行,確認可靠後再用於任何重要資料。

靜態加密實際能防護什麼

Vault 使用 XChaCha20-Poly1305 封存。這是一種 AEAD(authenticated encryption with associated data,附加資料驗證加密)密碼。存放主金鑰的 keyslot 則使用 Argon2id 加密包裝。Argon2id 是專為降低速度並增加記憶體需求而設計的密碼雜湊函式。這會帶來兩個結果。即使檔案副本出現在遭竊的磁碟、舊備份或支援案件附件中,內容也只是一串無法使用的位元組。檔案開啟時若有單一位元遭到翻轉,驗證就會失敗,因此資料損毀會明確顯示錯誤,而不是產生錯誤結果。

Embedding vectors 也會加密,這點的重要性可能超出預期。Embedding 不是 hash。Embedding inversion 相關研究已能僅根據向量,還原原始文字中可讀的片段。因此,若將未加密的向量索引放在加密資料庫旁邊,實際上幾乎等同於讓資料庫保持開放狀態。Compartment 不會將未加密的索引寫入磁碟。

刪除就是真正的刪除。每筆記錄都有自己的金鑰,而 compartment forget --shred 會銷毀該金鑰。因此,遺留的密文無法由任何人解密,包括你自己。相較之下,從資料庫檔案刪除的資料列通常仍會留在可用頁面中,直到其他資料覆寫該區域。

離線運作是另一個重點。系統不會上傳任何資料,因此沒有由供應商帳戶保存你的記憶,也沒有可能外洩的 API key。

不受 Compartment 保護的內容

這項保證只到 vault 邊界為止,而這個邊界比想像中更近。

agent 會讀取明文。 Recall 會解密記憶,並將文字交給 agent。如果該 agent 是託管模型,記憶會隨下一個 prompt 傳送至模型供應商,與 context window 中的其他內容完全相同。靜態加密能保護檔案,但無法保護 retrieval。因此,避免讓 AI agent 接觸機密 中的規則不會因為 store 已加密而放寬:將密碼儲存為記憶,就等於安排系統自動將密碼貼入 prompt。

執行中機器上已解鎖的 vault 就是開啟狀態。 專案的安全說明已明確指出這點。vault 解鎖期間,master key 與工作資料集會留在 RAM 中;Python 無法保證清除 buffer,而 swap 或休眠映像可能會將該記憶體寫入磁碟。以你的使用者身分執行的 malware 不必破解 cipher,因為它可以要求已解鎖的 vault 提供資料。

呼叫端身分是宣告式的。 可以依呼叫端限制 namespaces,但呼叫端名稱來自 host process,因此會謊報名稱的 host 會取得它所宣稱的 grants。Namespace 權限屬於組織管理機制,不是防禦惡意本機程式的安全邊界。

Shredding 無法涵蓋副本。 forget --shred 會刪除目前檔案內的 key。shred 前建立的 backup 仍保留該筆記錄,也仍可使用當天的 passphrase 開啟。

弱 passphrase 會使討論失去意義。 Argon2id 會提高每次猜測的成本,但無法挽救出現在 word list 中的 passphrase】【。

從固定版本安裝 Compartment

Compartment 需要 Python 3.11 或更新版本。此專案更新快速,截至 2026 年 8 月 10 日已在 PyPI 發布 30 個版本,因此請固定版本,不要在安裝當天直接使用當時的最新版本。

python3 --version
pip install "compartment==4.6.0"
compartment --version
compartment init

compartment --version 應輸出您固定的版本。如果 shell 回應 compartment: command not found,表示安裝目錄不在 PATH 中;在大多數系統上,該目錄是 ~/.local/binpipx install compartment==4.6.0uv tool install compartment==4.6.0 會自行管理路徑,因此不會有這個問題。

compartment init 會要求輸入兩次密碼,且不會回顯任何內容。這組密碼是唯一的金鑰。此專案不會產生密碼或復原片語,這是刻意的設計:軟體不會持有任何您不知道的認證資料。

在將任何內容連接到它之前,先確認結果。

compartment status

正常的 vault 會回報已解鎖。如果回報已鎖定,請執行 compartment unlock 並輸入密碼。重新啟動後 vault 會再次鎖定,因為維持解鎖狀態的認證取決於每次開機產生的 secret。在 macOS 上,compartment unlock --keychain 會將該認證儲存在系統 keychain 中,以選擇在重新開機後保留解鎖狀態。

資料實際儲存的位置

預設 vault 位於 ~/.compartment/memory.vault。在任何命令中使用 --vault PATH 指定其他位置,或設定 COMPARTMENT_VAULT 環境變數。

這一個檔案就是完整的儲存庫。檔案開頭是標頭,其中包含格式版本與 Argon2id keyslots,接著是已封存的 payload,最後是隨著新記憶加入而附加的 journal entries。每個 journal entry 都會記錄自身的長度,以及該長度的 CRC (cyclic redundancy check)。因此,因當機而中斷的寫入會被辨識為遭截斷的 entry,不會被當成資料讀取。Compaction 會序列化 vault、寫入暫存檔、執行 fsync,然後將暫存檔重新命名到目標位置,因此 reader 永遠不會看到寫入不完整的 vault。

實際好處是:backup script 只需複製一個路徑。缺點是:你無法對它執行 grep,也不能在文字編輯器中修復它。如果你想要能用 cat 讀取並提交至 git 的記憶,Memmy 的純文字本機記憶檔案則是另一種取捨。兩者都合理,取決於你擔心的是筆記型電腦遭竊,還是工具損壞。

compartment uninstall 會移除軟體,但保留 vault。只有在確定要移除 vault 時,才傳入 --purge

將其接入 agent

一個指令即可接入受支援的用戶端。

compartment integrate --list
compartment integrate claude

對 Claude Code 而言,此指令會先備份檔案,再寫入 MCP (model context protocol) server 項目與 PostToolUse hook 至 ~/.claude/settings.json,在 ~/.claude/skills/ 下安裝 /compartmentalize skill,並將受管理區塊加入 ~/.claude/CLAUDE.md,告知 agent:Compartment 優先於其原本使用的檔案式記憶。請確認兩個部分:

compartment hook status
compartment recent

若要手動註冊 server,請改用:

claude mcp add --scope user compartment -- \
    compartment --vault ~/.compartment/memory.vault --caller claude-code serve

其他支援 MCP 的 host 也使用相同的 server,但需指定各自的 caller name。

{ "mcpServers": { "compartment": {
    "command": "compartment",
    "args": ["--vault", "/path/to/memory.vault",
             "--caller", "your-agent-name", "serve"] } } }

為每個 host 指定不同的 --caller 值。這是 audit log 記錄的標籤,也是寫入 namespace grant 時使用的 key,因此共用名稱會讓兩者都失去作用。

如果 Claude Code 已經將事實寫入自己的記憶檔案,compartment import-claude --dry-run 會先顯示預計搬移的內容,不會立即搬移任何資料。請先閱讀 Claude Code 在記憶檔案中保留的內容,因為將一整年的筆記匯入全新的 vault,會使記憶儲存區塞滿原本沒有人打算保留的內容。

本機 vault 的速度有多快

以下數據是該專案針對個人規模 vault 發布的數值。數據來自專案文件,不是本次實際執行所得。

ChartCompartment published local latency, milliseconds
The data behind this chart
[
  {
    "label": "Store one memory, end to end",
    "latency_ms": 40
  },
  {
    "label": "Embed one memory, bundled model",
    "latency_ms": 25
  },
  {
    "label": "Hybrid search, median",
    "latency_ms": 11.6
  },
  {
    "label": "Vector search at 20k records, p95",
    "latency_ms": 0.68
  }
]

儲存一筆記憶的延遲為 40 ms;對 20,000 筆記錄執行向量搜尋時,第 95 百分位延遲為 0.68 ms。該專案主張將記憶保留在本機,依據的是延遲比較:對託管記憶 API 執行一次網路往返,通常就比這裡完整混合搜尋的 11.6 ms 中位數更慢。

兩項設計細節可以解釋這些搜尋數據。在 20,000 筆記錄以下,Compartment 會將查詢與每個向量逐一比較,因此召回率依設計就是精確的,而非近似值。超過這個數量後,Compartment 會切換至 HNSW(hierarchical navigable small world),這是一種近似索引,以少量召回率換取速度。vault 也會記錄 embedding model 的 SHA-256 雜湊值,若使用不同模型便拒絕開啟,因為不同模型產生的向量可能在不出現任何錯誤的情況下彼此比較,而回傳的分數沒有意義。

備份,以及明年仍能開啟的副本

鎖定的 vault 是單一可攜式檔案,因此搬移它就是複製檔案。

compartment lock
scp ~/.compartment/memory.vault other-machine:
compartment --vault memory.vault unlock

先鎖定 vault。agent 寫入期間進行複製,可能會截取正在追加的 journal 記錄。雖然 CRC framing 讓讀取器可以略過末尾的片段,但其中的記憶內容已遺失。compartment lock --sign 會使用 Ed25519 manifest 封存檔案,接收端不需要持有 passphrase,也能驗證副本是否完整抵達。

由於檔案已經封存,普通的雲端儲存空間即可存放。這正是靜態加密直接發揮效益的地方:備份目標永遠看不到任何記憶內容。

請注意兩點。Shredding 不會影響備份,因此今天以 cryptographic shredding 刪除的記錄,對持有上週 passphrase 的人而言,仍可在上週的副本中讀取。compartment export --plaintext 會將整個 vault 以未加密形式寫出;這適合用來遷移至其他工具,但不應將產生的檔案留在 ~/Downloads 中。

保留少量副本,並標註日期。沒有人清理時,memory store 就會從資產變成負擔;過時的 agent 記憶為何會悄悄污染檢索 說明了這一點。

金鑰處理、輪替與第二因素

compartment rekey
compartment 2fa enable
compartment 2fa status

rekey 會在目前檔案的 keyslot 中重新包裝主金鑰,以變更 passphrase。舊副本仍保留舊 passphrase,因為這些位元組是在變更前封存的,之後不會回頭修改。也一併輪替副本,否則已撤換的 passphrase 仍可能開啟某些內容。

2fa enable 會加入 keyfile 作為第二因素,並在金鑰衍生時與 passphrase 結合,因此兩者缺一不可才能開啟 vault。這也會讓可能遺失的項目數量加倍。請將 keyfile 保存在存放 vault 的機器之外。

對於指令碼與 CI(continuous integration),passphrase 可以透過 COMPARTMENT_PASSPHRASE 環境變數傳入,unlock --passphrase-stdin 則會從 pipe 讀取。優先使用 pipe。相同使用者擁有的其他程序可以讀取環境變數,而且環境變數通常會出現在工作日誌中。

稽核歷程採用雜湊鏈結,compartment audit verify 會逐一檢查並回報第一個斷裂的鏈結。每次還原後都應執行這項檢查,因為檔案遭到靜默截斷時,通常會在此時顯現。

遺失密碼片語時會發生什麼事

什麼事都不會發生,這正是設計目的。沒有重設機制、復原片語或可供書寫的地址,因為除了記憶與可選的金鑰檔案之外,系統沒有其他金鑰副本。Vault 仍會是一個由看似隨機的位元組組成的檔案。

因此,復原計畫不是針對 Vault,而是針對密碼片語。在執行 compartment init 的當天,將密碼片語記錄在密碼管理器中。接著進行測試:鎖定 Vault,只使用記錄的內容將其解鎖;確認可正常解鎖後,再讓 agent 開始填入內容。

Compartment 或記憶體伺服器

Compartment 的設計是單機使用。共用資料代表必須複製鎖定的檔案,或執行匯出與匯入;由於沒有並行寫入,讓筆記型電腦與工作站指向同一個檔案,會互相覆寫工作內容。

如果多台機器需要同時使用相同的記憶體,這就是伺服器問題。在 VPS 上自架 Mem0 記憶體伺服器可解決這個問題:一個端點、多個用戶端,且記憶內容不會隨筆記型電腦離線而消失。必須明確說明其代價。該伺服器會執行能讀取所儲存資料的程序,因此威脅模型也會納入 VPS,以及所有能連線到其 API 的人員。

請根據你實際擔心的資料損失選擇。如果你擔心的是筆記型電腦遭竊,或供應商讀取你的筆記,較強的選擇是加密的本機保存庫。如果你擔心的是切換機器後,代理程式立即忘記所有內容,則應選擇伺服器。

FAQ

Compartment 的加密實際上保護什麼?

它保護的是檔案。Vault 使用 XChaCha20-Poly1305 封存,keyslot 使用 Argon2id 包裝,embedding vectors 也經過加密。因此,即使磁碟遭竊或取得舊備份,裡面也只有無法讀取的位元組。它不會保護執行中機器上的已解鎖 vault,因為 vault 開啟時 master key 會留在 RAM 中;它也不會限制 agent 在 recall 以明文傳回 memory 後如何處理該 memory。

如果 Compartment 處於離線狀態,我的 memory 對模型供應商而言是私密的嗎?

只有在 recall 之前是。儲存與搜尋都不需要網路,embedding model 也在本機執行,因此寫入時不會有資料離開機器。讀取時,agent 會收到明文;如果該 agent 使用 hosted model,memory 就會進入 prompt,並與其他 context window 內容一樣傳送給供應商。請勿將 credential 儲存為 memory。

如果遺失 Compartment passphrase,會發生什麼事?

Vault 將無法復原,這是刻意設計的結果。Compartment 不會產生 seed 或 recovery phrase,也不持有任何不在你手上的 credential,因此沒有可重設的內容。請將 passphrase 存放在 password manager 中,並將任何 2FA keyfile 保存在儲存 vault 的機器之外;在 vault 存入任何重要內容前,先確認你能解鎖副本。

兩台機器可以共用同一個 Compartment vault 嗎?

不能同時共用。已鎖定的 vault 是單一可攜式檔案,文件記載的方式是先鎖定、複製檔案,再使用 --vault 在另一台機器上解鎖。這不支援並行存取,因此兩台機器同時寫入同一個檔案會遺失 memory。需要此功能時,請執行 memory server。

#agent-memory#compartment#encryption#offline#privacy