Imported from pokutuna/dotfiles (
claude/skills/memory-cleaner/SKILL.md). Install upstream withnpx skills add pokutuna/dotfiles --skill memory-cleaner. Copyright stays with the author.
Memory Cleaner
プロジェクトの永続メモリを 対象特定 → 早期終了条件の確認 → 現状測定・棚卸し → トリアージ → ユーザー確認 → バックアップ → 適用 → 報告 の順で整理する。
以後、「永続メモリ」はメモリ全体、「メモリディレクトリ」は保存先ディレクトリ、「個別メモリ」は MEMORY.md 以外の 1 ファイル、「index」は MEMORY.md を指す。「メモリ件数」は個別メモリの件数を指す。
対象の特定
対象は現在のセッションのメモリディレクトリ。システムプロンプトの # Memory 節に記載されているパス (~/.claude/projects/<slug>/memory/) をそのまま使う。cwd からパスを推測しない。別プロジェクトの永続メモリは対象にしない。
メモリディレクトリが空、またはメモリ件数が 3 件以下の場合は整理の必要がない旨を報告して終わる。
大原則
- スコープは永続メモリの操作。 リポジトリや CLAUDE.md に書き込むのは、ユーザーに承認された relocate (手順 3) だけ。確認の選択肢にも、永続メモリの操作と relocate 以外の行動 (issue 起票、リポジトリの修正など) を含めない。
- 判断と適用を分ける。 全件を読んで台帳を作ってから処遇を決める。読みながらその場で削除しない。個別には些細に見えるメモリが複数のメモリに共通する上位原則の一例であることがあり、keep / delete / merge は全体を見ないと決められない。
- 鮮度は「現実との照合」で判定する。 作成日や内容の印象ではなく、メモリが言及するパス・コマンド・値・事実が今も成り立つかをリポジトリや
~/.claudeで実際に確認する。 - 削除候補は 2 種類を区別する。 検証ベース (参照先の消滅・事実の矛盾・反映済み) は根拠つきで提案する。価値判断ベース (些細すぎる・もう使わない) は判断をユーザーに委ねる。
- 変更はすべてユーザーの承認後に行う。 永続メモリの削除・新規作成・統合・昇格・移管・書き換え・index の修復は、すべて承認後に行う。確認は 1 件ずつ聞かず、まとめて行う (手順 4)。
- 平易化と事実更新を区別する。 平易化では、事実を省略・一般化せず、表現だけを変える。事実が古い場合は、現実との照合で確認できた内容に更新する。この更新は rewrite として扱い、承認後に行う。
- 調査と機械的な作業はサブエージェントに委ねてよい。 個別メモリが 15 件以下なら、本文の読解はメインセッションで行い、現実との照合だけをサブエージェントに任せてもよい。16 件以上なら、個別メモリを複数グループに分け、サブエージェント (model: sonnet) に読み取り専用で並列調査させる。サブエージェントの報告のうち削除の根拠になる主張 (参照先の消滅・事実の矛盾) は、メインセッションで追試してから採用する。機械的な書き換えを委ねる場合も、ユーザーの承認後に限る。サブエージェントはユーザーに質問できないので、確認は必ずメインセッションで行う。
手順
1. 現状を測る
MEMDIR=<システムプロンプト記載のメモリディレクトリ>
ls -la "$MEMDIR"; wc -c "$MEMDIR"/*.md
ファイル数・メモリ件数・合計バイト数・index 単体のバイト数を before として記録する。index は毎セッション context に読み込まれるため、そのサイズが最も重要な数字。
2. 棚卸し — 台帳を作る (read-only)
大原則で定めた分担に従い、メインセッションまたはサブエージェントで検証する。読み取り範囲はメモリディレクトリ・対応リポジトリ・~/.claude の設定類に限る。対応リポジトリのパスは slug (元のプロジェクトパスの区切りを - に置換したもの) から復元して伝え、読み取り専用で扱わせる。
認証情報や秘密の値は読み取らず、台帳や確認画面にも出力しない。安全に確認できない項目は「検証不能」と記録し、推測で補わない。根拠は、秘密を含まないファイル名・検索結果・事実の要約で示す。
台帳には各個別メモリについて以下を記録させる:
- frontmatter (
name/description/metadata.type) と本文の要点 - 経過日数 (Read 時に付くリマインダー、または
mdls -name kMDItemFSCreationDate。取れなければ省略) - 鮮度検証: 言及するパス・コマンド・フラグ・バージョン・事実関係が今も成り立つか。
rg/fd/ 実ファイルの Read で確認した根拠つきで - 反映済みか: 内容がリポジトリの docs / CLAUDE.md / skill / 設定・実装そのものに既に反映されていないか。反映済みと数えられるのは人のレビューを経た確定文書 (確定扱いの docs・ADR・CLAUDE.md) とコード・設定だけで、AI 生成の暫定文書 (plans / research など) に書かれているだけでは反映済みとしない
- 内容が重なる・同じ上位原則から派生している個別メモリの組
- スタイル問題: 圧縮表記 (記号の羅列・矢印チェーン・1 文への詰め込み)、比喩・擬人化、本題から逸れた追記、初見で意味が取れない略語
- index との整合: リンク漏れ、実体のないリンク、
[[link]](本文中で他個別メモリのnameを指すリンク記法) の未解決、index に本文として直書きされた知見 - frontmatter の世代差:
nameとファイル名の不一致、metadata.typeがuser/feedback/project/reference以外の旧形式または不正な値
3. トリアージ
台帳を見て、メインセッションで各個別メモリの処遇を決める:
| 処遇 | 判断基準 |
|---|---|
| delete (検証ベース) | 参照先が消えた / 記載事実が現実と矛盾 / repo・docs・skill に反映済み / 再利用できる知見を含まない、完了したタスクの記録 |
| delete (価値判断) | 些細すぎる、状況が変わってもう使わない — ユーザーに聞く |
| merge | 同じ上位原則の具体例が複数ある → 統合後の文面案を作る |
| promote | index に直書きされた未反映の知見 → 意味のまとまりごとに個別ファイルへ昇格し、index は 1 行リンクにする。行単位で機械的に切らず、関連する断片は 1 ファイルに束ねる |
| rewrite | 内容は有効だが、事実の一部が古い、または表現に問題がある |
| keep | そのまま残す |
「反映済みか」と「メモリとして残す価値があるか」は独立の軸として扱う。反映済みでも、反映先から読み取れない背景があれば keep や rewrite にしてよい。逆に、どこにも反映されていない知見はメモリ側にしか存在しないので、それ自体が残す根拠になる。
rewrite にするものは、本題から逸れた追記を独立した個別メモリに分離するか削るかもここで決めておく。「検証不能」は削除の根拠にならない。検証不能な知見を残すかどうかは価値判断としてユーザーに委ねる。
メモリよりふさわしい置き場が明らかにあるもの (チーム全員に効くべき制約 → プロジェクトの CLAUDE.md や docs、プロジェクトに依らない知見 → グローバルメモリ) には、オプションとして relocate (移管) 案を添える。承認されたら移管先に書いてから個別メモリを削除し、承認されなければ、その項目について提示した永続メモリ内の代替処遇 (keep / rewrite / merge / promote / delete) を適用する。
4. ユーザー確認 — まとめて聞く
まず全案を「名前 / 処遇案 / 根拠 (検証結果の要約)」の一覧としてテキストで提示する。relocate は移管先と追記内容もここで見せる。index の修復 (リンク漏れ・切れ・重複行) が必要な場合は、それも一覧の 1 項目として出す。
そのうえで AskUserQuestion で承認を取る。1 呼び出しに入るのは 4 問・1 問 4 択までなので、全案を処遇ごとにグループ化し、1 つの選択肢に複数の個別メモリを束ねてよい (根拠の詳細は先に出したテキスト一覧が担う)。グループの承認と個別除外の指定は multiSelect の同じ問いで聞く。同じ個別メモリへの排他的な代替案 (削除する / 統合して残す) は、multiSelect: false の別の問いとして立てる。
1 件ずつ聞かない。ただし、回答の自由記述が新しい判断基準や追加の削り込み要求を含む場合は、その基準で台帳を再トリアージし、新たな案を同じ形式で再確認する。承認されなかった案は適用せず、対象を現状のまま残して報告する。承認された項目が 1 つもなければ、手順 5〜6 を行わず現状の報告だけして終わる。
5. バックアップ
適用前に必ず取る。Git リポジトリ内ではプロジェクトルートを git rev-parse --show-toplevel の結果とし、リポジトリ外では cwd をプロジェクトルートとする。保存先はそのプロジェクトルートの .claude/ 直下とし、BK_DIR には絶対パスを設定する。ユーザーがバックアップの存在に自然に気づける場所に置く。
PROJECT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
BK_DIR="$PROJECT_ROOT/.claude"
mkdir -p "$BK_DIR"
cd "$(dirname "$MEMDIR")" && zip -r "$BK_DIR/$(date +%Y%m%d-%H%M%S)-memory.zip" "$(basename "$MEMDIR")"
# 復元前に、削除対象が "$MEMDIR" と一致することを確認する
# 復元: cd "$(dirname "$MEMDIR")" && rm -r "$(basename "$MEMDIR")" && unzip <上記 zip>
復元コマンドを報告に含める。バックアップが取れなければ適用に進まず中断する。過去の実行のバックアップが残っていたら、古いものの削除を報告時に提案する。
6. 適用 — 削除 → 統合・昇格・移管 → 平易化 → レビュー → index 再生成
この順序を守る。削除するものを書き直さない、統合で文面が変わるものを先に平易化しない。
- 削除: 承認されたものだけ削除する
- 統合・昇格・移管: merge は統合後ファイルを書いて元ファイルを削除する。promote は直書き知見を個別ファイルに書き出す。relocate は移管先に書いてから個別メモリを削除する。新規個別メモリの規約:
- ファイル名は内容を表す短い名前で、既存の個別メモリの命名規約 (kebab-case か snake_case か、接頭辞の有無) に合わせる。既存から読み取れなければ kebab-case。frontmatter の
nameはファイル名 (拡張子なし) に一致させる descriptionは 1 行。metadata.typeはuser/feedback/project/referenceから内容に合うものを選ぶ- feedback / project は本文に Why: と How to apply: を持たせる
- merge では
metadata.mergedFromに元のnameを列挙する。既存個別メモリに共通するその他のキー (例:node_type) は揃えて付け、由来の分からないメタデータ (例:originSessionId) は捏造せず省略する
- ファイル名は内容を表す短い名前で、既存の個別メモリの命名規約 (kebab-case か snake_case か、接頭辞の有無) に合わせる。既存から読み取れなければ kebab-case。frontmatter の
- 平易化 (サブエージェントに委ねてよい): rewrite 対象を書き直す
- パス・コマンド・値・日付・エラーメッセージを省略・一般化しない。古い事実は、現実との照合で確認できた内容に更新する。承認済みの更新は rewrite として扱う
- 圧縮表記・矢印チェーン・1 文への詰め込みをやめ、完結した文にする。値の変化や遷移を表す 2 項の表記 (
57s→32s,SIGTERM→SIGKILLなど) は事実表記なので残す - 比喩・擬人化・独自のレトリックを、プロジェクトやリポジトリで使われている平易な語彙に置き換える
- 相対日付は、本文の文脈から特定できる絶対日付 (YYYY-MM-DD) に変換する。特定できない場合は推測せず、原文を変更しない
- 本題から逸れた追記は、トリアージで決めたとおり分離または削除する
- frontmatter は、手順 6 の項目 2 に示した新規個別メモリの規約に合わせて正規化する。既存の他のキーは残す
- レビュー: 新規作成・書き換えした全ファイル (サブエージェントの成果物を含む) をメインセッションで Read し、台帳の検証結果と承認済みの処遇案に照らして、承認されていない事実の欠落・変更がないか確認する。見つけたらメインセッションで直してから先へ進む
- index 再生成: index を作り直す。確認を複数回行った場合も、再生成は全処遇の適用が終わってから 1 回だけ行う。個別メモリ 1 件につき 1 行
- [タイトル](file.md) — 要点。元の index の節見出し (## Referenceなど) は維持してよい。要点は全角換算 40 文字未満で「何についての個別メモリか」だけを書き、コマンド・値・手順は書かない (詳細は本文ファイル側にある)。タイトルと要点は、手順 6 の項目 3 に示した平易化のルールに従い、比喩や擬人化を新しく持ち込まない。全個別メモリが index に載っていること、リンク先が実在すること、本文中の[[link]]が残存個別メモリのnameと一致することを確認する
7. 報告
- before / after: ファイル数・メモリ件数・合計バイト数・index のバイト数
- 削除・統合・昇格・移管・書き換え・index 修復の一覧 (それぞれ 1 行で)
- バックアップの場所と復元コマンド
- 次回の目安: index が 5KB またはメモリ件数が 20 件を超えたら再実行を勧める