
AIに毎日の活動日記を書いてもらう仕組みを作った
「昨日なにやったっけ?」
日報を書くとき、週次報告をまとめるとき、確定申告の作業時間を振り返るとき——この問いに正確に答えるのは意外と難しいものです。
複数のプロジェクトを並行して進めていると、1日の中で何を触ったかの記憶はどんどん曖昧になります。gitのコミットログを漁ればある程度はわかるけれど、コードを書かなかった調査や設計の時間、AIとの対話で解決した問題は残りません。
そこで、AIに毎日の活動日記を書いてもらう仕組みを作りました。最初はCursorに手動で依頼する形でしたが、最終的にはCRONとシェルスクリプトで完全自動化するところまで辿り着いたので、その全体像をまとめます。
アイデア:ログはすでに揃っている
ふと気づいたのは、「日記に必要な情報は、実はもう手元にある」ということでした。
- gitログ: 各プロジェクトで何をコミットしたか
- ファイル更新日時: git管理外の変更も含めて何を触ったか
- Cursor agent-transcripts: AIとの会話ログ(コードを書かなかった調査作業も含む)
- Claude Codeのセッション履歴: 別のAIエージェントでの作業内容
- Codexのセッションログ: さらに別のAIエージェントでの作業内容
これらをAIに読み取らせて要約させれば、それだけで「今日やったこと」の日記になるのでは?
仕組みの全体像
構築した仕組みの全体像です。
┌─────────────────────────────────────────────┐
│ Data Sources │
├─────────────────────────────────────────────┤
│ git log (各プロジェクト) │
│ File timestamps (find + stat) │
│ Cursor agent-transcripts │
│ Claude Code sessions-index.json │
│ Codex sessions (YYYY/MM/DD/*.jsonl) │
│ メモリポジトリ │
└──────────────────┬──────────────────────────┘
│
▼ collect.sh(データ収集)
│
▼
┌─────────────────┐
│ Claude CLI │
│ (非対話モード) │
│ 要約・整形 │
└────────┬────────┘
│
▼ generate-diary.sh(生成・保存)
│
▼
┌─────────────────┐
│ diary/ │
│ 2026/ │
│ 2026-02-10.md │ → git commit & push
└─────────────────┘
▲
│
CRON (毎朝 6:00)
最初はCursorを開いて「昨日の日記を書いて」と手動で依頼していましたが、シェルスクリプトに落とし込んでCRONで自動実行するようにしたことで、朝起きたら日記ができあがっている状態になりました。
情報源 1: gitログ(主要ソース)
最も信頼できる情報源はgitのコミットログです。開発ディレクトリ配下にある各リポジトリのログを日付指定で取得します。
# 各プロジェクトディレクトリで実行
git log --after="2026-02-10 00:00:00" \
--before="2026-02-11 06:00:00" \
--format="%ai %h %s" --all深夜作業を考慮して、翌日06:00までを対象にしているのがポイントです。--allで全ブランチを対象にすることで、feature branchでの作業も漏れなく拾えます。
情報源 2: ファイル更新日時(補助ソース)
gitにコミットしていない変更や、git管理外のファイルを検出するための補助ソースです。
find ~/srv/projects -maxdepth 3 \
\( -name "*.md" -o -name "*.js" -o -name "*.ts" \
-o -name "*.py" -o -name "*.html" -o -name "*.css" \) \
-not -path "*/.git/*" -not -path "*/node_modules/*" \
-not -path "*/.next/*" \
| xargs stat -f "%m %N" \
| awk '$1 >= START_TIMESTAMP && $1 < END_TIMESTAMP' \
| sort -rngitで漏れたものを補完する役割ですが、node_modulesや.nextなどのビルド成果物は除外しています。
情報源 3: Cursor agent-transcripts(AI会話ログ)
ここがこの仕組みの真骨頂です。
Cursorの各ワークスペースでのAIとの会話は、agent-transcriptsとしてローカルに保存されています。
~/.cursor/projects/{ワークスペースID}/agent-transcripts/{セッションUUID}.txt
ワークスペースIDはパスの-区切り変換になっています。例えば:
Users-sakata-srv-projects-my-app
→ ~/srv/projects/my-app
なぜAI会話ログが重要か
gitログにはコードを変更した記録しか残りません。しかし実際の開発作業には、以下のような「コードに残らない作業」が大量にあります。
- ライブラリの調査・比較検討
- エラーの原因調査
- 設計方針の検討
- コードレビュー
- ドキュメントの読み込み
これらの作業はすべてAIとの対話ログに残っています。トランスクリプトの冒頭50〜100行を読めば、「何を目的にAIと会話したか」が把握できます。
収集方法
# 指定日に更新された agent-transcripts を一覧表示
for dir in ~/.cursor/projects/*/agent-transcripts/; do
proj=$(echo "$dir" | sed 's|.*/projects/||' \
| sed 's|/agent-transcripts/||')
find "$dir" -type f -name "*.txt" 2>/dev/null \
| while read f; do
mod=$(stat -f "%m" "$f" 2>/dev/null)
if [ -n "$mod" ] && \
[ "$mod" -ge $START_TS ] && \
[ "$mod" -lt $END_TS ]; then
size=$(wc -c < "$f" | tr -d ' ')
echo "$proj: $(basename $f) (${size}B)"
fi
done
done情報源 4: Claude Codeのセッション履歴
Claude Codeを使った作業も記録に含めます。Claude Codeは特に便利な構造でログを保存しています。
| ファイル | 内容 |
|---|---|
~/.claude/history.jsonl | 全コマンド履歴(タイムスタンプ付き) |
~/.claude/projects/{ID}/sessions-index.json | セッション一覧と自動要約 |
sessions-index.jsonのsummaryフィールドが特に有用です。Claude Code自身がセッション単位で「何をしたか」を要約してくれているため、要約の要約という効率的な情報収集が可能です。
情報源 5: Codexのセッションログ
OpenAI Codex CLIの履歴も情報源に加えます。Codexは日付ディレクトリで整理されているため、対象日のフォルダを直接参照できるのが便利です。
~/.codex/sessions/YYYY/MM/DD/*.jsonl
出力フォーマット
生成される日記ファイルは以下のような形式です。
# 2026-02-10(火)活動日記
## プロジェクトA(Webアプリケーション)
バックエンドの不具合修正を2件実施。
- **チケット-001**: トランザクション分離レベルの変更
- 対象: 6ファイル
- **チケット-002**: 更新履歴の表示不具合を修正
- テストコード300行を新規作成
## プロジェクトB(個人開発)
Next.jsプロジェクトを新規作成し、本番デプロイ可能な状態まで構築。
- **プロジェクト初期化**: 67ファイルを一気に実装
- **SEO対策**: robots.ts / sitemap.tsの追加
## メモ・ドキュメント整理
- 案件メモの整理・再構成
- コマンド集に追記プロジェクト単位でセクションが分かれ、それぞれに概要と箇条書きの詳細がつきます。これだけで「この日は何をどれだけやったか」が一目でわかります。
シェルスクリプトで自動化
手動でCursorに依頼するのも悪くないのですが、毎朝やるのは少し面倒です。そこで2つのシェルスクリプトを作成し、CRONで完全自動化しました。
スクリプト構成
diary/scripts/
├── collect.sh # データ収集(全ソースから情報を集める)
├── generate-diary.sh # 日記生成(収集 → AI要約 → 保存 → commit & push)
└── generate-diary.log # 実行ログ
collect.sh: データ収集スクリプト
全情報源から指定日のデータを収集し、標準出力にテキストとして出力するスクリプトです。
#!/bin/zsh
# 使い方:
# ./collect.sh # 昨日のデータを収集
# ./collect.sh 2026-02-10 # 指定日のデータを収集
set -euo pipefail
# 日付計算(Python3で安定動作)
eval $(python3 -c "
from datetime import datetime, timedelta
import sys
target = sys.argv[1] if len(sys.argv) > 1 else \
(datetime.now() - timedelta(days=1)).strftime('%Y-%m-%d')
dt = datetime.strptime(target, '%Y-%m-%d')
next_dt = dt + timedelta(days=1)
start_ts = int(dt.timestamp())
# 深夜作業を考慮し、翌日06:00まで
end_ts = int(datetime.strptime(
f'{next_dt:%Y-%m-%d} 06:00:00', '%Y-%m-%d %H:%M:%S'
).timestamp())
print(f'TARGET_DATE={target}')
print(f'NEXT_DATE={next_dt:%Y-%m-%d}')
print(f'START_TS={start_ts}')
print(f'END_TS={end_ts}')
print(f'START_TS_MS={start_ts * 1000}')
print(f'END_TS_MS={end_ts * 1000}')
" "${1:-}")このスクリプトは以下の順でデータを収集します。
- Cursor agent-transcripts: トランスクリプトの冒頭80行を読み取り
- Claude Code:
history.jsonlとセッション要約を抽出 - Codex: 日付ディレクトリのセッション一覧とコマンド履歴
- gitログ: 全リポジトリのコミット内容と変更ファイル統計
- メモリポジトリ: git管理されたメモの変更内容
- ファイル更新日時: git管理外の変更を補完(上位50件)
generate-diary.sh: 日記生成スクリプト
collect.shの出力をClaude Code CLI(非対話モード)に渡して日記を生成し、保存・コミット・プッシュまで行うスクリプトです。
#!/bin/zsh
# 使い方:
# ./generate-diary.sh # 昨日の日記を生成
# ./generate-diary.sh 2026-02-10 # 指定日の日記を生成
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
DIARY_DIR="$(dirname "$SCRIPT_DIR")"
COLLECT_SCRIPT="$SCRIPT_DIR/collect.sh"
# 日付処理
TARGET_DATE="${1:-$(python3 -c "
from datetime import datetime, timedelta
print((datetime.now() - timedelta(days=1)).strftime('%Y-%m-%d'))
")}"
TARGET_YEAR=$(echo "$TARGET_DATE" | cut -d- -f1)
OUTPUT_FILE="$DIARY_DIR/$TARGET_YEAR/${TARGET_DATE}.md"
# 既に存在する場合はスキップ
if [[ -f "$OUTPUT_FILE" ]]; then
echo "既に存在します: $OUTPUT_FILE(スキップ)"
exit 0
fi
# 1. データ収集
COLLECTED_DATA=$("$COLLECT_SCRIPT" "$TARGET_DATE" 2>&1)
# 活動データがなければスキップ
SECTION_COUNT=$(echo "$COLLECTED_DATA" | grep -c "^### " || true)
if [[ "$SECTION_COUNT" -eq 0 ]]; then
echo "活動データなし。スキップします。"
exit 0
fi
# 2. Claude Code CLI で日記を生成
mkdir -p "$DIARY_DIR/$TARGET_YEAR"
DIARY_CONTENT=$(cat <<PROMPT_EOF | claude -p --no-session-persistence
以下は ${TARGET_DATE} の開発活動の収集データです。
活動日記のMarkdownを生成してください。
## 出力ルール
- 最初の行は「# ${TARGET_DATE}(曜日)活動日記」
- プロジェクトごとに「## プロジェクト名」で分ける
- 各プロジェクトの冒頭に概要を1行で記述
- private/ 内の変更はファイル名と「更新」のみ
- 認証情報・パスワード等は絶対に記載しない
## 収集データ
${COLLECTED_DATA}
PROMPT_EOF
)
# 3. 保存
echo "$DIARY_CONTENT" > "$OUTPUT_FILE"
# 4. git commit & push
cd "$DIARY_DIR"
git add -A
git commit -m "feat: ${TARGET_DATE} の活動日記を自動生成"
git push origin masterポイントは以下の通りです。
- 既存ファイルのスキップ: 同じ日の日記が既に存在する場合は何もしない
- 活動データの有無チェック: 休日など活動がない日は生成をスキップ
claude -p(パイプモード): Claude Code CLIの非対話モードで、標準入力からプロンプトを受け取り、結果を標準出力に返す- 自動コミット&プッシュ: 生成した日記をgitリポジトリに即座に反映
CRONで毎朝自動実行
最後に、これをCRONに登録して完全自動化します。
0 6 * * * PATH=~/.local/bin:/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin \
HOME=/Users/sakata \
~/srv/projects/diary/scripts/generate-diary.sh \
>> ~/srv/projects/diary/scripts/generate-diary.log 2>&1毎朝6:00に前日の活動日記を自動生成し、gitにコミット&プッシュ。朝起きたら日記ができあがっているという仕組みが完成しました。
CRONの注意点として、PATHとHOMEを明示的に設定しています。CRONのデフォルト環境ではclaudeコマンドのパスが通っていないためです。
手動実行も可能
もちろん、手動でも実行できます。
# 昨日の日記を生成
~/srv/projects/diary/scripts/generate-diary.sh
# 指定日の日記を生成
~/srv/projects/diary/scripts/generate-diary.sh 2026-02-10
# データ収集のみ(デバッグ用)
~/srv/projects/diary/scripts/collect.sh 2026-02-10過去の日付を指定すれば、遡って日記を生成することも可能です。
運用ルール
実運用で気をつけているポイントをいくつか。
1. プライバシーの保護
- private/ 内の変更はファイル名と「更新」のみ記載し、内容は書かない
- 認証情報・パスワード等は絶対に記載しない
AI会話ログにはSSH鍵やAPIキーが含まれることもあるため、これはAGENTS.mdにルールとして明記しています。
2. 年ディレクトリ構成
diary/
AGENTS.md
scripts/
collect.sh
generate-diary.sh
2026/
2026-02-10.md
2026-02-11.md
...
ファイルが増えても見通しが悪くならないよう、年ごとにディレクトリを分けています。
3. 深夜作業の考慮
gitログの取得範囲を翌日06:00までにしているのは、深夜を跨いで作業することがあるためです。深夜2時のコミットは「その日の作業」として記録されます。
4. 手動修正OK
自動生成された日記は手動で修正しても問題ありません。次回の自動実行では既存ファイルをスキップするため、修正内容が上書きされることはありません。
実際に運用してみた感想
よかったこと
- 完全に放置でOK: CRONで自動化したので、意識しなくても日記が蓄積される
- 記憶の補完: 「あ、この調査もしてたんだった」と、自分でも忘れていた作業が記録される
- AIとの対話も記録に残る: コードに残らない調査・設計作業が可視化される
- プロジェクト横断の全体像: 1日の中で複数プロジェクトを行き来した全体像が把握できる
- 休日は自動スキップ: 活動データがなければ日記を生成しないので、無駄なファイルが増えない
改善したい点
- トランスクリプトが大きい(数MB)場合、冒頭だけでは全容を掴みにくいことがある
- プロジェクト名の自動解決(ワークスペースID → プロジェクト名)がたまに曖昧になる
- Claude CLIのトークン制限により、活動が多い日は一部が省略されることがある
今後の展望:メールやチャットも加えたい
現在の情報源は「開発活動」に偏っています。実際の1日には、開発以外にも多くの活動があります。
| 追加したい情報源 | 把握できること |
|---|---|
| メール | クライアントとのやり取り、依頼事項 |
| Slack / Chatwork | チーム内のコミュニケーション、決定事項 |
| カレンダー | ミーティング、打ち合わせの内容 |
| ブラウザ履歴 | 調査・リサーチの内容 |
メールやチャットを追加すれば、開発作業だけでなく、コミュニケーションや意思決定の記録も含めた完全な活動日記が自動生成できるようになるはずです。
ただし、これらは開発ログ以上にプライバシーへの配慮が必要です。どの情報をどこまで記録するか、慎重に設計してから進めるつもりです。
技術的なポイント
この仕組みが成立する背景には、いくつかの前提があります。
AIエージェントがローカルにログを残してくれる
Cursor、Claude Code、Codexはいずれもローカルファイルシステムに会話ログを保存しています。これがなければ成り立たない仕組みです。
| ツール | ログの場所 | 形式 |
|---|---|---|
| Cursor | ~/.cursor/projects/*/agent-transcripts/ | テキスト |
| Claude Code | ~/.claude/projects/*/sessions-index.json | JSON |
| Codex | ~/.codex/sessions/YYYY/MM/DD/ | JSONL |
AGENTS.mdでAIに手順を教える
プロジェクトルートにAGENTS.mdを置くことで、AIがこのプロジェクトをどう扱うべきかのルールを定義しています。日記プロジェクトのAGENTS.mdには、データ収集方法・フォーマット・プライバシールールなどが記載されており、AIはこれに従って日記を生成します。
Claude Code CLIの非対話モード
claude -p(パイプモード)を使うことで、シェルスクリプトからClaude Code CLIを呼び出してテキスト処理ができます。これがCRON自動化の鍵でした。
# 標準入力からプロンプトを渡し、結果を変数に格納
RESULT=$(echo "要約してください: $DATA" | claude -p)git管理で日記自体もバージョン管理
日記ファイルはgitリポジトリで管理しているため、AI が生成した内容を後から手動で修正しても、変更履歴が残ります。
まとめ
| 項目 | 内容 |
|---|---|
| 目的 | 日々の活動記録の自動生成 |
| 情報源 | git、ファイル更新日時、Cursor/Claude/Codexのログ |
| 自動化 | collect.sh + generate-diary.sh + CRON(毎朝6:00) |
| AI | Claude Code CLI(claude -pで非対話モード) |
| 出力形式 | Markdown(プロジェクト単位で整理) |
| 今後の展望 | メール、チャット、カレンダーの追加 |
「ログはすでにそこにある。あとはAIにまとめてもらうだけ。」
最初はCursorに手動で依頼していましたが、シェルスクリプトに落とし込んでCRONで回すようにしたことで、完全に意識しなくても日記が蓄積される仕組みが完成しました。
しばらくこの運用で回してみて、メールやチャットの追加など、改善点が見つかったらまた記事にしたいと思います。