🦙

Claude Codeに長期記憶を持たせたら、壁打ちの質が変わった

に公開2
87

どうも、AIエンジニアの@noprogllamaです。普段はAIで日常の仕組み化をしたり、投資×テクノロジーの実践知を発信したりしています。

CLAUDE.mdという仕組みがあります。プロジェクトのルートに置いておくと、Claude Codeがセッション開始時に読み込んで、プロジェクトの方針や技術スタックを把握してくれます。開発に必要な情報はこれで十分伝わります。

ですが、CLAUDE.mdには書けないものがあります。

「前にこの方針で議論して、こういう理由で却下したよね」「あの時ハマったの、覚えてる?」——過去の会話の文脈です。

私はClaude Codeを開発だけでなく壁打ち相手としても使っています。戦略の相談、記事の構成、設計判断の議論。こういう用途では、過去に何を話したかが重要です。新しいセッションを開くたびに前提の共有からやり直すのは、率直に言ってしんどい。毎朝出社したら同僚が記憶喪失になっている、あの感じです。

この問題を解決するために、自分で記憶エンジンを作りました。結果として1,942セッション分の会話が蓄積され、壁打ちの質が明らかに変わりました。

以前、一度失敗している

実はこれが2回目の挑戦です。

1回目は、claude-memというOSSプラグインをフォークして使おうとしました。コミット1,493件(2026-03-22現在)のそれなりに成熟したプロジェクトです。セキュリティ上の懸念があったのでサニタイズして、Dropboxでマシン間同期も設計したのですが…3日後に全面無効化しました。

プロジェクトごとに記憶が断絶していたこと、バックグラウンドで毎メッセージ結構なトークンを消費していたことが主な理由でした。

この経緯は以前Zennに書いたので、興味があれば「claude-memをフォークして使ってみたけど3日で辞めた話」を読んでみてください。

今回の設計思想

2回目は一から作りました。名前はsui-memory。

前回の反省を踏まえて、設計方針を3つに絞っています。

  • 外部サービスに依存しない。SQLiteの1ファイルに全データを格納する
  • バックグラウンドでトークンを消費しない。記憶の保存にLLMを使わない
  • セッション終了時に自動で保存される。手動操作ゼロ

依存パッケージも実質2つです(sentence-transformersとsqlite-vec)。削ぎ落として、ようやく動くものになりました。

仕組みの全体像

やっていることは素朴です。セッションが終わると、会話の全文がsui-memoryに送られます。sui-memoryはそれをQ&A形式のチャンクに分割し、日本語特化の埋め込みモデル(Ruri v3)でベクトル化して、SQLiteに保存します。

ユーザー側で必要な設定は、Claude Codeのsettings.jsonにHookを数行足すだけです。セッション終了時に自動で発火するので、普段の使い方は何も変わりません。

CLAUDE.mdとの棲み分け

この仕組みは、CLAUDE.mdと競合するものではありません。役割が違います。

CLAUDE.mdはプロジェクトのルールブックです。技術スタック、コーディング規約、ディレクトリ構成。静的な情報を伝えるのに向いています。セッションが変わっても内容は同じで、それでよいのです。

sui-memoryは過去の会話の蓄積です。この設計にした理由、あの案を却下した経緯、先週試して失敗したこと。動的な情報、つまり議論の文脈を保持します。

CLAUDE.mdが取扱説明書なら、sui-memoryは共有した経験に近い。どちらか一方では足りません。両方あって初めて、文脈を持った壁打ち相手になると思っています。

2つの検索を組み合わせる

記憶は保存するだけでは意味がありません。必要な時に、必要なものを取り出せなければ価値がありません。

sui-memoryでは、2つの検索を組み合わせています。

1つ目はキーワード検索です。SQLiteに組み込みの全文検索(FTS5)を使い、日本語を形態素解析なしに検索します。一般的にはMeCabなどの外部辞書を使いますが、ここではtrigramトークナイザという方式を採用しました。文字列を3文字ずつの断片に分割するだけの素朴な方法ですが、追加の依存パッケージが不要です。「Tailscale」「LaunchAgent」のような固有名詞にはこちらが強い。

2つ目はベクトル検索です。テキストの意味的な近さで検索します。エンベディングモデルにはRuri v3-310mという日本語特化モデルを選びました。310Mパラメータと小型ながらCPUでも十分な速度で動きます。OpenAIのEmbeddings APIを使わない選択をしたのは、コストとプライバシーの両面からです。全ての会話ログを外部に送信するのは避けたかったので。

この2つの結果をRRF(Reciprocal Rank Fusion)という方法で統合します。それぞれの検索結果の順位を使ってスコアを合算する仕組みで、検索方式ごとのスコアの単位が違っても公平に扱えます。キーワード検索だけだと意味的な類似を見逃し、ベクトル検索だけだと固有名詞に弱い。両方を組み合わせることで、お互いの弱点を補います。

さらに、時間減衰を入れています。古い記憶ほどスコアが下がる設計で、半減期は30日です。30日前の記憶はスコアが半分に、60日前は4分の1になります。人間の記憶も直近のことほど鮮明で、古いことは薄れていくので、この仕組みを導入してみました。

実際に使ってみて

現在、1,942セッション分の会話から7,059件のメモリが蓄積されています。検索のレスポンスは100ms前後です。

体感として最も変わったのは、壁打ちの精度です。

たとえば記事のテーマを相談するとき、以前なら毎回ゼロからブレストしていました。今は過去に検討したテーマや、その時の判断理由が文脈として残っているので、同じ議論を繰り返さずに済みます。前回の結論を踏まえて、その先の議論ができる。

これは開発の効率化というよりも、思考の相手としての質の変化です。壁打ちが壁打ちとして機能するようになった、という感覚があります。

もちろん万能ではありません。7,000件のメモリの中から本当に必要な数件を引き当てられるかは、クエリの質とチャンクの粒度に依存します。検索精度の調整は今も続けています。

前回の失敗との違い

前回(claude-mem)と今回(sui-memory)の違いを整理しておきます。

                   claude-mem        sui-memory
─────────────────────────────────────────────────
コード量            大規模              1,759行
言語               TypeScript         Python
記憶の保存          LLMで要約・圧縮    生のtranscriptをチャンク化
トークン消費        毎メッセージ数千    ゼロ(LLM不使用)
検索               Chroma(外部DB)     SQLite内蔵(FTS5+sqlite-vec)
外部依存            ChromaDB等         sentence-transformers, sqlite-vec
セットアップ        複数プロセス起動    uv syncのみ

根本的な差は、記憶の保存にLLMを使うかどうかです。claude-memはバックグラウンドでLLMを起動して会話を要約・圧縮していました。sui-memoryは生のtranscriptをルールベースでチャンクに分割するだけです。LLMを使わないから、トークンも消費しないし、応答速度にも影響しません。

要約しないぶん情報は多少冗長になりますが、大事な文脈が要約の過程で消えてしまうリスクを避けられます。何を残して何を捨てるかの判断は、保存時ではなく検索時にやればよいのです。


大規模なシステムを捨てて、1,759行で作り直しました。やっていることの本質は同じです。会話を保存して、必要な時に取り出す。余計なものを全部削ぎ落としたら、ようやく納得のいくものになりました。

私のClaude Codeは今、過去の会話を覚えている相手になっています。CLAUDE.mdでルールを伝え、sui-memoryで経験を共有する。この2層構造が、今の私にとっての最適解です。

AIで仕組み化する実践知を発信しています → @noprogllama

87

Discussion

CodeBondCodeBond

うちの構成に似ているのでとても興味深く拝見しました。
sui-memoryはSQLiteをメインにチャンク分け、ベクトル化という構成なんですね。
うちのはRAGに後付けでSQLiteを積んだ形です。
やはり記憶を持たせると会話の質が全然違ってきますよね。
ぜひ今後とも近況を教えてください。

noprogllamanoprogllama

構成が似ているとのコメント、嬉しいです。ありがとうございます。
sui-memoryはSQLiteのBM25全文検索をベースに、後からベクトル検索を重ねていった形です。
逆にRAGベースにSQLiteを後付けされたというのは、真逆のアプローチですが、求めているものはまさに同じものですね!
記憶があるとAIが本当に変わりますよね。毎回ゼロから説明し直す必要がなくなるだけで、壁打ちが積み上がる感覚になるというか。日々のAIとの会話がかなり楽になりました。
振り返ると失敗も多いですが、これに関しては正解のアプローチだったと思います。
また書いていきますので、今後ともよろしくお願いします。

ログインするとコメントできます
87