• #claude-code
  • #automation
  • #windows
  • #productivity
開発

Claude Codeとの会話を自動記録する仕組み - Windows環境での実装計画

背景

Claude Codeでの会話はセッション終了とともに消えてしまう。過去の会話を検索・参照できるよう、自動的にMarkdownファイルとして保存する仕組みを作りたい。

参考にした記事では、macOS環境でLaunchAgentを使ってObsidianに同期している。これをWindows環境に適応し、mdx-playgroundプロジェクト内に保存する形で実装する。

結論

以下の構成で実現できる:

mdx-playground/
└── claude-code-sync/
    ├── watch-claude-sync.sh   # 監視スクリプト(1分ごと:ファイル更新のみ)
    ├── commit-daily.sh        # コミットスクリプト(1日1回:commit & push)
    ├── 2026年1月13日.md        # 会話ログ(日付ごと)
    └── ...
  • 監視スクリプト: 1分ごとにセッションファイルを監視し、Markdownに追記(コミットしない)
  • コミットスクリプト: 1日1回(23:59)にまとめてcommit & push
  • 常駐化: Windowsタスクスケジューラで2つのタスクを登録
  • 保存先: claude-code-sync/ ディレクトリにMarkdownファイル

実装計画

Phase 1: ディレクトリ構造の準備

mkdir -p claude-code-sync

Phase 2: 監視スクリプトの作成

claude-code-sync/watch-claude-sync.sh を作成する。

主な機能

  1. セッションファイルの監視(1分間隔)
    • ~/.claude/projects/*/ 配下の全プロジェクトのjsonlファイルを監視
    • 最終更新から60分以内のファイルを対象
  2. 会話の抽出・整形
    • jq を使ってjsonlをパース
    • type: "user"type: "assistant" のメッセージを抽出
    • システムメッセージやコマンド出力はフィルタリング
  3. 日付ごとのファイル分割
    • YYYY年M月D日.md 形式で保存
    • タイムスタンプを確認し、その日の会話のみ抽出
  4. 追記モード
    • 上書きではなく差分追記
    • 最後に処理した行番号を記録し、新しい行のみ処理

スクリプト骨格

#!/bin/bash
# Watch Claude Code sessions and sync to markdown
# コミットは別スクリプト(commit-daily.sh)で1日1回行う

SYNC_DIR="$(dirname "$0")"  # スクリプトと同じディレクトリに保存
CLAUDE_PROJECTS="/c/Users/numbe/.claude/projects"
STATE_FILE="$SYNC_DIR/.sync-state"

# 日本語日付フォーマット
get_today() {
    date +"%Y年%-m月%-d日"
}

# セッションファイルを検索(全プロジェクト)
find_sessions() {
    find "$CLAUDE_PROJECTS" -name "*.jsonl" -type f -mmin -60 \
        ! -path "*/subagents/*" 2>/dev/null
}

# jsonlから会話を抽出
extract_conversations() {
    local session_file="$1"
    local today_start=$(date -u -d "today 00:00:00 +0900" +%Y-%m-%dT%H:%M:%S 2>/dev/null)

    jq -r --arg today "$today_start" '
        select(.type == "user" or .type == "assistant") |
        select((.timestamp // "9999") >= $today) |
        # フィルタリングとフォーマット処理
        ...
    ' "$session_file"
}

# メインループ(ファイル更新のみ、コミットしない)
while true; do
    for session in $(find_sessions); do
        extract_conversations "$session"
    done

    sleep 60
done

Phase 3: コミットスクリプトの作成

claude-code-sync/commit-daily.sh を作成する。1日1回実行し、まとめてcommit & pushする。

#!/bin/bash
# Daily commit and push for Claude Code sync
# タスクスケジューラで毎日23:59に実行

SYNC_DIR="$(cd "$(dirname "$0")" && pwd)"
cd "$SYNC_DIR" || exit 1

# 今日の日付
TODAY=$(date +"%Y年%-m月%-d日")

# 変更があればコミット&プッシュ
if git status --porcelain | grep -q .; then
    git add -A
    git commit -m "Claude: ${TODAY}"
    git push origin master
    echo "Committed and pushed: ${TODAY}"
else
    echo "No changes to commit"
fi

Phase 4: フィルタリングルール

以下のメッセージは除外する:

パターン理由
<system-reminder>システムの自動挿入メッセージ
<local-command-*>ローカルコマンドの出力
<command-name>スラッシュコマンドの内部表現
<task-notification>タスク通知
tool_use / tool_resultツール実行の詳細

Phase 5: 出力フォーマット

# 2026年1月13日 Claudeとの会話

## セッション: mdx-playground (10:30)

**ユーザー**: Claude Codeとの会話を自動的に記録したい

**Claude**: はい、実現できます。以下の仕組みで...

---

## セッション: tax-assistant (14:15)

**ユーザー**: 確定申告の準備について

**Claude**: 確定申告の準備として...

Phase 6: タスクスケジューラで常駐化

2つのタスクを登録する。

タスク1: 監視スクリプト(ログイン時に起動)

$action = New-ScheduledTaskAction -Execute "C:\Program Files\Git\bin\bash.exe" `
    -Argument "-c 'C:/Users/numbe/Git_repo/mdx-playground/claude-code-sync/watch-claude-sync.sh'"

$trigger = New-ScheduledTaskTrigger -AtLogon

$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries `
    -DontStopIfGoingOnBatteries -StartWhenAvailable

Register-ScheduledTask -TaskName "ClaudeCodeSync" -Action $action `
    -Trigger $trigger -Settings $settings -RunLevel Highest

タスク2: コミットスクリプト(毎日23:59に実行)

$action = New-ScheduledTaskAction -Execute "C:\Program Files\Git\bin\bash.exe" `
    -Argument "-c 'C:/Users/numbe/Git_repo/mdx-playground/claude-code-sync/commit-daily.sh'"

$trigger = New-ScheduledTaskTrigger -Daily -At "23:59"

$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries `
    -DontStopIfGoingOnBatteries -StartWhenAvailable

Register-ScheduledTask -TaskName "ClaudeCodeSyncCommit" -Action $action `
    -Trigger $trigger -Settings $settings -RunLevel Highest

手動での起動・停止

# 監視スクリプト
Start-ScheduledTask -TaskName "ClaudeCodeSync"
Stop-ScheduledTask -TaskName "ClaudeCodeSync"
Get-ScheduledTask -TaskName "ClaudeCodeSync"

# コミットスクリプト(手動実行したい場合)
Start-ScheduledTask -TaskName "ClaudeCodeSyncCommit"

Phase 7: 動作確認

  1. 監視スクリプトを手動実行してエラーがないか確認
  2. 会話が正しく抽出されるか確認
  3. 日付フィルタリングが正しく動作するか確認
  4. コミットスクリプトを手動実行してcommit & pushを確認
  5. タスクスケジューラからの起動を確認

技術的な注意点

Windows環境での違い

macOSWindows (Git Bash)
date -v-9Hdate -d "-9 hours"
~/.claude//c/Users/numbe/.claude/
LaunchAgentタスクスケジューラ

セッションファイルの構造

{"type":"user","message":{"role":"user","content":"..."},"timestamp":"2026-01-13T01:30:00.000Z"}
{"type":"assistant","message":{"role":"assistant","content":[{"type":"text","text":"..."}]},"timestamp":"..."}
  • type: "user", "assistant", "system" など
  • message.content: ユーザー入力は文字列、Claude応答は配列
  • timestamp: UTC形式

コミット戦略

項目設定
ファイル更新1分ごと(リアルタイム)
コミット1日1回(23:59)
プッシュコミットと同時
履歴1日1コミットできれいに保つ

メリット:

  • git履歴が汚れない(1日1コミット)
  • 会話はリアルタイムで保存される
  • pushも1日1回で済む

今後の拡張案

  • プロジェクトごとのディレクトリ分け
  • 要約の自動生成
  • 検索機能の追加
  • Web UIでの閲覧

まとめ

Claude Codeのセッションファイルを監視し、会話を自動的にMarkdownとして保存する仕組みを実装する。監視は1分ごとにファイル更新のみ行い、コミット&プッシュは1日1回にまとめることで履歴をきれいに保つ。Windows環境ではタスクスケジューラとGit Bashを組み合わせて実現する。これにより、過去の会話を検索・参照でき、学んだことがナレッジベースに蓄積される。