macOS KeychainはAPIキーをAES-256-GCMで暗号化し、.envファイルより安全にClaude Codeから利用できます。
- 要点1: .envファイルのAPIキーはGit誤コミットやシェル履歴への露出リスクがある
- 要点2: security コマンド1行でKeychainへの登録・読み出しが可能。アカウント名は $USER で統一するのがポイント
- 要点3: SSH経由でのアクセス時はKeychainがロックされる問題があり、unlock-keychainコマンドで対処できる
対象: Claude CodeでAPIキーを扱うスキル開発者・AI自動化担当者
今日やること: 既存の.envファイルのAPIキーをsecurity add-generic-passwordでKeychainに移行する
この記事の目次
Claude CodeでAPIキーを管理するなら、.envファイルへの平文保存よりmacOS Keychainを使った管理が正解です。
「スクリプトにAPIキーを直書きしてしまっている」「.envファイルをGitにコミットしてしまいそうで不安」——こうした悩みは、Claude Codeを活用してスキルや自動化ツールを開発しているエンジニア・非エンジニアの両方で共通する課題です。
この記事では、macOS Keychainを使ったAPIキーの登録・読み出し方法から、実際のClaude Codeスキル開発で遭遇したつまずきポイント(アカウント名の不一致・SSH経由でのアクセス問題)の解決策まで、実践的に解説します。
.envファイルのAPIキー管理、実はこんなリスクがある
多くの開発者が最初に選ぶのが、プロジェクトルートに.envファイルを作り、そこにAPIキーを保存する方法です。しかしこのアプローチには、見落としがちなセキュリティリスクが複数あります。
Gitへの誤コミットは誰にでも起こる
.gitignoreに.envを追記するのを忘れた、あるいは書き方を間違えた——こうした小さなミスが、APIキーの公開につながります。セキュリティサービスのGitGuardian社の調査によると、GitHubには毎年数百万件のシークレットが誤コミットされており、そのうちAPIキーは最も多いカテゴリの一つです。
誤ってコミットされたAPIキーは、たとえすぐに削除しても、Gitの履歴に残ります。完全に無効化するには、APIキー自体の再発行が必要になります。
シェル履歴やログへの意図しない露出
export API_KEY="sk-xxxxx"とターミナルに直接入力する方法も危険です。macOSのzshはコマンド履歴を~/.zsh_historyに保存するため、APIキーがそのまま平文でファイルに残ります。別のユーザーや別のプロセスが読み取ってしまうリスクがあります。
複数のプロジェクトで同じキーを使い回す問題
.envファイルはプロジェクトごとに存在するため、同じAPIキーを複数プロジェクトで使う場合、それぞれのファイルに平文でコピーすることになります。管理すべきファイルが増えるほど、漏洩のリスクも比例して高まります。
macOS Keychainとは — OSレベルのセキュリティ管理
macOS Keychainとは、Appleが提供するOSレベルのパスワード・シークレット管理システムです。SafariのパスワードやWi-Fiのパスフレーズも、内部的にはKeychainで管理されています。
APIキーの管理に使うメリットは、そのセキュリティの仕組みにあります。
Keychainのデータはどこに保存されるか
Keychainのデータは~/Library/Keychains/login.keychain-dbに保存されます。このファイルはmacOSのセキュリティ機能によって保護されており、認証なしに他のプロセスが読み取ることは原則できません。
Apple公式のドキュメントによると、KeychainのデータはAES-256-GCMで暗号化されています。テーブル全体を保護するテーブルキーと、各エントリを個別に保護するper-rowキーの2層構造です。
.envファイルとの4つの違い
| 項目 | .envファイル | macOS Keychain |
|---|---|---|
| 保存形式 | 平文テキスト | AES-256-GCM暗号化 |
| Git誤コミットリスク | あり(gitignore設定が必要) | なし(ファイルシステム外) |
| 複数プロジェクトでの共有 | ファイルのコピーが必要 | 1箇所の登録で全プロジェクトから参照可能 |
| アクセス制御 | なし(読み取り権限があれば誰でも) | macOSの認証が必要 |
\ Claude Codeの導入、何から始めればいいかわかります /
法人向けClaude Code個別指導の無料相談はこちらAPIキーをKeychainに登録する(security add-generic-password)
では実際に、securityコマンドを使ってAPIキーをKeychainに登録する方法を解説します。securityコマンドは、macOSに標準搭載されているKeychainを操作するためのCLIツールです。
基本コマンド構文
security add-generic-password \ -s "サービス名(APIキーの識別名)" \ -a "$(whoami)" \ -w "APIキーの値" \ -U
オプションの意味を解説します。
| オプション | 意味 | 例 |
|---|---|---|
-s |
サービス名(Service)。APIキーを識別するための名前 | GEMINI_API_KEY |
-a |
アカウント名(Account)。誰のキーかを示す | $(whoami)(= riku など) |
-w |
パスワード(APIキーの値) | AIzaSyXXXXXXXX |
-U |
同名のエントリがあれば上書き更新(Update) | — |
具体的な登録例をいくつか示します。
# Gemini API Keysecurity add-generic-password -s "GEMINI_API_KEY" -a "$(whoami)" -w "AIzaSyXXXXXXXX" -U# X(Twitter)Bearer Tokensecurity add-generic-password -s "X_BEARER_TOKEN" -a "$(whoami)" -w "AAAAAAAAAAAAAXxxx..." -U# OpenAI API Keysecurity add-generic-password -s "OPENAI_API_KEY" -a "$(whoami)" -w "sk-proj-XXXXXXXXX" -U
アカウント名(-a)は $USER で統一する理由
ここは 実際のスキル開発で最も多くのつまずきが発生するポイントです。
あるプロジェクトで、Gemini APIキーをKeychainに登録した際に-a "gemini"と設定してしまったことがありました。スクリプト側では-a "$(whoami)"(= riku)でKeychain検索しているため、キーが見つからずエラーになり続けました。
このトラブルを防ぐために、アカウント名は常に$(whoami)または$USERで統一することを強く推奨します。
# NG: アカウント名をサービス名で登録してしまうsecurity add-generic-password -s "GEMINI_API_KEY" -a "gemini" -w "AIzaSyXXX" -U# OK: アカウント名をシステムユーザー名で統一security add-generic-password -s "GEMINI_API_KEY" -a "$(whoami)" -w "AIzaSyXXX" -U
上書き更新(-U フラグ)と削除・再登録
APIキーを更新する際は-Uフラグで上書きできます。ただし、アカウント名を変更したい場合は、一度削除してから再登録が必要です。
# 誤ったアカウント名で登録したエントリを削除security delete-generic-password -s "GEMINI_API_KEY" -a "gemini"# 正しいアカウント名で再登録security add-generic-password -s "GEMINI_API_KEY" -a "$(whoami)" -w "AIzaSyXXX" -U
Claude Codeの導入や活用方法について、個別にご相談いただけます。「どのAPIキーをどう管理すればいいか」「スキルの設計から始めたい」という段階から対応しています。
Keychainのキーをスクリプトから読み出す
登録したAPIキーをスクリプトから読み出すには、security find-generic-passwordコマンドを使います。
シェルスクリプトからの読み出し(bash/zsh)
# APIキーを読み出して変数に代入API_KEY=$(security find-generic-password -s "GEMINI_API_KEY" -a "$(whoami)" -w)# 環境変数として設定してからツールを実行export GEMINI_API_KEY=$(security find-generic-password -s "GEMINI_API_KEY" -a "$(whoami)" -w)python3 my_script.py
-wオプションを付けることで、パスワード(APIキーの値)のみをstdoutに出力します。これをコマンド置換$()で変数に代入する形が定番パターンです。
Pythonスクリプトからの読み出し(subprocess)
Claude Codeのスキル内でPythonスクリプトを使う場合は、subprocessモジュールでこのコマンドを呼び出します。
import subprocessdef get_keychain_secret(service_name: str) -> str: """macOS KeychainからAPIキーを取得する""" import os result = subprocess.run( ["security", "find-generic-password", "-s", service_name, "-a", os.getenv("USER", "riku"), "-w"], capture_output=True, text=True ) if result.returncode != 0: raise ValueError(f"Keychainに {service_name} が見つかりません。登録してください。") return result.stdout.strip()# 使用例api_key = get_keychain_secret("GEMINI_API_KEY")
このパターンは、実際に複数のClaude Codeスキル(nano-banana画像生成スキル、X APIスキルなど)で採用している実装です。
環境変数として設定してからツールを実行するパターン
外部CLIツールがAPIキーを環境変数から読み取る場合は、subprocessにenvパラメータを渡す方法が便利です。
import subprocess, os# Keychainから読み取って環境変数に渡すapi_key = get_keychain_secret("OPENAI_API_KEY")env = {**os.environ, "OPENAI_API_KEY": api_key}result = subprocess.run(["openai", "api", "completions.create", ...], env=env)
\ 業務自動化のお悩み、プロが30分で整理します /
法人向けClaude Code個別指導の無料相談はこちらClaude Code スキルでの実践パターン
実際に50個以上のClaude Codeスキルを開発した中で確立した、Keychain管理のベストプラクティスを紹介します。
(Claude Code Skillsの設計パターンの詳細はこちら →)
推奨命名規則(サービス名は ALL_CAPS、アカウント名は $USER)
| 項目 | 推奨ルール | 理由 |
|---|---|---|
| サービス名(-s) | GEMINI_API_KEY のようにALL_CAPS |
環境変数名と統一し、混乱を防ぐ |
| アカウント名(-a) | 常に $(whoami) |
スクリプト側との不一致を防ぐ |
| 複数アカウントの場合 | -a "riku_work" のようにサフィックスを付加 |
同一サービスの複数キーを区別できる |
スキル内でのKeychain読み出しテンプレート(Python版)
import subprocess, osdef get_api_key(service_name: str, account: str | None = None) -> str: """ macOS KeychainからAPIキーを読み出す Args: service_name: -s オプションに渡す値(例: "GEMINI_API_KEY") account: -a オプションに渡す値。Noneの場合は$USERを使用 Returns: APIキーの文字列 Raises: SystemExit: Keychainにキーが見つからない場合 """ if account is None: account = os.getenv("USER", os.getenv("LOGNAME", "")) result = subprocess.run( ["security", "find-generic-password", "-s", service_name, "-a", account, "-w"], capture_output=True, text=True ) if result.returncode != 0: print(f"エラー: Keychainに '{service_name}' が見つかりません。") print(f"以下のコマンドで登録してください:") print(f'security add-generic-password -s "{service_name}" -a "$(whoami)" -w "YOUR_API_KEY" -U') raise SystemExit(1) return result.stdout.strip()
macOS Keychainアクセスアプリで確認・管理する
コマンドラインが苦手な方や、登録済みのキーを確認したい場合は、Keychainアクセスアプリ(GUIツール)が便利です。
Spotlightで「キーチェーンアクセス」と検索して起動します。左サイドバーで「ログイン」を選択し、検索バーにサービス名(例: GEMINI_API_KEY)を入力すれば、登録済みのエントリが確認できます。
補足Keychainアクセスアプリからも新規エントリの追加が可能です。メニューバー → ファイル → 新規パスワード項目 から、項目名(サービス名)・アカウント名・パスワードを設定できます。
SSH経由でKeychainにアクセスする場合の注意点
Claude Codeを別のMacにSSHで接続して使う場合(例: Mac miniをサーバーとして使う場合)、Keychainへのアクセスに追加の設定が必要になることがあります。
(VSCode Remote SSHでMac miniのClaude Codeを遠隔操作する方法はこちら →)
なぜSSH経由ではKeychainにアクセスできないのか
macOSのKeychainは、セキュリティ上の理由から、ユーザーがGUIでログインしているセッションでのみ自動アンロックされます。SSHでリモートログインしたセッションは、GUIログインとは別セッションとして扱われるため、Keychainがロックされた状態のままになります。
実際の開発セッションでも、SSHで別のMacに接続してClaude Codeを操作した際に、security find-generic-passwordコマンドが次のようなエラーを返すことがありました。
security: SecKeychainSearchCopyNext: The specified item could not be found in the keychain.
security unlock-keychain でアンロックする方法
SSH接続したターミナルから、以下のコマンドでKeychainをアンロックできます。
security unlock-keychain ~/Library/Keychains/login.keychain-db
実行するとパスワードの入力が求められます。Macのログインパスワードを入力することでアンロックされ、その後はsecurity find-generic-passwordが正常に動作します。
注意
security unlock-keychainの効果は一時的なもので、次回のSSH切断・再接続後は再度アンロックが必要になります。自動化スクリプトでの利用には向いていないため、後述の代替戦略も検討してください。
SSH接続時のAPIキー管理の代替戦略
SSH経由でのKeychain利用が困難な場合、以下の代替方法を検討します。
| 方法 | 適するケース | 注意点 |
|---|---|---|
| SSH接続先のMacにKeychainを使ってコンソールから手動アンロック | 作業開始時に毎回手動操作できる場合 | ログインパスワードの入力が必要 |
環境変数ファイル(~/.zshenv)に書いてSSH経由で渡す |
セキュリティ要件が低い開発環境 | セキュリティは.envと同レベル |
.plistでlaunchd環境変数として設定 |
常時稼働のサーバー用途 | 設定が複雑だが自動化しやすい |
ローカルのMacBook上でスクリプトを動かす場合は、Keychainが最も簡単で安全です。SSH経由の利用が多い場合は、使用する環境に合わせて設計することをお勧めします。
\ AI活用の「次の一手」を一緒に考えませんか /
法人向けClaude Code個別指導の無料相談はこちらよくある質問
Q. security コマンドで登録したAPIキーは再起動後も残りますか?
はい、残ります。macOS Keychainはログインキーチェーン(login.keychain-db)に保存されるため、再起動後もsecurity find-generic-passwordでいつでも取り出せます。
Q. Keychain Access(GUIアプリ)でキーを確認・追加する方法は?
Spotlightで「キーチェーンアクセス」と検索して起動します。左サイドバーで「ログイン」を選択し、一覧から登録済みのエントリを確認できます。ダブルクリックで詳細を開き、「パスワードを表示」にチェックを入れるとAPIキーの値が確認できます(ログインパスワードの入力が必要です)。
Q. 複数のMacでAPIキーを同期するには?
現在のmacOS Keychainは基本的にデバイスローカルのものです。複数のMacでAPIキーを使う場合、それぞれのMacでsecurity add-generic-passwordコマンドを実行して個別に登録する必要があります。なお、iCloud Keychainを使えばデバイス間の同期も可能ですが、コマンドラインからの操作はやや複雑になります。
(MacBookとMac miniでClaude Code環境を同期する方法はこちら →)
Q. Keychainのキーを削除するコマンドは?
# 削除コマンドsecurity delete-generic-password -s "サービス名" -a "$(whoami)"# 例: GEMINI_API_KEYを削除security delete-generic-password -s "GEMINI_API_KEY" -a "$(whoami)"
削除に成功するとpassword has been deleted.と表示されます。
Q. 登録済みのAPIキー一覧を確認するには?
# サービス名で検索(部分一致)security find-generic-password -s "GEMINI"# 全エントリの一覧(非常に多いのでgrepで絞る)security dump-keychain | grep "svce" | grep "API"
まとめ
本記事では、macOS Keychainを使ったAPIキー管理の方法を解説しました。要点を整理します。
- .envファイルへの平文保存は、Git誤コミット・シェル履歴への露出・複数プロジェクト管理の困難さという3つのリスクがある
- macOS KeychainはAES-256-GCMで暗号化し、OSレベルのアクセス制御を提供する安全な選択肢
security add-generic-passwordで登録、security find-generic-password -wで読み出す。アカウント名(-a)は$(whoami)で統一することが重要- PythonスクリプトからはsubprocessモジュールでKeychainにアクセスできる
- SSH経由での利用時はKeychainがロックされる問題があり、
security unlock-keychainでアンロックする
今日からできることとして、まずsecurity add-generic-passwordコマンドで、最もよく使うAPIキー(OpenAI, Gemini等)をKeychainに登録してみてください。.envファイルへの依存を一つずつ減らしていくことで、セキュリティリスクを大幅に下げられます。
Claude Codeの導入・活用をサポートします
株式会社Nexaでは、Claude Codeを活用した業務自動化の個別指導・企業研修を提供しています。APIキー管理のような細かいつまずきも含め、スキル設計から実際の業務自動化まで、実践的にサポートします。「何から始めればいいかわからない」という段階からご支援いたします。





