Claude Codeに作業させた証跡をEasyBlocks Syslogに集約してみた

最近、VSCode + Claude Code でドキュメントのPDF化作業を任せることが増えました。

長時間の作業を放置できて本当に便利なのですが、ある日ふと思ったんです・・・

これ、AIに何をさせたか、説明できる状態になっているのかな?

ファイル操作もコマンド実行もWebアクセスも、Claude Codeが自動でこなしてくれる。便利な反面、後から「あのとき何をしたか」を追えるようにしておかないと、業務利用としては心許ない。

そこで今回は、EasyBlocks Syslogを使ってClaude Codeの作業証跡を自動的に集約する仕組みを実際に組んでみました。

本記事ではその実装過程と、ハマったポイントについて共有します。

なぜ証跡が必要か

Claude Codeのようなコーディングエージェントは、自律的に以下を行います。

  • ファイルの作成・編集・削除
  • シェルコマンド(PowerShell等)の実行
  • Webからの情報取得
  • 外部APIとの連携

これらが自動で進むのは効率的ですが、業務で利用する場合「何を読んで」「何を作って」「何を削除したか」が後から検証できる状態にしておく必要があります。

社内ガバナンス、コンプライアンス、トラブル時の原因究明、どれをとっても証跡は必須です。

ところが、Claude Code単体ではこの「行動証跡」を外部に出す仕組みがありません。ここで EasyBlocks Syslog の出番です。

構成

構成自体はシンプルです。

[Windows端末: VSCode + Claude Code]
(1) hooks 機能で発火
      ▼
[PowerShellスクリプト]
(2) syslog形式(RFC3164)に変換してUDP/514で送信
      ▼
[EasyBlocks Syslog]
(3) 受信・蓄積・Web UIで可視化
      ▼
[運用者がブラウザで確認]

重要な気付き:Claude Codeは直接Syslogを投げない

Claude Codeにはsyslog送信機能はありません。あくまで「特定タイミングで任意のコマンドを実行できる」hooks機能があるだけ。

つまり「hooksでPowerShellスクリプトを呼び出し、そのスクリプトがsyslog形式に変換して送信する」という1ステップを挟む必要があります。

環境

  • クライアント:Windows 11 + VSCode + Claude Code 拡張
  • シェル:Windows PowerShell 5.1
  • Syslogサーバー:EasyBlocks Syslog
  • ネットワーク:クライアントから Syslog サーバへ UDP/514 が疎通可能

実行手順

STEP①:PowerShellスクリプトの作成

まず C:\claude-hooks\ フォルダを作って、その中にsyslog送信用スクリプトを置きます。

PowerShellで以下を実行してフォルダを作成。

New-Item -Path "C:\claude-hooks" -ItemType Directory

次に、メモ帳で C:\claude-hooks\Send-ClaudeSyslog.ps1 を作成し、以下の内容を貼り付けます。

# Send-ClaudeSyslog.ps1

# Claude CodeのhooksからJSON入力を受け取り、EasyBlocks Syslog (RFC3164) へUDP送信する

# ===== 設定 =====

$SyslogServer    = "192.168.X.X"   # 自社のEasyBlocks SyslogのIPに置き換え

$SyslogPort      = 514

$Facility        = 21              # local5

$DefaultSeverity = 5               # notice

# ================

try {

    # stdinからJSONを受け取る

    $jsonInput = [Console]::In.ReadToEnd()

    $hookData  = $jsonInput | ConvertFrom-Json

    $eventName = $hookData.hook_event_name

    $toolName  = $hookData.tool_name

    $sessionId = $hookData.session_id

    # tool_inputから主要パラメータを抜き出す

    $detail = switch ($toolName) {

        "Bash"       { "cmd=`"$($hookData.tool_input.command)`"" }

        "PowerShell" { "cmd=`"$($hookData.tool_input.command)`"" }

        "Write"      { "file=`"$($hookData.tool_input.file_path)`"" }

        "Edit"       { "file=`"$($hookData.tool_input.file_path)`"" }

        "Read"       { "file=`"$($hookData.tool_input.file_path)`"" }

        "WebFetch"   { "url=`"$($hookData.tool_input.url)`"" }

        "WebSearch"  { "query=`"$($hookData.tool_input.query)`"" }

        default      { "" }

    }

    # RFC3164フォーマット組み立て

    $priority = ($Facility * 8) + $DefaultSeverity

    # TIMESTAMP: "Mmm dd hh:mm:ss" (英語ロケール固定、日が1桁ならスペース埋め)

    $now       = Get-Date

    $invariant = [System.Globalization.CultureInfo]::InvariantCulture

    $month     = $now.ToString("MMM", $invariant)

    $day       = $now.Day.ToString().PadLeft(2, ' ')

    $time      = $now.ToString("HH:mm:ss")

    $timestamp = "$month $day $time"

    $hostname     = $env:COMPUTERNAME

    $user         = $env:USERNAME

    $tag          = "claude-code"

    $sessionShort = if ($sessionId) { $sessionId.Substring(0, [Math]::Min(8, $sessionId.Length)) } else { "-" }

    $message = "<$priority>$timestamp $hostname ${tag}: user=$user session=$sessionShort event=$eventName tool=$toolName $detail"

    # UDP送信

    $udp   = New-Object System.Net.Sockets.UdpClient

    $bytes = [System.Text.Encoding]::UTF8.GetBytes($message)

    [void]$udp.Send($bytes, $bytes.Length, $SyslogServer, $SyslogPort)

    $udp.Close()

    exit 0

}

catch {

    # hook失敗でClaude Codeを止めないため、stderrに出して0で抜ける

    [Console]::Error.WriteLine("Syslog send failed: $_")

    exit 0

}

ポイントを少し解説します。

stdinからJSON受信:Claude CodeのhooksはJSON形式で情報を渡してきます。tool_name でどのツールが使われたか、tool_input でその引数が分かります

RFC3164フォーマット:EasyBlocks SyslogはBSD-syslog(RFC3164)とIETF-syslog(RFC5424)の両方に対応していますが、今回はシンプルな前者を採用。

タイムスタンプは英語ロケール固定:日本語ロケールのWindowsでは Get-Date -Format “MMM” が「11月」と返してしまうので、InvariantCulture を明示して英語表記を強制しています。ここ地味だけど重要です。

失敗してもexit 0:syslog送信失敗でClaude Codeの動作を止めないため

STEP②:PowerShellの実行ポリシー確認

PowerShellは初期状態だとスクリプト実行が禁止されています。確認してみましょう。

Get-ExecutionPolicy

Restricted だった場合は以下で許可します。

Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned

RemoteSigned Unrestricted Bypass のいずれかなら、既に実行可能なのでスキップでOK。

STEP③:スクリプト単体テスト

Claude Codeに組み込む前に、スクリプト単体で動作確認します。PowerShellで以下を実行します。

'{"hook_event_name":"PostToolUse","tool_name":"Bash","session_id":"test1234","tool_input":{"command":"dir"}}' | powershell -File C:\claude-hooks\Send-ClaudeSyslog.ps1

擬似的にClaude Codeから来るJSONをスクリプトに流し込んで、Syslogサーバーへ送信させるテストです。

EasyBlocks SyslogのWeb UIを開いて、テストログが届いていることを確認します。

このときFacilityが [ local5 ]、Priorityが [ notice ]、プログラム名が [ claude-code ] として正しく分類されていることもポイントです。EasyBlocks Syslog側でフィルタや色分けが効きます。

STEP④:Claude Codeの設定ファイル(settings.json)を編集

Claude Codeに「ツールを使ったら自動でこのスクリプトを呼ぶ」と教える設定を書きます。

ファイルパス:C:\Users\<ユーザー名>\.claude\settings.json

すでに既存の設定がある場合は、その内容を活かしつつ “hooks” ブロックを追加します。ゼロから書くなら以下のような内容になります。

{

  "hooks": {

    "PostToolUse": [

      {

        "matcher": "*",

        "hooks": [

          {

            "type": "command",

            "shell": "powershell",

            "command": "C:\\claude-hooks\\Send-ClaudeSyslog.ps1"

          }

        ]

      }

    ],

    "UserPromptSubmit": [

      {

        "hooks": [

          {

            "type": "command",

            "shell": "powershell",

            "command": "C:\\claude-hooks\\Send-ClaudeSyslog.ps1"

          }

        ]

      }

    ],

    "SessionStart": [

      {

        "hooks": [

          {

            "type": "command",

            "shell": "powershell",

            "command": "C:\\claude-hooks\\Send-ClaudeSyslog.ps1"

          }

        ]

      }

    ]

  }

}

各イベントの意味は以下のとおりです。

イベント 発火タイミング
SessionStart Claude Codeの起動・再開時
UserPromptSubmit ユーザーがチャットでプロンプトを送信したとき
PostToolUse ツール(ファイル操作、コマンド実行など)が完了したとき

PostToolUse の matcher は最初 “Bash|Write|Edit|…” のように個別指定にしていたのですが、後述する理由で最終的に “*”(全マッチ)にしました。

重要:保存時の文字コードはUTF-8(BOMなし)にする

メモ帳で編集する場合、必ず「名前を付けて保存」から文字コードを 「UTF-8」 に明示的に指定してください。普通の Ctrl+S だと環境によって ShiftJIS で保存されてしまい、Claude Codeが「Invalid or malformed JSON」エラーを出すことがあります。

動作確認

VSCodeを完全に終了してから再起動し、Claude Codeを開きます(設定は起動時に読み込まれます)。

ログの見え方

Claude Codeを起動すると SessionStart のログが、チャットに何か送信すると UserPromptSubmit のログが、ツールが実行されると PostToolUse のログが、それぞれEasyBlocks Syslogに自動で送られます。

実際に「テストファイルを作って削除して」と指示してみたときのログがこちら。

作成→削除の流れが完全に追跡できています。しかもどのファイルを、どんなコマンドで削除したかまで証拠として残ります。

session= でフィルタすれば、1つの作業セッション全体の足跡を一覧できます。

ハマったポイント

検証中にいくつかつまずいたので、同じ道を歩む方の参考になればと思い、共有しておきます。

ハマりポイント①:WindowsのClaude CodeはBashではなくPowerShellツールを使う

公式ドキュメントを見ると、シェル実行ツールは Bash という名前で紹介されています。なので最初は matcher を “Bash|Write|Edit|…” と書いていました。

ところが実際にWindowsで使ってみると、シェルコマンドのログがほとんど飛んでこない。デバッグ用に matcher を “*”(全マッチ)に変えて流してみたところ判明したのが、Windows版のClaude Codeは Bash ではなく PowerShell というツールを使うということ。

これは公式ドキュメントには明示的に書かれておらず、実機で動かさないと気付けない部分でした。matcher で個別指定するなら “Bash|PowerShell|Write|Edit|…” のようにPowerShellも含める必要があります。

ただ実用上は、何が来るか分からないのでむしろ “*” で全マッチさせて全部記録するのがおすすめです。証跡として網羅性が高いほうがいいですから。

ハマりポイント②:settings.jsonのエンコーディング問題

すでに permissions が設定された状態の settings.json に hooks を追記したところ、メモ帳の保存時にShiftJISで保存されてしまい、Claude Codeが「Invalid or malformed JSON」エラーで全部の設定を読まなくなりました。

解決策は「名前を付けて保存」で文字コードを「UTF-8」(BOMなし)に明示すること。

普段あまり意識しないところですが、メモ帳の保存ダイアログには文字コード選択欄があります。日本語を含むJSONを扱うときは必ず確認しましょう。

業務効率と監査証跡の両立

本記事のテーマには、もうひとつ大事な側面があります。

settings.json の permissions ブロックで「特定のコマンドは確認なしで自動許可」を設定すると、PDF化のような長時間作業を放置で流せます。具体的には以下の通りです。

{

  "permissions": {

    "deny": [

      "Write(C:/Windows/**)",

      "PowerShell(*Format-Volume*)",

      "PowerShell(*diskpart*)"

    ],

    "allow": [

      "Read",

      "Edit",

      "Write",

      "PowerShell(pip install python-docx -q)",

      "PowerShell(python -m pip install python-docx -q)"

    ]

  },

  "hooks": {

    "...": "..."

  }

}

このように permissions と hooks は共存できます。

つまり、

  • deny ルールでシステム破壊系コマンドは確実にブロック
  • allow ルールで日常作業の確認プロンプトをスキップ(効率化)
  • hooksで全行動を Syslog に自動記録(証跡)

「効率」と「ガバナンス」を同時に確保できる、というのがこの構成の本質的な価値です。

今後の展望

EasyBlocks Syslog の活用範囲は、まだまだ広がります。

EasyBlocks Syslogでは複数人のClaude Code利用ログを集約・保存でき、これからAIエージェントを業務で本格利用する組織にとって、AIの行動証跡を専用のSyslog基盤に集約するという発想は、シンプルだけど効果的です。

まとめ

  • Claude Codeは hooks 機能で任意のタイミングに任意のコマンドを呼べる
  • Windows + PowerShell で簡単にsyslog送信スクリプトが書ける
  • EasyBlocks Syslog で受け取り、可視化・蓄積・検索ができる
  • permissions と hooks を組み合わせれば、業務効率と監査証跡を両立できる
  • 「AIに任せた作業の説明責任」を、シンプルな仕組みで担保できる

VSCode + Claude Code で生産性は確実に上がっています。

だからこそ、その活動を見える化しておくことが、これからのAI時代における働き方のスタンダードになるのではないでしょうか。

AIの行動証跡を手軽に集約・管理したいとお考えの方は、ぜひEasyBlocks Syslogをご検討ください。

EasyBlocks Syslogについてもっと知りたい方へ
ログ管理・導入のご相談はお気軽にどうぞ

EasyBlocks Syslogは、ネットワーク機器や各種サーバーのログを専用アプライアンスで手軽に一元集約できる製品です。製品選定・見積もり・技術的なご質問など、担当者が個別にご対応します。

(最後に、本記事のソースコードおよび設定ファイルはサンプルであり、動作を保証するものではありません。ご自身の環境に合わせてご確認のうえご利用ください。)

五十嵐正伸

1981年に爆誕。生まれも育ちも千葉県です。
むかしはバイク(ホンダCB400SS)やブラックバス釣りが趣味でしたが、今は習い事に励む娘の応援団です。
社会人生活では、ずっと"技術の人"という立ち位置で、2010年にぷらっとホームに来ても、変わらず技術の人をやっています。
営業に同行してお客さんと話すことも多いので、ユーザーの声をブログを通して届けられたらいいな、と思ってます。

EasyBlocks
シェアする
ぷらっとブログ
タイトルとURLをコピーしました