Claude Code や Codex で作業していると、会話のログがどんどんたまっていきます。設計の相談、ハマったエラーの直し方、決めたことの理由など、あとから読み返すとかなり役に立つ記録です。
ただ、このログは Mac ごとの ~/.claude/ や ~/.codex/ の中にしかありません。iMac と MacBook Air の両方で使っていると、「あの作業、どっちの Mac でやったっけ?」となりがちでした。
そこで、複数の Mac の会話ログを、1つの private な GitHub リポジトリに自動で集める仕組みを作りました。探すのは、全部が集まっている母艦の iMac でやっています。
欲しかったのは、次の2つです。
- いつ何をしたかを、いつでも探せる
- あとからブログのネタとして使える(どんな作業をしてきたかを、あとで眺められる)
この記事でわかること
- 複数の Mac から1つのリポジトリに push しても衝突しない、フォルダの分け方
- 全文検索をする前に、目的のセッションまで絞り込める索引の作り方
- launchd で1時間ごとに同期するときの工夫
- 集めたセッションを、Gemini で毎日要約する使い方
何を集めているか
Claude Code は ~/.claude/ の下に、Codex は ~/.codex/ の下に、いろいろなデータを置いています。そのうち、残しておきたいものを選びました。
| 対象 | 中身 |
|---|---|
projects/<フォルダ名>/*.jsonl |
セッションの会話ログ本体 |
projects/<フォルダ名>/<セッションID>/ |
ツールの実行結果など、セッションに付いてくるデータ |
projects/<フォルダ名>/memory/ |
プロジェクトごとのメモリ |
history.jsonl |
入力したプロンプトの履歴 |
~/.codex/sessions/ の rollout-*.jsonl |
Codex のセッションの会話ログ |
~/.codex/ の session_index.jsonl・history.jsonl |
Codex のセッションの一覧と、入力の履歴 |
キャッシュのように、作り直せて大きくなるだけのものは対象から外しています。
衝突しないように「まとめるもの」と「Mac ごとに分けるもの」を分ける
複数の Mac が同じリポジトリに push するので、同じファイルを2台が書き換えないことが大前提です。
- セッションのログは、全部の Mac の分を1か所にまとめる:ファイル名はセッションごとの ID で、1台の Mac でしか作られず、追記もその Mac でしかされません。なので、全部の Mac が同じフォルダに置いても、ファイル同士はぶつかりません。どの Mac のセッションかは、索引に書いておきます
- 同じ名前のファイルを各 Mac が持っているものは、Mac ごとに分ける:
history.jsonlやメモリは、どの Mac にも同じ名前であって、中身が違います。まとめると上書きし合ってしまうので、Mac ごとのフォルダに分けました
data/
├── projects/<プロジェクト名>/<セッションID>.jsonl ← 全部の Mac の分をまとめる
└── hosts/<Mac の名前>/history.jsonl, memory/ ... ← Mac ごとに分ける
プロジェクト名は、起動したフォルダの名前にしました。 Claude Code は、起動したフォルダのパスから -Users-xxx-...-lifelog のような名前を作って、ログをそこに置きます。Mac ごとにリポジトリを置いた場所が違うと、同じプロジェクトでもこの名前が変わってしまいます。そこで、末尾のフォルダ名(この例なら lifelog)だけを使うことにしました。どの Mac のどこに置いていても、同じフォルダに集まります。Codex のセッションも、ログに残っている作業フォルダの名前で、同じプロジェクトのフォルダに入れています。ファイル名が rollout- で始まるので、Claude Code のものと見分けられます。
ログはそのまま上書きでコピーし、消しません。 セッションのログは、追記していくファイルです。なので、rsync で上書きコピーするだけで、追記に追いつけます。一方で、--delete は付けていません。Mac の側で消えたセッションも、リポジトリには残しておきたいからです。
ログは Git LFS に入れません。 LFS は追記でもファイル全体を送り直すので、追記していくログとは相性がよくありません。それに、LFS に入れると grep やエディタで直接読めなくなります。代わりに、45MB を超えるファイルがあれば、同期のときに警告を出すようにしました。GitHub の 100MB の制限に当たる前に気づくためです。
全文検索をする前に絞り込める索引
セッションが増えてくると、毎回すべてのログを全文検索するのは重くなります。そこで、軽いものから順に絞り込める3段の索引を、同期のたびに作るようにしました。
- 目次(
catalog.md):最初に読む1ファイル。プロジェクトごとのセッション数と期間、月別の一覧へのリンク - 月別の一覧(
by-month/YYYY-MM.md):その月のセッションの一覧(日付・Mac・プロジェクト・最初のプロンプトの冒頭) - 1行1セッションの JSON(
sessions.jsonl):プログラムから読むためのデータ
探すときは、目次を見る → 月別の一覧か JSON を grep する → 見つけたログの必要なところだけを読む、という順番です。Claude Code に探してもらうときも、この順番でたどるように README に書いておきました。「先月どんな作業をしていたか」を見るなら、月別の一覧を開くだけで済みます。
毎日、Gemini で1セッションずつ要約する
ログをそのまま読み返すのは大変なので、集めたセッションを1つずつ要約しています。母艦の iMac で毎日1回、Vertex AI の Gemini(gemini-2.5-flash-lite)に会話の部分を渡して、次の形の短い要約を作ります。
- 目的(何をしようとしたか)
- やったこと
- 決定と理由
- 未解決・次にやること
要約はセッションごとに1ファイルで、同じリポジトリに入れています。すでに要約があって、元のログのほうが古ければ作り直さないので、毎日の分は新しいセッションだけで済みます。
要約を新しい順に眺めると、どんな作業をしてきたかがすぐにわかります。記事にできそうな作業を探すのにも使っていて、ブログのネタ出しにも役立っています。
launchd で1時間ごとに同期する
定期実行には、cron ではなく launchd を使っています。1時間ごとと、ログインしたときに同期が走ります。スリープしている間は動きませんが、起きたあとの次の回で追いつきます。
1回の同期でやることは、「pull → ログを集める → 索引を作る → commit → push」だけです。
- 二重に動かないようにする:同期の最初にロックを取ります。2時間以上残っている古いロックは、前の回が途中で落ちた残りとみなして、取り直します
- 秘密情報に気づけるようにする:会話ログには、うっかり貼ったトークンなどが混ざることがあります。リポジトリは private にしたうえで、同期のときに代表的な形(API キー、アクセストークン、秘密鍵など)を探して、見つかったら警告を出します。push は止めません。アーカイブとして欠けないことを優先して、外に出す前に気づいてマスクする使い方にしています
まとめ
- 複数の Mac から1つのリポジトリに集めるなら、「まとめるもの」と「Mac ごとに分けるもの」を分けると衝突しない
- 追記していくログは、rsync で上書きコピーして Git にそのまま入れるので足りる。LFS は使わない
- 件数が増える前提で、全文検索の前に絞り込める索引を作っておく
- 定期実行は、二重に動かないことと、秘密情報に気づけることを先に考えておく
- セッションを毎日要約しておくと、あとから探すときにも、ブログのネタを探すときにも役に立つ
Claude Code や Codex の会話ログは、放っておくと Mac ごとに散らばってしまいます。複数の Mac で使っている人は、まず1か所に集めるところから始めてみるとよいと思います。
あわせて読みたい
