はじめに
Claude Code はセッションごとにまっさらなコンテキストから始まります。
そのため筆者は、個人開発の育児記録アプリで PROGRESS.md という引き継ぎメモを置き、「セッション開始時にまず読む・終わったら更新する」運用をしていました。
ところが3か月後、このファイルは 2.6KB → 約110KB に膨らみ、同じ見出しが2回出てくる・「前の記載は誤り」という訂正が何か所もある状態になっていました。
この記事では、膨らんだ原因と、PROGRESS.md / BACKLOG.md / auto memory の3層に役割を分けて約6KBに戻した方法を紹介します。
Claude Code で数週間以上続くプロジェクトを回している方に向けた内容です。
TL;DR
- 引き継ぎメモは「追記」で運用すると必ず膨らむ。「上書き」して古い内容を消すファイルとして扱う
- 情報は寿命で分ける。今だけの情報 → PROGRESS.md/やること・完了履歴 → BACKLOG.md/恒久的な学び → auto memory
- 消した経緯は git に残っているので、ファイルには「整理前は
git show <hash>:PROGRESS.md」と書いておけば十分 - ルールは「履歴は書かない」だけでは守られなかった。行数の目安(150行)と「どこへ移すか」まで書くと守られるようになった
- auto memory はサブエージェントには読み込まれない。実装をサブエージェントに任せるなら、守らせたいルールは CLAUDE.md にも書く
環境・前提
| 項目 | 内容 |
|---|---|
| ツール | Claude Code(CLI / デスクトップアプリ) |
| 期間 | 2026年6月〜9月(約3か月・PROGRESS.md のコミット112回) |
| プロジェクト | Next.js + Supabase の個人開発アプリ |
| 進め方 | Claude Code に BACKLOG の項目を順に実装させ、ほぼ毎日セッションを切り替える |
CLAUDE.md と auto memory の違いそのものは、以前の記事で整理しています。
PROGRESS.md を導入した最初の形
導入時(2026-06-24)の CLAUDE.md への追記はこれだけでした。
## Session Memory(必読・更新必須)
セッションをまたぐ引き継ぎは `PROGRESS.md` で行う。
- **セッション開始時**: まず `PROGRESS.md` を読み、現在地・次の一手・申し送りを把握してから作業に入る。
- **作業を終えるたび**: `PROGRESS.md` の「現在地」「次にやること」「申し送り」「最終更新」日付を更新する(コミット前に)。
- 役割分担: `BACKLOG.md` = やること一覧と完了履歴の台帳 / `PROGRESS.md` = 今この瞬間の現在地・申し送り(履歴は書かない)。
PROGRESS.md 本体の冒頭にも、役割をはっきり書いていました。
> **このファイルの役割**: 新しいセッションを始めた Claude が「今どこまで進んでいて、
> 次に何をすべきか」を最短で把握するための引き継ぎノート。
>
> **BACKLOG.md との違い**(重複させない):
> - `BACKLOG.md` … やることの一覧(優先度順)と、完了イテレーションの**履歴**台帳。
> - `PROGRESS.md`(このファイル)… **今この瞬間**の現在地・次の一手・未コミットの作業・
> 引っかかり・環境メモ。履歴は書かない(流れたら消す)。
>
> 恒久的な学び・設計判断・ユーザーの好みは、このファイルではなく自動メモリに残す。
このときは 37行・2.6KB。「現在地」「次にやること」「申し送り」「環境メモ」の4見出しだけでした。
3か月でどう膨らんだか
git の履歴からファイルサイズを追うと、こうなっていました。
# 8コミットおきに PROGRESS.md のバイト数を出す
for h in $(git log --format='%h' --reverse -- PROGRESS.md | awk 'NR%8==1'); do
printf "%s %s\n" "$(git log -1 --format=%ad --date=short "${h}")" \
"$(git show "${h}:PROGRESS.md" | wc -c)"
done
| 日付 | サイズ |
|---|---|
| 2026-06-24(導入) | 2.6KB |
| 2026-07-14 | 19.8KB |
| 2026-08-06 | 31.0KB |
| 2026-08-23 | 64.6KB |
| 2026-09-22 | 87.0KB |
| 2026-09-23(整理直前) | 113KB・377行 |
| 2026-09-23(整理後) | 6.2KB・55行 |
zsh で git show $h:PROGRESS.md と書くと、:P が zsh の修飾子として解釈されてパスが壊れます。"${h}:PROGRESS.md" のように波括弧で囲んでください。
整理直前のファイルで起きていたこと
113KB のファイルを開くと、次のような状態でした。
-
「現在地」が過去の作業ログになっていた
「直近の作業」「過去の作業」という段落が積み重なり、1行が1,000文字を超える箇条書きもありました。 -
同じ見出しが2回あった
## 次にやることが84行目と343行目の2か所にあり、どちらが最新か分からない状態でした。 -
古い記述への訂正が何か所もあった
「本セクション後段に『push未実施』と記載していたが、次セッションで確認したところ〜」「過去の『未push』記載は誤り」のような訂正が、6か所ありました。 -
環境メモが古いままだった
CI を Vercel から GitHub Actions に移した後も、「push 毎に Vercel のvercel-buildが CI として走る」という記述が残っていました。
3つ目と4つ目が一番まずいと感じました。
新しいセッションの Claude は、古い記述と訂正の両方を読んだうえで「今どちらが正しいか」を判断しなければなりません。古いまま放置された記述は、訂正すらされていません。引き継ぎのためのファイルが、かえって誤解の元になっていました。
なぜ「履歴は書かない」と書いてあったのに膨らんだのか
ルールには最初から「履歴は書かない(流れたら消す)」と書いてありました。それでも膨らんだ理由は、振り返ると次の2つだと考えています。
-
「更新する」が「追記する」と解釈された
「作業を終えるたびに現在地を更新する」と指示すると、Claude は前の内容を残したまま新しい段落を足していきました。消してよいかの判断基準がなかったためです。 -
消した情報の行き先が決まっていなかった
完了した作業の経緯は「どこかに残したい」情報です。行き先がないので、PROGRESS.md に残り続けました。
つまり「書くな」だけでなく、「どこへ移すか」と「どこまでなら許すか」 が必要でした。
3層の役割分担
整理後は、情報を「どれくらいの期間、意味を持つか」で3つに分けています。
| 層 | ファイル | 中身 | 寿命 | 毎セッション読むか |
|---|---|---|---|---|
| ① 今 | PROGRESS.md |
現在地・次の一手・未解決の引っかかり・環境メモ | 数日(片付いたら消す) | 読む(CLAUDE.md で必読指定) |
| ② 台帳 | BACKLOG.md |
やること一覧(優先度順)と完了履歴 | プロジェクト期間中ずっと | 必要なときだけ |
| ③ 学び | auto memory | 失敗から得た教訓・設計判断・ユーザーの好み | 恒久 | 索引(MEMORY.md)だけ自動で読み込まれる |
加えて、「なぜそうしたか」の細かい経緯は git のコミットメッセージ に寄せています。BACKLOG の完了行にはコミットハッシュを書いておき、詳しく知りたいときは git show で追える形です。
迷ったときの振り分け
実際に書く場面では、次の順に判断しています。
その情報は…
├─ 次のセッションが「すぐ」動くために必要? ──→ PROGRESS.md
│ (未コミットの作業・次の一手・未解決の不具合・一時的な制約)
├─ やること/やったことの記録? ────────────→ BACKLOG.md
│ (着手前の項目・完了日とコミットハッシュ・1行の要約)
├─ 別の作業でも同じ失敗をしないために必要? ──→ auto memory
│ (「パイプで exit code が潰れる」「getSession は認可に使わない」など)
└─ 経緯の詳細・やりとりの記録? ──────────→ git のコミットメッセージ
① PROGRESS.md:上書きして消すファイルにする
整理後の冒頭には、膨らまないためのルールを2行足しました。
> **肥大化させない**: 完了した作業の経緯は BACKLOG.md の完了行(+git log)に移し、
> ここからは消す。目安 150 行以内。
> (2026-09-23 に 110KB → 整理。整理前の全文は `git show <hash>:PROGRESS.md` で参照可)
ポイントは3つです。
- 移し先を明記する:「消す」ではなく「BACKLOG の完了行に移してから消す」と書く。消すことへの抵抗がなくなります。
- 数字で上限を決める:「肥大化させない」だけでは基準になりません。150行という数字があれば、更新のたびに「超えていないか」を確かめる基準になります。
- 整理前の場所を書いておく:git に残っているので、消しても失われません。それをファイルに書いておくと、ユーザー(筆者)も安心して消す判断ができます。
構成は導入時と同じ4見出しのままです。
最終更新: 2026-09-26
## 現在地
- 直近で終わった作業を数行。詳細は「BACKLOG.md 完了行」へのリンクで済ませる
## 次にやること
- 次のセッションが最初に手をつけるもの
- 日付つきの確認タスク(例: 約2週間後に計測値を見て着手を判定)
## 申し送り・引っかかり(未解決)
- 解決していない不具合・ツールの不調・一時的な回避策
- 解決したら消す
## 環境・運用メモ
- ビルド/テストのコマンド、CI の流れ、ハマりやすい手順
整理後の3日間(2026-09-23〜26)は、55行 → 68行と、目安の150行を大きく下回ったまま推移しています。
② BACKLOG.md:伸びてよい台帳
BACKLOG.md は、上の「やること一覧」と下の「完了済みイテレーション」の表からできています。
## バックログ(優先度順)
- [ ] #93 公開前に非機能要件を確定する(着手条件: 公開を決めたとき)
- [ ] #98 〜(着手条件: 計測値が○○を下回ったら)
## 完了済みイテレーション
| 完了日時 | コミット | 内容 |
|---|---|---|
| 2026-09-26 | 1ef7bda | #97 表示速度の常時計測を導入。… |
こちらは台帳なので、伸びるのは前提です(2026-09末時点で約84KB)。
CLAUDE.md で必読にしているのは PROGRESS.md だけなので、BACKLOG.md は必要なときに Claude が該当箇所を読みに行く形にしています。
「着手条件」を書いておくのもおすすめです。「計測値が悪ければやる」「公開を決めたらやる」といった条件付きの項目を、PROGRESS.md に「いつかやる」として残さずに済みます。
③ auto memory:失敗から得た教訓だけを残す
auto memory は Claude が自分で書くメモで、~/.claude/projects/<プロジェクト>/memory/ に保存されます。公式ドキュメントによると、索引の MEMORY.md は 先頭200行または25KBまで が毎セッション自動で読み込まれ、個別のファイルは必要なときに読みに行く仕組みです。
このプロジェクトでは約3か月で20件ほど溜まりました。例えば次のようなものです。
---
name: pipe-swallows-exit-codes
description: lint/test/buildの出力をtail/grepにパイプするとexit codeが潰れ、&&チェーンが失敗を素通りさせる
metadata:
type: feedback
---
`npm run lint 2>&1 | tail -1 && 次のコマンド` のようにパイプすると、パイプ全体の exit code は
tail のもの(0)になり、lint が失敗していても && が続行してしまう。
2026-07-12 に実際に lint エラーを見逃してコミット・push し、CI 失敗を指摘された。
**Why:** tail/grep で出力を刈ると失敗シグナルごと消える。
**How to apply:** ゲート実行はコマンドを素で実行して exit code で判定する。
出力を絞りたいときは `set -o pipefail` を付けるか、コマンドごとに分けて実行する。
PROGRESS.md との境目は、「その作業が終わっても、次の別の作業で役に立つか」です。
- 「〇〇の migration が未適用」→ 適用したら不要になる → PROGRESS.md
- 「新しいテーブルには GRANT を明示しないと 42501 になる」→ 次にテーブルを作るときも必要 → auto memory
分けておくと、教訓は索引から1行で引け、PROGRESS.md は「今」の情報だけに保てます。
auto memory はサブエージェントに届かない
整理と同じコミットで、「データ量は増え続ける前提で設計する」という方針を CLAUDE.md に書き足しました。
この方針は auto memory にも保存済みでした。それでも CLAUDE.md に書いたのは、コミットメッセージにあるとおり「サブエージェントにも効かせるため」です。
公式ドキュメントには、メインの会話の auto memory はサブエージェントには読み込まれないと書かれています(会話をそのまま引き継ぐ fork は例外)。
筆者のプロジェクトでは、実装を feature-dev というサブエージェントに任せています。
auto memory にだけ書いた方針は、実装するサブエージェントには届きません。そこで、置き場所を次のように分けています。
| 情報の種類 | 置き場所 |
|---|---|
| 実装するとき必ず守らせたいルール(例: 新しいテーブルには GRANT を明示する) | CLAUDE.md(要点だけ)+ auto memory(理由・経緯) |
| メインの会話で判断に使う学び・ユーザーの好み | auto memory だけ |
ハマったポイント・注意事項
整理そのものを AI に任せるときは「消してよい根拠」を渡す
整理を頼むときは、「完了した作業の経緯は BACKLOG の完了行と git log にあるので消してよい」と根拠も一緒に伝えるのがおすすめです。
BACKLOG に完了行がない作業は、消す前に BACKLOG へ移すよう指示しておくと、経緯が失われません。
訂正を書かずに、元の記述を直す
古い記述が間違っていたと分かったとき、「〜と書いたが誤り」と追記すると、両方が残ります。
PROGRESS.md は履歴ではないので、元の行を書き換えるのが正解です。経緯が大事なら、それはコミットメッセージに書きます。
コミットハッシュを書くためだけのコミットが増える
PROGRESS.md を変えたコミット112件のうち、49件は PROGRESS.md と BACKLOG.md しか変えていないコミットでした。
コミットメッセージに「ハッシュ」「台帳更新」を含むものだけでも24件あります。
原因は、BACKLOG の完了行にその作業自身のコミットハッシュを書こうとしたことです。
ハッシュはコミットしたあとでないと決まりません。そのため「実装のコミット → ハッシュを書き込むコミット」の2回に分かれていました。
書き込みを忘れて、(このセッションでコミット予定) のままになっている完了行も、今も残っています。
対策は、次のどちらかだと考えています。
- 完了行にはハッシュを書かず、コミットメッセージに BACKLOG の番号(例:
#97)を入れる。あとからgit log --grep='#97'で探せる - ハッシュを書くなら、次の作業のコミットに相乗りさせる。ハッシュを書くためだけのコミットは作らない
CLAUDE.md 自体も膨らませない
公式ドキュメントでは、CLAUDE.md は1ファイル200行未満が目安とされています。長いほどコンテキストを消費し、指示が守られにくくなるためです。
PROGRESS.md の運用ルールを CLAUDE.md に書き足すときも、詳細は PROGRESS.md の冒頭に置き、CLAUDE.md には「まず読む・終わったら更新する」の数行だけにしています。
まとめ
- 引き継ぎメモは「追記」で運用すると膨らみ、古い記述と訂正が混ざって誤解の元になる
- 情報を寿命で分ける:今 → PROGRESS.md/台帳 → BACKLOG.md/教訓 → auto memory/経緯 → git
- ルールには「書くな」だけでなく、**移し先と数字の上限(150行)**を書く
- 消した内容は git にあるので、整理前の参照方法をファイルに1行書いておけば安心して消せる
- auto memory はサブエージェントに届かない。実装時に守らせたいルールは CLAUDE.md にも書く
- 今後の課題:BACKLOG.md の完了履歴も伸び続けている(約84KB)。いずれは古い完了履歴を別ファイルに切り出す必要がありそう
同じプロジェクトで Claude Code を半日自走させたときの運用ノウハウは、こちらにまとめています。
長いセッション内でのコンテキスト対策(Compaction)については、こちらの記事もどうぞ。