コードを書かないSE日誌

SE歴26年。コードを書かずにClaude Codeで8体のAIエージェントチームを動かしています。AIエージェント・自動化・GTDの実験日誌。

Claude Code の PreToolUse フックで操作ログを自動保存する — 個人環境のセキュリティ強化

この記事の実施記録(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ステップで動く。

  1. stdin から Claude Code が渡す JSON ペイロードを受け取る
  2. tool_nametool_input.command を抽出する(jq がなければ python3 でフォールバック)
  3. JST の現在時刻を取得する(Windows 環境は PowerShell 経由)
  4. 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"}

フィールドは timestamptoolcommand の3つだけ。エラーが発生してもスクリプトは終了コード 0 を返す設計だ(set +e)。ログの失敗が Claude Code の動作を止めることを最優先で防ぐ。


実際のログで分かること: 2,070件のコマンド履歴が示す作業パターン

初日の42コマンドから始まった

Hooks 導入初日(2026-05-04)の1日分を集計したところ、42コマンドが記録されていた(当時の集計値。現在はローテーションにより削除済み)。上位は bashgitls。全コマンドが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で作る1人エージェントチーム エンジニア向け。writer + reviewer の2体から始めるサブエージェント設計(序章無料)

シリーズ全6冊: Vol.1 作るまでVol.2 回すまでVol.3 書き続けるまでVol.4 仕組みを渡すまでVol.5 仕事を任せるまでVol.6 1人エージェントチーム