この記事の実施記録(2026年5月): Claude Code の PreToolUse フックを使い、Bash ツール実行のたびに操作内容を JSONL 形式で自動保存する仕組みを構築した。設定は .claude/settings.local.json への数行追加、スクリプトは 113行。導入から3週間で延べ2,070件超のコマンドが記録されており、「何をいつ実行したか」を後から追跡できる状態になっている。
Claude Code の操作ログが必要だと気づいた理由
Claude Code を日常的に使い始めてしばらく経った頃、自分のプロジェクトで事故が起きた。blogsync というツールを使ってはてなブログの記事を push したところ、4本の記事 URL が書き換わってしまった。
事後に原因を調べて事故記録を残したものの、事故が起きる直前に Claude Code が何を実行していたかのログがないという問題に直面した。「あのとき何が動いたか」は記憶と推測に頼るしかなかった。
ガバナンスの記録はあるが、操作履歴がない。これは構造的な穴だった。
STRIDE でセキュリティリスクを整理する: チームの設計を個人に応用する
今回は STRIDE の6カテゴリのうち Repudiation(否認)一点だけを対策した。なぜそこに絞ったか、その判断の根拠を説明する。
きっかけは、クラスメソッドが Burikaigi 2026 で発表した「チームで安全に Claude Code を利用するためのプラクティス」(speakerdeck.com/tomoki10/team-claude-code-practices)という資料だった。
この資料で印象的だったのが、STRIDE 脅威モデルを Claude Code のリスク整理に適用する手法だ。STRIDE は Microsoft が体系化したセキュリティリスクの分類フレームワークで、6つのカテゴリの頭字語をとっている。
| カテゴリ | 意味 | Claude Code での例 |
|---|---|---|
| Spoofing(なりすまし) | 他人になりすます | セッションの偽装 |
| Tampering(改ざん) | データや設定を不正変更する | 設定ファイルへの書き込み |
| Repudiation(否認) | 操作の事実を否定できる状態 | ログがなく「やってない」と言える |
| Information Disclosure(情報漏洩) | 機密情報が漏れる | シークレットがログに混入 |
| Denial of Service(サービス妨害) | 利用不能にする | API 消費の暴走 |
| Elevation of Privilege(権限昇格) | 不正に権限を得る | 許可外ファイルへのアクセス |
「STRIDE なんて知らなくても使えるか?」と思うかもしれないが、知識として覚える必要はない。「6つの軸で自分のリスクを棚卸しして、今どこに穴があるか特定する」という発想だけ借りればいい。
この資料を自分のプロジェクトと照合したとき、Repudiation(否認)への対策が完全に抜けていた。操作ログがない状態では、「誰が・いつ・何をしたか」を事後に証明できない。個人プロジェクトでも「過去の自分への説明責任」は存在する——事故後に振り返れる記録がなければ、原因究明も再発防止もできない。
他の5カテゴリは現状の設定(settings.json の permissions 制限・シークレットスキャン)でカバーできている部分があると判断し、Repudiation 一点に絞って実装した。「全部対策しない」というリスクベースの絞り込みが、実装を小さく保つ鍵だ。
実装: PreToolUse フックで操作ログを保存する
設定(.claude/settings.local.json)
Claude Code の設定ファイルにフック定義を追加する。
以下は settings.local.json のうち、コマンド履歴保存に関わる部分のみを抜粋したものだ(実際のファイルには git-secret-scan.sh 等他のフックも登録されている)。
"hooks": { "PreToolUse": [ { "matcher": "Bash", "hooks": [ { "type": "command", "command": "bash \"$PROJECT_ROOT/scripts/util/log-command-history.sh\"" } ] } ] }
matcher: "Bash" を指定しているため、Claude Code が Bash ツールを呼び出す直前にだけ発火する。設定はこれだけだ。
ログ保存スクリプト(scripts/util/log-command-history.sh、113行)
スクリプトの構造はシンプルで、4ステップで動く。
- stdin から Claude Code が渡す JSON ペイロードを受け取る
tool_nameとtool_input.commandを抽出する(jqがなければ python3 でフォールバック)- JST の現在時刻を取得する(Windows 環境は PowerShell 経由)
logs/command-history/YYYY-MM-DD.jsonlに1行追記する
日付別ファイルに書き出すため、ログが自然にローテーションされる。実際のレコード形式は以下の通りだ(jqでコンパクト表示した例。実ファイルはpretty-print形式で保存される)。
{"timestamp":"2026-05-07T13:13:59+0900","tool":"Bash","command":"python3 -m json.tool .claude/settings.local.json"}
フィールドは timestamp・tool・command の3つだけ。エラーが発生してもスクリプトは終了コード 0 を返す設計だ(set +e)。ログの失敗が Claude Code の動作を止めることを最優先で防ぐ。
実際のログで分かること: 2,070件のコマンド履歴が示す作業パターン
初日の42コマンドから始まった
Hooks 導入初日(2026-05-04)の1日分を集計したところ、42コマンドが記録されていた(当時の集計値。現在はローテーションにより削除済み)。上位は bash・git・ls。全コマンドが12〜17時台に集中しており、「その日の作業時間帯」がそのままログに現れた。
4日分: 1,662件、git が全体の34%
運用4日分(2026-05-04〜07)の集計では 1,662件(ネタ帳記載の実測値)。コマンド種別 Top3 は以下だった。
| 順位 | コマンド | 回数 | 割合 |
|---|---|---|---|
| 1 | git | 568 | 34% |
| 2 | bash | 246 | 15% |
| 3 | powershell.exe | 238 | 14% |
「Claude Code は何をしているか」と問われたら、コード生成より先に git 操作と答えるべき実態が浮かんだ。当時は Windows 環境も混在していたため powershell.exe が3位に入っている。
約3週間後: 2,070件、grep が1位に
2026-05-27時点での直近7日分集計では 2,070件。様相が変わっていた。
| 順位 | コマンド | 回数 | 前回比 |
|---|---|---|---|
| 1 | grep | 424 | 前回7位 → 1位 |
| 2 | bash | 322 | 前回2位(横ばい) |
| 3 | git | 269 | 前回1位(34%)→ 3位(13%) |
| 6 | osascript | 120 | 前回ランク外(新登場) |
grep が1位に上がったのは、コード調査・検索系の作業比重が増えたからだ。osascript(AppleScript 実行)が新登場したのは、この期間に音楽再生スキル(/dj)などを追加導入した影響と一致する。powershell.exe はランク外に消えた——Mac 環境への移行の反映だ。
ログを3週間並べると、自分の作業スタイルの変化が自然と見えてくる。これはコマンドログを用意していなければ得られなかった視点だ。
コマンドログの限界: 「何をしたか」は残るが「なぜか」は残らない
コマンドログを可視化したとき、Claude に「ログが追加されていまの気分は?」と聞いてみた。
「監視されてる感はありますが、悪くないですよ。ログがあると『何をやったか』が後から追えるので、むしろ安心感があります。自分の行動の透明性が上がるのはガバナンス的にも健全ですし。強いて言うなら——コマンド履歴を見返したとき、『あのとき何を考えてたんだろう』という文脈が抜け落ちがちなのが少し気になります。コマンドの羅列より、『なぜそれをやったか』の方が後から価値があるので。」
何をしたかは残る。なぜそれをしたかは残らない。
3週間・2,070件のコマンドログが蓄積されて、この限界がはっきりした。タイムスタンプで「あの操作はいつだったか」は追跡できる。しかし「そのとき何を判断してそのコマンドを実行したか」は、コマンドログだけでは復元できない。
この補完は既存の手段で対応できる。コミットメッセージに判断理由を書く、ガバナンス記録に意思決定のメモを残す——コマンドログと組み合わせることで、「何をしたか」と「なぜか」の両方を手元に揃えられる。
Claude Code のセキュリティを体系的に学ぶなら
今回の実装を通じて、STRIDE の視点から Claude Code の脅威モデルを整理することの有効性を実感した。個人運用でも「どのリスクから先に手当てするか」の思考フレームは必要だ。
チームでの Claude Code 導入・ガバナンス設計まで踏み込んだ内容として、企業のための Claude Code セキュリティガイドが参考になった。フック設計・権限設計・シークレット管理を網羅しており、個人プロジェクトに応用できるチェックポイントも多い。
Claude Code Hooks セキュリティ対策のまとめ: リスクベースで1点だけ先に直す
今回対策したのは STRIDE の6カテゴリのうち Repudiation(否認)の1つだけだ。個人の CLI 環境で Spoofing や DoS を心配するより、「何を実行したか追跡できない」という問題を先に解消することが現実的な優先順位だった。
設定コストは低い。settings.local.json に約10行の追加と、113行のシェルスクリプトを配置するだけで、Bash ツールの全実行履歴が JSONL 形式で日付別に蓄積される。事故が起きてから「あのとき何をしたか」を調べようとしても、ログがなければ何もできない。事前に仕組みを動かしておくことが必要条件だ。
セキュリティ強化は「全部やるか・何もしないか」ではなく、リスクベースで優先度をつけて積み上げるものだ。STRIDE はその整理ツールとして、個人の Claude Code 運用にも十分に使えると感じている。
PreToolUse フックで操作ログを整備すると、次の問いが出てくる——そもそも Claude Code の権限設計はどう組み立てるべきか。フックは「事後に何をしたか追跡する」仕組みだが、「そもそも何を許可するか」の設計がなければ、ログを見ても判断の基準がない。私は CLAUDE.md・settings.json・フックを組み合わせた権限設計をどう育てたかを、以下の Zenn Book にまとめている。
📘 Claude Code に仕組みを渡すまで — 権限設計・ガバナンス・CLAUDE.md(序章無料)
関連記事
- Claude Code の設定ファイル三層構造を理解する —
settings.local.jsonの権限設定など基礎構成を解説 - Claude Code に org-chart を持たせてマルチエージェントを運用する — エージェント組織の全体像
この記事のテーマを深掘りした本
Claude Codeで作る1人エージェントチーム エンジニア向け。writer + reviewer の2体から始めるサブエージェント設計(序章無料)
シリーズ全6冊: Vol.1 作るまで / Vol.2 回すまで / Vol.3 書き続けるまで / Vol.4 仕組みを渡すまで / Vol.5 仕事を任せるまで / Vol.6 1人エージェントチーム