sealkeep について
sealkeepは、AIエージェント向けにシークレットを管理します。名前で指定した値をコマンド環境に渡し、出力から伏せ字にします。CLI、MCPサーバー、ガードフックを備えています。
主な機能
- 01コマンドへのシークレット注入
- 02コマンド出力のシークレット伏せ字化
- 03OSキーチェーンやVaultへの保存
- 04シークレットファイルのスキャンと取り込み
- 05値を表示する呼び出しの遮断
活用シーン
- 01APIキーを必要とするエージェントコマンドの実行
- 02.envやINIファイルからの認証情報移行
- 03エージェントの会話履歴へのシークレット混入防止
MCP 対応
`sealkeep mcp`サーバーは、`list_secrets`、`run_with_secrets`、`store_status`ツールを提供します。どのツールもシークレットの値を返しません。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
npx -y @munhq/sealkeepSEALKEEP_CONFIGPath of the config file (stores, aliases, guard rules). Default: the config folder of the OS. With no file, sealkeep uses the OS keyring.ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細

sealkeep
sealkeep を使うと、AI エージェントは秘密情報を見ることなく利用できます。
各秘密情報を shared/stripe/test/SECRET_KEY のような名前で、一度だけ保存します。エージェントは sealkeep list で名前を確認し、その名前を使ってコマンドを実行します。値を読み取ることはなく、値を尋ねる必要もありません。
エージェントは名前を指定して秘密情報を要求します。sealkeep は値を1つのコマンドの環境変数に設定してそのコマンドを実行し、すべての出力で値を [sealkeep:NAME] に置き換えます。値がコンテキスト、トランスクリプト、ファイルに入ることはありません。
agent ──► sealkeep run OPENROUTER_API_KEY -- sh -c 'curl -H "Authorization: Bearer $OPENROUTER_API_KEY" …'
│
├─ reads the value from a store ──► OS keyring (macOS Keychain, Secret Service, Windows Credential Manager)
│ └─► Vault KV v2 (a replica)
├─ starts the command with the value in its environment
└─ redacts the value from stdout and stderr ──► agent sees [sealkeep:OPENROUTER_API_KEY]
以下の4つの要素で構成されています。
- CLI(
sealkeep):set、list、run、import、scan、sync、エイリアス、およびストアコマンドを備えています。 - MCP サーバー(
sealkeep mcp):list_secrets、run_with_secrets、store_statusツールを提供します。どのツールも値を返しません。 - ガードフック(
sealkeep guard):秘密情報を出力するツール呼び出し(たとえばcat .envやsealkeep get)を拒否します。 - エージェントに CLI の使用タイミングと使用方法を伝えるスキル。
インストール
MCP サーバーのみを利用する場合(任意のクライアント)、コマンドは npx -y @munhq/sealkeep です。
{ "mcpServers": { "sealkeep": { "command": "npx", "args": ["-y", "@munhq/sealkeep"] } } }
Claude Code では、プラグインによって MCP サーバー、スキル、ガードフックが一度に追加されます。
/plugin marketplace add munhq/sealkeep
/plugin install sealkeep@sealkeep
以下のフルインストール手順では、Claude Code、Codex、Cursor に同じものをインストールします。
Linux および macOS:
curl -fsSL https://raw.githubusercontent.com/munhq/sealkeep/main/install.sh | sh
このスクリプトは最新リリースのバイナリをダウンロードして SHA256SUMS と照合し、~/.local/bin にコピーした後、sealkeep install を実行します。
Rust を使用する場合:
cargo install --locked --git https://github.com/munhq/sealkeep
sealkeep install
sealkeep install はマシン上の AI クライアントを検出します。各クライアントにスキル、MCP サーバー、ガードフックを追加します。
| クライアント | スキル | MCP サーバー | ガードフック |
|---|---|---|---|
| Claude Code(各設定フォルダー) | <config>/skills/sealkeep | claude mcp add --scope user | <config>/settings.json、Bash、Read、Grep の PreToolUse |
| Codex | $CODEX_HOME/skills/sealkeep | codex mcp add | $CODEX_HOME/hooks.json、PreToolUse(/hooks で一度承認してください) |
| Cursor | ~/.cursor/skills/sealkeep | ~/.cursor/mcp.json | ~/.cursor/hooks.json、beforeShellExecution |
オプション:--client claude,codex を指定すると、指定したクライアントにのみインストールします。--dry-run はインストール計画を表示します。--no-skills、--no-mcp、--no-hooks を指定すると、該当する要素を省略します。sealkeep は JSON ファイルを変更する前に、バックアップ(<file>.bak-<unix time>)を作成します。sealkeep uninstall は install で追加したものを削除します。
sealkeep doctor を実行すると、ストアとクライアントを確認できます。
名前
名前の形式は <scope>/<project>/<env>/<KEY> です。
| 部分 | 値 | 例 |
|---|---|---|
| scope | シークレットの所有者です。personal、雇用主またはクライアントの名前、あるいは複数のスコープで使うアカウントの場合は shared です | personal、acme、shared |
| project | リポジトリまたはサービスです | example-app、stripe、ovh |
| env | prod、dev、test、local です。シークレットに環境がない場合(アカウントの API キーなど)は省略します | prod |
| KEY | プログラムが読み取る環境変数です | DATABASE_URL |
フォルダー名は小文字(a-z、0-9、.、_、-)です。キーは大文字(A-Z、0-9、_)で、run が設定する変数です。
personal/example-app/prod/DATABASE_URL
personal/example-app/dev/DATABASE_URL
personal/example-app/dev/STRIPE_SECRET_KEY -> shared/stripe/test/SECRET_KEY (alias)
acme/ovh/ovh-eu/APPLICATION_KEY
acme/cloudflare/API_TOKEN
shared/stripe/test/SECRET_KEY
shared/openrouter/API_KEY
1 つの値に 1 つの名前を付けます。 2 つのプロジェクトが同じアカウントを使う場合は、その値を shared/… に 1 回だけ保存し、各プロジェクトのフォルダーにエイリアスを作成します。これにより、プロジェクトのフォルダーに必要なすべての変数が揃い、ローテーション時には 1 つの値を変更するだけで済みます。
シークレットを保存する
sealkeep set shared/openrouter/API_KEY -d "OpenRouter, the main account" # writes to every store
sealkeep は値の入力を 2 回求めます。入力内容は表示されません。値をパイプで渡すには、--stdin を使います。
some-password-tool show openrouter | sealkeep set shared/openrouter/API_KEY --stdin
マシン上のシークレットを見つけるには、scan を実行します。各 .env ファイルのパス、キー名、各キーの分類(secret、config、empty)、そして複数の場所にある値ごとのグループ番号が表示されます。値が表示されることはありません。また、認証情報が含まれていることの多いほかのファイルも、パスのみを一覧表示します。
sealkeep scan ~/code --max-depth 4
ファイルをフォルダーにコピーするには、次のようにします。
sealkeep import ../example-app/.env --to personal/example-app/dev \
--map STRIPE_SECRET_KEY=shared/stripe/test/SECRET_KEY
sealkeep import ~/.ovh.conf --to acme/ovh # INI: one folder for each section
sealkeep set personal/github/PAT --from-file ~/.github-token
import は dotenv ファイルと INI ファイル(.ini、.conf、AWS の credentials)を読み込みます。名前のみが表示されます。--map KEY=NAME は値を NAME に保存し、プロジェクトのキーをそのエイリアスにします。NAME にすでに別の値がある場合、import は処理を停止し、その旨を伝えます。インポート後は、元のファイルを削除するか、エージェントがアクセスできない場所に保管してください。
エージェントに使わせる
エージェントに指示します。スキルは、名前の確認には sealkeep list を、コマンドの実行には sealkeep run を使うよう指示します。
sealkeep run shared/openrouter/API_KEY -- sh -c 'curl -sS -H "Authorization: Bearer $API_KEY" https://openrouter.ai/api/v1/key'
sealkeep run --all personal/example-app/dev -- npm run dev
sealkeep run -e GITHUB_TOKEN=personal/github/PAT -- gh api user
名前を指定すると、そのキー名の変数が設定されます。--all FOLDER は .env ファイルと同じように、フォルダー内の各シークレットに対して変数を 1 つずつ設定します。--recursive はサブフォルダーも対象にします。この場合、同じキー名のシークレットが 2 つあるとエラーになります。-e VAR=NAME は別の名前の変数を設定します。STORE:NAME は 1 つのストアのみから読み込みます。
シークレットをファイルから読み取るツールでは、--dotenv を使うと、自分だけが読み取れる一時ファイルが作成されます。$XDG_RUNTIME_DIR/sealkeep が存在する場合、ファイルはその中に作成されます。sealkeep は、コマンド内の {dotenv} の位置にファイルのパスを渡し、コマンドの終了時にファイルを削除します。この例では、テストアカウントのログイン情報を Playwright MCP に渡します。エージェントは ADMIN_PASSWORD という名前を入力し、Playwright が値を設定します。
sealkeep run --dotenv personal/example-app/dev/ADMIN_EMAIL --dotenv personal/example-app/dev/ADMIN_PASSWORD \
-- npx @playwright/mcp@latest --secrets {dotenv}
--secrets <path> は @playwright/mcp のオプションです(README を参照してください)。
自分で値を確認する
sealkeep get shared/openrouter/API_KEY
get が動作するのは、標準入力と標準出力が端末の場合だけです。エージェントは端末なしでコマンドを実行するため、get は拒否し、ガードフックも同様に拒否します。
ストア
sealkeep は、設定ファイルに記載された順にストアを検索し、単独の名前を探します。その名前を持つ最初のストアから値を取得します。
設定ファイルは、Linux では ~/.config/sealkeep/config.toml、macOS では ~/Library/Application Support/sealkeep/config.toml です。$SEALKEEP_CONFIG を使うと、別のパスを指定できます。設定ファイルがない場合、sealkeep は local という名前のキーチェーンストアを 1 つ使います。
[[store]]
name = "local"
kind = "keyring"
[[store]]
name = "vault"
kind = "vault"
address = "http://127.0.0.1:{port}"
mount = "agent"
auth = "kubernetes"
role = "sealkeep"
jwt_command = ["kubectl", "-n", "vault", "create", "token", "sealkeep", "--duration", "10m"]
port_forward = ["kubectl", "-n", "vault", "port-forward", "svc/vault", "{port}:8200"]
[aliases]
"personal/example-app/dev/STRIPE_SECRET_KEY" = "shared/stripe/test/SECRET_KEY"
[guard]
block_dotenv = true
deny = ["vault kv get", "ansible-vault view"]
OS のキーリング
| OS | ストア |
|---|---|
| macOS | ログインキーチェーン |
| Linux, BSD | セッション D-Bus 上の Secret Service(GNOME Keyring、KWallet) |
| Windows | 資格情報マネージャー |
各シークレットは、サービスを sealkeep、アカウントをシークレット名とする 1 つのエントリーです。インデックスエントリー(__index__)には、名前と説明が保存されます。
Linux では、キーリングのロックを解除しておく必要があります。デスクトップセッションでは、ログイン時にロックが解除されます。デスクトップのないセッション(SSH、キーリングのパスワードを使わないログイン)ではキーリングがロックされ、ロック解除のプロンプトを表示できません。起動するたびに、次のコマンドを 1 回実行してください。
sealkeep unlock
ログインキーリングのパスワードを求められ、そのパスワードが gnome-keyring-daemon --unlock に渡されます。各キーリング呼び出しは最大 30 秒(SEALKEEP_KEYRING_TIMEOUT)待機するため、エージェントにはエラーが返され、呼び出しがハングすることはありません。
レプリカとしての Vault
Vault(または OpenBao)の KV v2 マウントには、別のマシンで使うため、またはバックアップ用にキーリングのコピーを保存できます。各フォルダーが 1 つの KV シークレットとなり、各キーがそのフィールドになります。たとえば、shared/stripe/test/SECRET_KEY は agent/shared/stripe/test の SECRET_KEY フィールドです。各シークレットの custom_metadata にはキーとその説明が記載されるため、list は値を読み取りません。
Kubernetes 内の Vault には、sealkeep はポートフォワードを使って Kubernetes API 経由で接続し、有効期間の短い ServiceAccount トークンでログインできます。その場合、マシンに Vault トークンを保存する必要はありません。
sealkeep store add-vault vault \
--address 'http://127.0.0.1:{port}' --mount agent --auth kubernetes --role sealkeep \
--jwt-command 'kubectl -n vault create token sealkeep --duration 10m' \
--port-forward 'kubectl -n vault port-forward svc/vault {port}:8200'
sealkeep sync --from local --to vault # one time, for the secrets that are already in the keyring
set、import、mv はすべてのストアに書き込みます(Vault ストアはフォルダーを含む名前のみを受け付けます)。そのため、ストア間で内容が同じ状態に保たれます。--store NAME を指定すると、1 つのストアに書き込みます。Vault 側には、KV v2 マウント、agent/data/* に対する create、read、update と、agent/metadata/* に対する read、list、update の権限を持つポリシー、および ServiceAccount に紐付けられた Kubernetes 認証ロールが必要です。--auth token を指定した場合、sealkeep は $VAULT_TOKEN、または sealkeep store token vault でキーリングに保存したトークンを読み取ります。
その他のシークレットマネージャー
以下はそれぞれストアの種類です。各ストアはベンダー公式の CLI を実行するため、ベンダー独自のサインイン方法(SSO、サービスアカウント、生体認証)が適用され、sealkeep はベンダーのトークンを保存しません。値は stdin 経由、または自分だけが読み取れるファイル経由で CLI に渡されます。ps で表示されるコマンド引数として渡されることはありません。
| ストア | 追加方法 | レイアウト | 値の受け渡し方法 |
|---|---|---|---|
| AWS Secrets Manager | sealkeep store add-aws aws --region eu-west-1 | 各フォルダーにつき 1 つの JSON シークレット、sealkeep/<folder> | --secret-string file://… |
| Google Secret Manager | sealkeep store add-gcp gcp --project acme-prod | 各名前につき 1 つのシークレット。名前はアノテーションに保存 | --data-file=-(stdin) |
| Azure Key Vault | sealkeep store add-azure azure --vault acme-kv | 各名前につき 1 つのシークレット。名前はタグに保存 | --file … |
| 1Password(CLI 2.23+) | sealkeep store add-1password op --vault Engineering | 各フォルダーにつき 1 つのセキュアノート、各キーにつき 1 つの非表示フィールド | アイテムの JSON を stdin で渡す |
| Bitwarden / Vaultwarden | sealkeep store add-bitwarden bw | sealkeep:<folder> というセキュアノート 1 つ、各キーにつき 1 つの非表示フィールド | アイテムの JSON を stdin で渡す |
| OpenBao | sealkeep store add-vault … | Vault と同じ | Vault と同じ |
Google と Azure ではシークレット ID に使える文字が限られているため、ID は名前の / を -- に置き換え、短いハッシュを付けたものになります。実際の名前はアノテーションまたはタグに保存されます。Azure では削除したシークレットがソフト削除状態で保持され、後で同じ名前に対して set を実行すると復元されます。Bitwarden では、先にロックを解除してください。export BW_SESSION=$(bw unlock --raw)。Bitwarden Secrets Manager CLI(bws)では値をコマンド引数としてしか渡せないため、sealkeep はパスワードマネージャー CLI(bw)を使用します。
SSH キー
SSH エージェントは、パスフレーズ付きのキーをメモリ内にのみ保持します。再起動後は空になり、エージェントの git push は Permission denied (publickey) で失敗します。sealkeep はパスフレーズを保持し、キーを読み込みます。
sealkeep set personal/ssh/ID_ED25519_PASSPHRASE
sealkeep ssh-add ~/.ssh/id_ed25519 --passphrase personal/ssh/ID_ED25519_PASSPHRASE
sealkeep ssh-load # unlock runs it too
ssh-load は sealkeep を SSH_ASKPASS プログラムとして ssh-add を実行します。askpass の処理では、親プロセスが ssh-add であり、1 回限りのトークンが一致した場合にのみ応答します。また、パスフレーズはストアから読み込まれるため、ファイルや出力に書き込まれることはありません。--agent はエージェントのソケットを指定します。デフォルトは $SSH_AUTH_SOCK です。
MCP
sealkeep mcp は stdio で次のツールを提供します。
| ツール | 内容 |
|---|---|
list_secrets | すべての名前、または 1 つの folder に含まれる名前、ストア、説明を返します。 |
run_with_secrets | シェルを介さず、引数のリストである command を実行します。環境変数には folders と secrets を設定し、一時ファイルには dotenv を設定します。終了コード、stdout、stderr を返し、値はマスキングされます。制限時間はデフォルトで 120 秒、最大 900 秒です。各ストリームは 100 KiB で切り詰められます。 |
store_status | 各ストアを現在使用できるかどうかを返します。 |
ガードフック
このフックは次のツール呼び出しを拒否し、エージェントに sealkeep run を使うよう伝えます。
$(…)、バッククォート、bash -c内での使用を含むsealkeep get。- sealkeep のキーチェーンエントリの読み取り:
secret-tool lookup service sealkeep …、security find-generic-password -s sealkeep … -w、keyring get sealkeep …。 block_dotenvが有効な場合、シェルコマンド、または Read と Grep ツールによる.envファイルの読み取り。.env.example、.env.sample、.env.template、.env.distは引き続き読み取り可能です。guard.denyにある各コマンドのプレフィックス。
Claude Code では、さらに 2 つの層が機能します。
- 出力ガード(
sealkeep guard --after。Bash、Read、Grep 用の PostToolUse フック)。ツール呼び出し後、結果を保存済みシークレットの値と照合します。照合にはrunと同じ形式のマスキングを使います。結果に値が含まれている場合、エージェントが結果を読む前にフックがその値を[sealkeep:NAME]に置き換え、メモでシークレット名を示します。これにより、env > out.txtを実行してからout.txtを読み取る場合や、パスに glob や変数を使う場合も保護されます。ストアは最大 4 秒の制限で並行して読み込まれ、応答しないストアからは値を取得しません。Claude Code は元の出力を自身のテレメトリに記録します。 - 拒否ルール(
settings.jsonのpermissions.deny)。sealkeep installはRead(**/.env)、Read(**/.env.local)、Read(**/*.env)と、ほかの.env.*の名前に対するルールを追加します。Claude Code はパスに基づいてこれらのルールを確認するため、Read ツールと、Claude Code が認識するファイルコマンドは、シェルのトリックを使ってもファイルにアクセスできません。block_dotenvが有効な場合にインストール時にルールが追加され、sealkeep uninstallで削除されます。
sealkeep が保護するもの、保護しないもの
sealkeep はシークレットをエージェントのコンテキスト、トランスクリプト、プロジェクトのファイルに残さないようにします。使用のたびに監査ログ(Linux では ~/.local/share/sealkeep/audit.jsonl、または $SEALKEEP_AUDIT_LOG)に、名前とコマンドを記録します。値は記録しません。
マスキングでは、値そのもの、JSON エスケープ形式、パーセントエンコード形式、base64 形式の値を照合します。キー名にシークレットを示す語(KEY、TOKEN、SECRET、PASS、AUTH など)が含まれる場合、パスワード付きの URL の場合、または値が 16 文字以上の場合、その値はマスキングされます。PORT=3000 のような設定値は読み取り可能なままです。4 文字未満の値はマスキングされません。値を別の方法で変換するコマンド(たとえば、値のハッシュ化や一部の抽出)では、sealkeep が照合できない形式で出力されることがあります。
ユーザーとして任意のシェルコマンドを実行できるエージェントは、そのユーザーが読み取れるものを読み取れます。sealkeep はこの点を変えません。安全な方法を簡単に使えるようにし、値にアクセスする一般的な方法を拒否し、使用のたびに記録します。エージェントには、スコープを絞ったキーを渡してください。たとえば、制限付きの Stripe キー、支出上限付きの OpenRouter キー、ウェブログイン用のテストアカウントなどです。
ビルドとテスト
cargo build --release
cargo test --features test-store
test-store 機能は、テスト時に限り、OS のキーリングをファイルに置き換えます。リリース用バイナリには含まれません。
ライセンス
MIT
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。