1. 專案定位與核心價值

問題背景

傳統開發流程中,.env 檔案是管理環境變數的主流方式,但在 AI 編碼代理(如 Claude Code、OpenAI Codex)日益普及的今天,.env 檔案已成為嚴重的安全隱患:

  1. 代理洩漏風險:AI 代理天生傾向執行 cat .envgrep -r KEY 等指令來理解專案,敏感值可能進入模型 context
  2. 意外提交.env 若未妥善 .gitignore,機密值會直接進入版控歷史
  3. Shell 繼承direnv 等工具將值注入持久 shell,從該 shell 啟動的任何子程序(含 AI 代理)都會繼承所有機密

hush 的解答

hush 是一款專為 macOS 設計的本地端機密管理 CLI (Command Line Interface; 命令列介面) 工具,其核心設計理念為:

  • Value-free declaration(無值宣告):repo 中僅有 .hush.toml 記錄 key 名稱,永遠不含值
  • Encrypted at rest(靜態加密):所有機密值以 age encryption (age 加密) 儲存於 ~/.config/hush/store.age,master key 存放在 macOS Keychain
  • Child-only injection(僅子程序注入):值僅注入 hush run -- <cmd> 啟動的子程序環境,永遠不進入 shell
  • Dual-mode(雙模式):人類獲得 shim + 提示;agent 被自動限制為「use, don’t see(只用、不看)」

與既有工具的對比

面向.env + dotenvdirenvsopshush
值在 repo 中✅ 是❌ 否✅ 加密❌ 完全不在
值進入 shell✅ 是✅ 是N/A❌ 僅子程序
Agent 安全✅ 雙模式
macOS Keychain
RAM disk 編輯
零服務依賴

2. 安裝指南

2.1 系統需求

  • macOS(必要:依賴 Keychain + hdiutil RAM disk)
  • Go 1.24+(若選擇從原始碼安裝)
  • Homebrew(若選擇 brew 安裝)

2.2 安裝方式

方式 A:Go install(推薦 — 本地建置,無 Gatekeeper 隔離問題)

1go install github.com/allen-hsu/hush@latest

方式 B:Homebrew

1brew install allen-hsu/tap/hush

方式 C:從 GitHub Release 下載

https://github.com/allen-hsu/hush/releases 下載對應架構的 tarball(支援 darwin_amd64darwin_arm64)。

2.3 Shell 整合

1hush install     # 在 ~/.zshrc 自動加入 eval "$(hush hook)"

此指令是冪等的(idempotent),重複執行不會重複加入。安裝後重啟 shell 或執行 source ~/.zshrc

2.4 版本確認

1hush version
2# 輸出: hush v0.1.5

3. 核心架構解析

3.1 架構總覽


graph TB
    subgraph "Repository(版控內)"
        TOML[".hush.toml
無值宣告
keys + profile 規則"] end subgraph "macOS Keychain" KEY["age X25519 Identity
master key"] end subgraph "~/.config/hush/" STORE["store.age
age 加密的 JSON
project → profile → key → value"] end subgraph "hush CLI" RESOLVE["resolve
讀 .hush.toml + git branch
→ project/profile"] DECRYPT["store
Keychain 取 key
→ age decrypt"] INJECT["cli/run
env 注入子程序
exec(cmd)"] end subgraph "子程序(唯一能見值的地方)" CHILD["npm run dev
process.env.DATABASE_URL"] end TOML --> RESOLVE KEY --> DECRYPT STORE --> DECRYPT RESOLVE --> INJECT DECRYPT --> INJECT INJECT --> CHILD

3.2 檔案格式

.hush.toml(在 repo 中,已提交,永不含值)

1project = "my-app"           # store 命名空間
2profile = "branch"           # branch | cwd | fixed:<name>
3extends = "base"             # fallback profile
4keys = ["DATABASE_URL", "STRIPE_KEY"]
5shims = ["npm", "pnpm"]     # 自動包裝的指令

store.age(加密 JSON,解密後結構)

1{
2  "my-app": {
3    "base":      { "DATABASE_URL": "...", "STRIPE_KEY": "..." },
4    "feature-x": { "DATABASE_URL": "..." }
5  }
6}

3.3 Profile 解析流程

  1. .hush.tomlproject(若空則用 repo 目錄名)
  2. profile 設定決定 active profile:
    • branch → 當前 git branch 名稱
    • cwd → 工作目錄名稱
    • fixed:<name> → 固定名稱
  3. 對每個宣告的 key,依 extends chain 查找值(active → base),首個命中者勝出
  4. 未找到的 key 回報為 missing error

3.4 Agent 偵測機制

hush 透過兩層偵測判斷是否在 agent 環境中:

  1. 環境變數標記CLAUDECODE(Claude Code)、CODEX_SANDBOX(Codex)、HUSH_AGENT(手動覆寫)
  2. TTY 檢查stdin 非終端機時視為非互動模式

偵測結果影響:

  • hush get → 拒絕執行
  • hush edit → 拒絕執行
  • hush run(若 deny_agent_run = true)→ 拒絕執行
  • agent_profile 設定時 → 切換至 sandbox profile

4. 主要功能與 API 詳解

4.1 指令一覽

指令用途Agent 可用
hush run -- <cmd>解析 profile、注入 env、exec✅(除非 deny_agent_run
hush edit [--profile p]在 $EDITOR 中編輯 profile(RAM disk)❌ TTY only
hush set <KEY>設定單一值(互動提示或 pipe stdin)✅(via pipe)
hush unset <KEY>從 active profile 移除值
hush purge <KEY> [--yes]從所有 profile + .hush.toml 移除--yes
hush ls [--json]列出宣告的 key 與解析來源
hush get [KEY]印出值(TTY only)
hush import [path] [--shred]匯入現有 .env
hush fork [--from p]從 source profile 複製至 active
hush cp <from> <to>複製 profile
hush init建立 .hush.toml 範本
hush install寫入 shell hook 至 ~/.zshrc
hush hook輸出 shell 整合程式碼
hush scrub清除 shell 中的 hush 變數/shim
hush context快速輸出 project/profile(無解密)

4.2 核心使用流程

初始化專案

1cd my-project
2hush init                    # 建立 .hush.toml

從現有 .env 遷移

1hush import .env             # 讀取 .env、加密、寫入 store
2hush import .env --shred     # 遷移後安全刪除原始 .env

設定與管理值

1hush set DATABASE_URL        # 互動式輸入值(不回顯、不進歷史記錄)
2echo "sk_test_xxx" | hush set STRIPE_KEY  # pipe 方式
3hush unset OLD_KEY           # 從 active profile 移除
4hush purge DEPRECATED_KEY --yes  # 從所有 profile 完全移除

使用機密

1hush run -- npm run dev      # 值僅注入此子程序
2hush run -- python app.py
3hush run -- docker compose up

Profile 管理

1hush ls                      # 查看 key 清單與解析來源
2hush ls --json               # 機器可讀輸出
3hush fork --from base        # 從 base 複製至 active profile
4hush cp staging production   # 跨 profile 複製

編輯機密(人類專用)

1hush edit                    # 開啟 $EDITOR,在 RAM disk 上操作
2hush edit --profile base     # 編輯指定 profile

4.3 Exit Code 規範

Code意義
0成功
2設定/用法錯誤
3拒絕執行(如 agent 模式下的 get
4解密/Keychain/執行時錯誤

4.4 JSON 輸出

所有讀寫指令支援 --json 旗標,方便機器解析:

1hush ls --json
2# {"project":"my-app","profile":"main","keys":[{"key":"DATABASE_URL","set":true,"from":"base"},...]}}
3
4hush set API_KEY --json
5# {"ok":true,"action":"set","key":"API_KEY","project":"my-app","profile":"main"}

5. 應用場景與實戰範例

5.1 場景一:全新專案設定

 1cd ~/projects/my-saas
 2hush init
 3
 4# 編輯 .hush.toml
 5cat .hush.toml
 6# project = "my-saas"
 7# profile = "branch"
 8# extends = "base"
 9# keys = []
10
11hush set DATABASE_URL
12hush set STRIPE_SECRET_KEY
13hush set OPENAI_API_KEY
14
15# 從現在起
16hush run -- npm run dev

5.2 場景二:團隊成員遷移現有 .env

 1# 一步遷移
 2hush import .env --shred
 3
 4# 確認結果
 5hush ls
 6# project my-saas · profile main
 7#   DATABASE_URL                set (main)
 8#   STRIPE_SECRET_KEY           set (main)
 9#   OPENAI_API_KEY              set (main)
10
11# 提交 .hush.toml(無值,安全)
12git add .hush.toml
13git commit -m "chore: migrate secrets to hush"

5.3 場景三:功能分支使用不同 DB

1git checkout -b feature/new-db
2hush fork --from base        # 從 base 複製所有值
3hush set DATABASE_URL        # 僅覆寫此 key
4hush run -- npm run test     # 使用 feature/new-db profile

5.4 場景四:Claude Code 開發

 1# Claude Code 環境下(CLAUDECODE 已設定)
 2hush run -- npm run dev      # ✅ 正常運行
 3hush get DATABASE_URL        # ❌ 拒絕:agent 模式
 4hush edit                    # ❌ 拒絕:agent 模式
 5
 6# 加強版:deny_agent_run
 7# .hush.toml: deny_agent_run = true
 8hush run -- npm run dev      # ❌ 也拒絕
 9
10# 折衷版:agent_profile
11# .hush.toml: agent_profile = "sandbox"
12# 預先設定 sandbox profile 使用測試 credentials
13hush run -- npm run test     # ✅ 但使用 sandbox 的測試值

5.5 場景五:啟動代理前清理 shell

1eval "$(hush scrub)"         # 清除所有 hush 管理的 env 變數與 shim 函式
2# 然後安全啟動 AI 代理

6. 資安掃描報告

6.1 掃描摘要

針對 hush 原始碼進行靜態安全掃描,涵蓋所有 .go.yaml.sh 檔案。

6.2 發現項目

🟢 安全設計亮點(正面發現)

#項目說明
1Keychain 存取master key 存於 macOS Keychain,無明文 key 檔案落盤
2RAM disk 編輯hush edit 使用 hdiutil RAM disk,明文不觸碰持久儲存
3Secure removesecureRemove() 先覆零再刪除(best effort on APFS)
4Agent 偵測多層偵測(env marker + TTY)自動鎖定敏感指令
5Atomic writestore 寫入使用 .tmp + rename,避免中斷損毀
6值不入 shellhush run 透過 exec.Command 注入子程序 env,不汙染 parent shell
7密碼不入 CLI 參數hush set 用互動提示或 stdin pipe,避免 ps 洩漏
8權限控制store.age 目錄 0700、暫存檔 0600

🟡 中等風險(設計限制,非漏洞)

#項目風險說明緩解
1環境變數標記可被取消同 uid 程序可 unset CLAUDECODE 繞過 agent 偵測設計文件已明確聲明此為 threat boundary
2APFS secure delete 不可靠即使覆零,CoW 檔案系統可能保留舊資料RAM disk 為主路徑,fallback 時有警告
3exec.Command("sh", "-c", ...) in edit透過 shell 呼叫 editor,理論上可注入值來自 $EDITOR 環境變數,需本地攻擊者
4CI tokens in YAMLGITHUB_TOKENHOMEBREW_TAP_GITHUB_TOKEN標準 GitHub Actions secrets 用法,無硬編碼

🔴 高風險發現

無。本專案的安全設計品質極高,在同類工具中屬於前段水準。

6.3 總結

hush 的安全模型定位清晰:防禦「accidental exposure and an agent’s reflex to read files(意外洩漏與代理的讀檔反射)」,而非防禦「同 uid 的惡意攻擊者」。在這個 threat boundary 內,實作品質優秀。


7. FAQ 常見問題

Q1: hush 支援 Linux 嗎?

不支援。hush 依賴 macOS 專屬功能:Keychain(security CLI)和 hdiutil RAM disk。在 Linux 上需要替換這兩個元件(例如使用 gnome-keyringtmpfs),但目前作者明確將此列為 non-goal。

Q2: 我的 .env 已經在 git 歷史中了,hush 能幫忙嗎?

hush 能阻止未來的洩漏,但無法清除已在 git 歷史中的值。你需要:

  1. 先用 hush import .env --shred 遷移
  2. 再用 git filter-branchBFG Repo-Cleaner 清除歷史
  3. 輪替所有已曝露的 credentials

Q3: hush 和 direnv 可以共存嗎?

可以。但 direnv 會將值注入 shell(hush 不會),所以混用時 direnv 管理的值仍有被代理讀取的風險。建議將 direnv 僅用於非機密的環境設定(如 PATH),機密一律走 hush。

Q4: 多人團隊怎麼分享 secrets?

hush 是單人工具(single-user),不提供團隊分享機制。這是有意的設計決策——team sharing 需要 multi-recipient encryption,會大幅增加複雜度。多人場景建議搭配 Vault、AWS Secrets Manager 等,hush 專注本地開發環境。

Q5: CI/CD 怎麼辦?

hush 僅用於本地開發。CI/CD 環境應使用 GitHub Actions secrets、GitLab CI variables 等平台原生機制。.hush.toml 中的 key 名稱可作為 CI 環境變數設定的參考清單。

Q6: fish shell 支援嗎?

目前 shell hook 僅支援 zsh。fish 使用者需手動在 config.fish 中設定等效整合,或直接使用 hush run -- 而不依賴 shim。


8. 進階技巧與最佳實踐

8.1 .hush.toml 最佳配置

 1project = "my-app"
 2profile = "branch"
 3extends = "base"
 4keys = ["DATABASE_URL", "STRIPE_KEY", "OPENAI_API_KEY"]
 5
 6# 推薦:對高敏感專案
 7disable_get = true           # 即使人類也不能 print 值
 8deny_agent_run = true        # agent 完全不能執行
 9# 或折衷:
10agent_profile = "sandbox"    # agent 使用測試 credentials
11
12# 推薦:常用指令加入 shim
13shims = ["npm", "node", "pnpm"]

8.2 Profile 策略

  • base profile 放共用的預設值(開發 DB、test API keys)
  • branch profile 僅覆寫需要不同值的 key(extends = "base" 自動 fallback)
  • sandbox profile 放純測試 credentials(搭配 agent_profile 使用)

8.3 與 Docker 搭配

1hush run -- docker compose up
2# 或單一容器
3hush run -- docker run -e DATABASE_URL=$DATABASE_URL my-image

hush 注入值到 docker compose 的程序環境中,docker-compose.yml 中使用 ${DATABASE_URL} 即可接收。

8.4 搭配 Makefile

1dev:
2	hush run -- npm run dev
3
4test:
5	hush run -- npm test
6
7deploy:
8	hush run -- ./scripts/deploy.sh

8.5 Git Worktree 工作流

hush 的 per-worktree 設計天生適合 git worktree

1git worktree add ../my-app-feature feature/x
2cd ../my-app-feature
3# .hush.toml 已在 repo 中,自動繼承
4# profile 自動解析為 feature/x(branch mode)
5hush run -- npm run dev      # 使用 feature/x 的值

9. 整合進其他工作流

9.1 與 Claude Code 整合

.claude/settings.json 中加入以下權限規則,形成縱深防禦:

1{
2  "permissions": {
3    "deny": [
4      "Read(.env*)",
5      "Bash(cat .env*)",
6      "Bash(grep .env*)"
7    ]
8  }
9}

搭配 hush 的 agent 偵測,Claude Code 環境下:

  • .hush.toml 可讀(僅 key 名稱)
  • hush run -- <cmd> 可用(若未設 deny_agent_run
  • hush get/hush edit 被拒絕

9.2 與 Codex 整合

Codex sandbox 環境中,CODEX_SANDBOX 環境變數自動觸發 hush 的 strict 模式。無需額外設定。

9.3 與 pre-commit hooks 搭配

1# .git/hooks/pre-commit
2#!/bin/sh
3# 確保 .env 不被意外提交
4if git diff --cached --name-only | grep -q '\.env'; then
5  echo "ERROR: .env files should not be committed. Use hush instead."
6  exit 1
7fi

9.4 啟動代理前的清理

1# 在 shell 腳本中啟動 AI 代理前
2eval "$(hush scrub)"
3# 然後啟動代理
4claude-code

10. 重點摘要 Checklist

  • ✅ macOS 限定工具,依賴 Keychain + hdiutil
  • ✅ 安裝方式:go install / brew install allen-hsu/tap/hush
  • ✅ 一步遷移:hush import .env --shred
  • ✅ 使用機密:hush run -- <cmd> 是唯一正途
  • ✅ 值永不進入 shell,僅存在於子程序環境
  • ✅ Agent 自動偵測:CLAUDECODE / CODEX_SANDBOX / HUSH_AGENT / non-TTY
  • ✅ 編輯機密用 RAM disk,明文不落盤
  • .hush.toml 可安全提交至 repo(僅 key 名稱)
  • ✅ Profile 按 git branch 自動切換,支援 extends 繼承
  • --json 旗標支援機器可讀輸出
  • ✅ Per-project agent policy:disable_get / deny_agent_run / agent_profile
  • ✅ Exit code 明確:0/2/3/4 分層

11. 進一步閱讀

官方文件

相關技術

  • age encryption — hush 使用的加密函式庫
  • direnv — 傳統 shell 層級環境變數管理工具(hush 的對比對象)
  • sops — Mozilla 的加密機密管理工具(hush edit 靈感來源)
  • macOS Keychain Services — hush 存放 master key 的系統服務

延伸思考


12. 與 AI-Knowledge Template (AIKT) 的關聯性

12.1 概述

hush 作為一款 macOS 專屬的 agent-safe 機密管理工具,與 AIKT 的 22 層架構有著天然的互補關係。AIKT 的各 Layer 大量依賴 API key、access token、service credential 等機密資訊,而 hush 正好提供了一種安全的方式來管理這些機密——特別是在 Claude Code 作為主要執行環境的情境下。

12.2 與各 Layer 的搭配場景

高度相關的 Layer

Layer名稱搭配方式
Layer 5ai-notebooklmNotebookLM API 的 credential 可由 hush 管理,hush run -- bash scripts/notebooklm-save.sh
Layer 9paper-searchPubMed/Semantic Scholar 等 API key 存入 hush store
Layer 10paper-qa-liteOpenAI/Anthropic API key 用於 embedding 與 RAG,是最敏感的 credential
Layer 18research-pipeline-v2多管線研究工作流涉及多個 API credential,hush 可統一管理
Layer 19tu-plan-generatorToolUniverse 的 API key(OpenRouter 等),搭配 agent_profile = "sandbox" 使用測試 key
Layer 22company-intel盡調資料涉及商業機密 API,搭配 hush 的 profile 隔離

中度相關的 Layer

Layer名稱搭配方式
Layer 1ai-savemarkitdown/playwright 等工具若需認證,可走 hush
Layer 2ai-gh-saveGitHub Personal Access Token 管理
Layer 3ai-autofetchcron job 執行的 API 呼叫,需在 shell 中先 hush run 包裝
Layer 12gh-tutorial-qdGitHub API 存取 token
Layer 16rtkrtk 本身不需 credential,但它代理的指令可能需要
Layer 21blog-publishNetlify deploy token 管理

低度相關(本地處理為主)

Layer名稱說明
Layer 4graphify純本地處理,通常不需 API key
Layer 6gitnexus純本地符號索引
Layer 7quarkdown本地 markdown 編譯(--deny=network 為預設)
Layer 8docling本地文件解析
Layer 11kami本地 HTML → PDF
Layer 17video-to-tutorial本地 whisper + ffmpeg
Layer 20sync-v1-to-clean本地 git 操作

12.3 實作建議

在 AIKT 環境中導入 hush 的推薦步驟:

 1# 1. 安裝 hush
 2go install github.com/allen-hsu/hush@latest
 3hush install
 4
 5# 2. 在 AIKT v1 根目錄初始化
 6cd "/config/workspace/1. 25-26 Finished Project/260414 Cli tools/260416 AI-knowledge_template v1"
 7hush init
 8
 9# 3. 遷移現有 API keys
10hush set OPENROUTER_API_KEY       # ToolUniverse / perplexity-search
11hush set ANTHROPIC_API_KEY        # paper-qa-lite embedding
12hush set GITHUB_TOKEN             # gh-save / gh-tutorial-qd
13hush set NETLIFY_AUTH_TOKEN       # blog-publish
14
15# 4. 在 scripts 中包裝
16# 原始: bash scripts/paper-search.sh "query"
17# hush: hush run -- bash scripts/paper-search.sh "query"
18
19# 5. 設定 agent 政策
20# .hush.toml 中加入:
21# agent_profile = "sandbox"       # Claude Code 使用測試 key

12.4 與 AIKT 機密邊界的協同

  • company-intel:使用獨立的 project namespace(ci-<company>),避免與其他專案的 credential 交叉
  • research-pipeline-v2 internal modeagent_profile = "internal" 指向含 decoy 資訊的 profile

12.5 限制與注意事項

  1. macOS 限定:若 AIKT 執行環境為 Linux(Docker/遠端伺服器),hush 不適用,需改用其他方案(如 passage 原生、sops
  2. Claude Code 的 CLAUDECODE 環境變數:hush 預設偵測此標記。若需讓 Claude Code 透過 hush run 執行指令(不設 deny_agent_run),需確保 scripts 內部也走 hush run 包裝
  3. cron job(ai-autofetch):需在 cron entry 中使用 hush run -- bash scripts/ai-autofetch.sh,而非直接呼叫
  4. 單人工具:AIKT 目前為單人使用,與 hush 的 single-user 定位完美契合;若未來需多人協作,credential 分享需另覓方案