Claude Code と Codex の会話ログを、複数の Mac から1つの Git リポジトリに自動で集める仕組みを作った

Claude Code と Codex の会話ログを、複数の Mac から1つの Git リポジトリに自動で集める仕組みを作った

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段の索引を、同期のたびに作るようにしました。

  1. 目次(catalog.md):最初に読む1ファイル。プロジェクトごとのセッション数と期間、月別の一覧へのリンク
  2. 月別の一覧(by-month/YYYY-MM.md):その月のセッションの一覧(日付・Mac・プロジェクト・最初のプロンプトの冒頭)
  3. 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か所に集めるところから始めてみるとよいと思います。

あわせて読みたい

Claude Code と Codex の会話ログを、複数の Mac から1つの Git リポジトリに自動で集める仕組みを作った

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!

この記事を書いた人

エンジニア。Claude Code / Codex / MCP / BigQuery / 自動化 / ガジェット / 3Dプリンター / スマートホーム。楽して生きたい。ゲーム / イヤホン / キーボード / プログラミング / AI

目次