この記事は Zenn に投稿したものの再掲です。
https://zenn.dev/reona777/articles/claude-code-memory-53-notes
教育系の事業所で現場の運営をしています。エンジニアではありません。2026年の春から Claude Code で社内ツールを作り始めて、5か月で6本を本番稼働させました。
前の記事で、CONTEXT.md と SPEC.md と ADR を書かせると開発が途中で破綻しなくなる、という話を書きました。あれは1つのプロジェクトの中で決定を残す話です。
実際に何本かツールを動かし始めると、それでは届かない層があることが分かってきます。この記事はその層の話です。手元のメモリが53本たまったので、何を書いたら効いて、何を書いても効かなかったかを数えて書きます。
設計文書は、そのプロジェクトの外に出ない
CONTEXT.md も SPEC.md も ADR も、そのリポジトリの中にあります。当然ですが、別のツールを触っているときには読まれません。
ところが実務で痛い目を見るのは、だいたいプロジェクトをまたぐ種類のことです。
- 外部サービスへの通知は、テスト投稿でも取り消せない
- 人名を消したつもりで grep すると取りこぼす
- ある種のシートは、CLIから触ると403になるのでブラウザから触るしかない
これらはどのプロジェクトの仕様書にも書けません。ツールAで踏んだのに、次に効くのはツールDだからです。プロジェクト単位の文書は、置き場所として間違っている。
Claude Code には、これを置くための場所があります。私の環境では実体はただのファイルで、こうなっています。
~/.claude/projects/<プロジェクト>/memory/
MEMORY.md 索引。セッションの最初に読まれる
feedback_xxx.md 1ファイル1事実
project_xxx.md
reference_xxx.md
各ファイルの先頭には frontmatter があり、name と description、それに種別(user / feedback / project / reference)が入ります。本文中で [[別のメモリの名前]] と書くと相互にリンクします。
実物の規模
数えました。
- 実体のメモリ 53本、合計 183,485字
- 1本あたり平均 3,462字。最大は 18,663字、最小は 524字
- 索引の MEMORY.md は 8,128字、53行
- 本文中のリンクは 153箇所、指し先は52種
作られた時期に偏りがあります。
2026-05: 2本
2026-06: 2本
2026-07: 24本
2026-08: 25本
4か月のうち、最初の2か月で4本しか書いていません。 使い方が分かっていなかったからで、当時は「便利そうな機能」くらいの認識でした。7月に事故が続いて、そこから増えています。あとで書きますが、増えた中身も事故が大半です。
4つある種別のうち、1つは一度も使っていない
内訳です。
project 27本
reference 15本
feedback 11本
user 0本
user は「自分が何者で、どういう好みか」を書く枠です。0本のまま4か月経ちました。
書かなかったのは、同じことが CLAUDE.md に書いてあるからです。回答は日本語で簡潔に、勝手に commit しない、といった常時適用のルールは、毎回読まれるファイルに置いたほうが確実です。メモリは索引を経由して必要なときだけ引かれるので、常に効いてほしいものを置く場所ではありません。
枠が4つ用意されていると、4つとも埋めたくなります。埋まらない枠は、その枠が要らないのではなく、そこに入るはずのものが別の場所にあるサインでした。
書かないもの ―― コードとgitに残ること
いちばん最初に決めたのはこれです。実物を読めば分かることは書きません。
- 何をどう直したか(gitのログが正)
- ファイル構成、関数の役割(コードが正)
- 設定値そのもの(設定ファイルが正)
理由は、書いた瞬間から古くなるからです。コードは変わりますが、メモリは誰も書き換えません。実際、私のメモリを開くと毎回こういう注意書きが出ます。
Memories are point-in-time observations, not live state
書いた時点のスナップショットであって、今の状態ではない、という警告です。この警告が要るような内容を書くと、事故ります。後の「効かなかったこと」でその実例を書きます。
書く価値があるのは、実物に痕跡が残らないもの
残った53本を読み返すと、書いてよかったものは3種類でした。
1. 事故と、そこから作った運用ルール
いちばん効きます。実物をそのまま載せます。これは「AIが会話の終盤で作業を先送りしてくる」ことに対して作ったルールです。
会話が長くなってきたときに「あとは後日やりましょう」「次回決めましょう」と
作業を先送りするのは禁止。コンテキストが苦しくなっているなら、
**そう正直に言って `/compact` を提案する**。
**Why:**
先送りの提案は、ユーザーには「作業上の判断」に見える。実際はこちらの都合
(コンテキスト残量)であることが多く、ユーザーは理由を知らないまま、
進められたはずの作業を止められる。判断材料を隠したまま結論だけ出しているのと
同じで、[[feedback_no_fabrication]] と同じ種類の不誠実さになる。
**How to apply:**
- 作業を止める提案をする前に、理由が「作業上そこが区切り」なのか
「こちらのコンテキスト」なのかを自分で切り分ける。
- 長い会話の締めに入りたくなったら、それは大抵こちらの都合。まず疑う。
このメモリには続きがあって、面白いのでそこも載せます。私はこのとき「前も同じ指示をしなかったか」と聞いたのですが、
**この指示は2026-08-11が初出。** 同日ユーザーから「前も言わなかったっけ?」と
確認されたが、全ログ63本・人間の発言739件を走査した結果、過去にその指示は
存在しなかった(ユーザーの記憶違い)。
私の記憶違いでした。過去のログ63本を全部走査した結果として、私(人間側)の記憶が間違っていたことが、記録として残っています。
これは人間が自分で書くドキュメントには、まず残らない形です。自分の思い違いが確定した瞬間というのは、書き留めるより先に片付けたくなります。書き手が別なので残りました。
2. 公式ドキュメントに書いていない外部サービスの挙動
調べても出てこないが、次も必ず踏むものです。
- あるスプレッドシートは CLI から触ると403になる。ブラウザから操作するしかない
- ある投稿方式は、UIからもAPIからも削除・編集ができない(4通り試して全滅と書いてある)
- 記事投稿サービスの限定共有URLは、公開記事とパスの形が違う。公開前のURLで開くと404になる
この種類は、書いておくと次に同じ壁に当たったときの調査時間がまるごと消えます。 私のメモリで15本ある reference は、ほぼ全部これです。
3. 判断の理由と、却下した案
前の記事に書いたADRと同じ役割ですが、こちらはプロジェクトをまたぐ判断を置きます。「この方式は検討して却下した、理由は◯◯」という形です。
書いていないと、同じ提案が新鮮な顔をして毎回出てきます。これは前の記事にも書きました。
実際にいちばん効いた1本
具体的なほうがいいので、効いた1本を紹介します。社内で作ったツールを、作品としてGitHubに公開するときの手順です。以下は実物ですが、固有名の部分だけ伏せています(まさにその話をしているメモリなので)。
社内ツールを作品として公開するときは、**既存のプライベートリポジトリを
public に切り替えない**。新規リポジトリに、履歴なしの1コミットで出す。
**Why:** 過去のコミットに実名が残るため。現在のファイルを綺麗にしても、
コミット履歴から誰でも読める。
ここまでは、少し考えれば出てきます。効いたのはこの下の「実際に踏んだ罠」の節でした。
- **危ないのは資格情報より固有名だった。** `.env` は最初から gitignore されていて
混入ゼロ。一方で**実在の人名が11名**、コード・テスト・SPEC/README に直書きされていた
- **grep では取りこぼす。** 最初の検索で見つかったのは3名だけ。
漢字の連続(`[一-鿿]{3,5}`)を全部列挙して目視するまで、残る8名が出てこなかった
- Git Bash の grep は `[一-龥]` のようなマルチバイト文字クラスが壊れる。
**この種のスキャンは Python で書く**
- **姓と名を別々に置換する。** そうすれば「山田 太郎」「山田 太郎」「山田太郎」を
一度に拾える。フルネームで置換すると空白入りの表記が残る
- **人名を差し替えると `localeCompare(_, "ja")` の順が変わり、
順序を固定したテストが落ちる。**
最後の1行が、この記事で言いたいことの見本です。
人名を差し替えたらテストが落ちた、という話は、どこにも痕跡が残りません。 テストは直せば通ります。直ったコードを見ても、なぜその名前なのかは分かりません。しかも実際には、そのとき「優先順位でソートするテスト」が名前順と同じ結果になっていて、ロジックが壊れても通る状態になっていました。名前を割り当て直して初めて、テストがテストとして機能しました。
この一連の判断は、コードにもgitログにも残りません。メモリに書くのはこういうものです。
Why と How to apply を必ず書く
上に貼ったメモリは、全部この形になっています。
何をするか(1〜2行)
**Why:** なぜそうなったか。だいたい事故の記録
**How to apply:** 次にどう動くか
前の記事で「理由の無い禁止は破られる」と書きました。仕様書に「これは作らない」とだけ書いて理由を書かないと、書いた本人が先に疑い始めるという話です。
メモリでも同じで、こちらのほうが症状が早く出ます。禁止事項だけ書いてあると、次のセッションでAIが「なぜですか」と聞いてきます。答えられないと、その場で考え直すことになって、書いていないのとほぼ同じになります。
How to apply を分けているのは、読んだ直後に何をすればいいかが書いていないと、読んでも動きが変わらないからです。「取り消せない前提で送る」だけだと解釈が要りますが、「送る前に投稿先と本文を見せる」と書いてあれば、そのまま実行できます。
索引が本体
53本で183,485字ありますが、セッションのたびに読まれるのは索引の MEMORY.md だけです。8,128字。本体の4.4%しか常時読まれていません。
索引はこの形です。
- [結果を捏造しない](feedback_no_fabrication.md) — ツールの実行結果は必ず実物を
確認、未確認は断定せず失敗もそのまま報告
- [貼り付け用テキストは素で出す](feedback_paste_text_plain.md) — 引用ブロックで
出すと記号が混入してそのまま公開される。文字数制限と改行の扱いも先に確認する
書き方でひとつだけコツがあります。「何が書いてあるか」ではなく「どういう状況で開くべきか」を書くことです。
「貼り付け用テキストについて」だと、読んでも開く理由になりません。「引用ブロックで出すと記号が混入してそのまま公開される」と症状で書いてあると、テキストを提示しようとしている場面で引っかかります。索引の1行は要約ではなく、引っかかるためのフックです。
ちなみに2番目の行は実話で、記号が混入したプロフィールがしばらく公開されたままでした。索引に症状を書いてあるのは、そういう理由です。
効かなかったこと
正直に書きます。3つあります。
1. 命名が割れて、リンクが切れていた
これを書くのは少し恥ずかしいのですが、この記事のために数えて発覚しました。
メモリ同士は [[名前]] でリンクします。この名前が指すのはファイル名ではなく、frontmatter の name です。そして私のメモリでは、その2つがずれている本が 53本中14本ありました。
ファイル名 reference_gas_clasp.md ← アンダースコア
name reference-gas-clasp ← ハイフン
こうなると、リンクを書くときにどちらの形を思い出すかで結果が変わります。数えました。
- リンク総数 153箇所のうち、23箇所(10種)が実体に届いていない
- 届かない10種は、全部がハイフンとアンダースコアの取り違えだけ。綴りの間違いは1つもない
いちばん派手に外していたのがこれです。
name は reference-gas-clasp
[[reference_gas_clasp]] ← 3本のファイルから計6箇所。全部切れている
いちばん多く参照されているメモリが、1箇所も繋がっていませんでした。 よく参照されるということは、それだけ「他のメモリを書くときに引き合いに出したくなる中心的な内容」だという意味なので、切れて困る順に切れています。
前の記事で私が書いたのは、「同じものが別の名前で呼ばれ、別物として実装される」のがいちばん高くつくという話でした。それを潰すために CONTEXT.md に _Avoid_(使ってはいけない類義語)を並べろ、と書きました。
その記事を書いた本人のメモリが、まさにその症状になっていました。しかも _Avoid_ で防げる種類の揺れではありません。類義語ですらなく、区切り文字が違うだけです。
実害を確認しておきます。切れたリンクはエラーになりません。仕様上、実体のないリンクは「まだ書いていない、いずれ書く価値のあるもの」という扱いになります。つまり、
すでに書いてあるメモリが、「まだ書いていない」ことになります。
エラーが出ないので、こうして数えるまで4か月気づきませんでした。教訓としては、_Avoid_ で類義語を止めるより先に、機械が照合できるところは1回スクリプトで突き合わせるほうが安い、ということだと思います。この検査は数行で書けて、4か月ぶんの不整合が10秒で出ました。
この記事を書いたあとに直しました。 ファイル名が全部アンダースコアだったので、name をそちらに揃える方針にしたのですが、やってみると片側だけでは終わりませんでした。
name を直すと、今度はもう片方が切れます。 ハイフンの name に向けて [[reference-gas-clasp]] と正しく書いてあったリンクは、name をアンダースコアに変えた瞬間に届かなくなります。届いていなかった23箇所のうち6箇所は name を直すだけで自動的に繋がり、逆に今まで繋がっていた側が新たに17箇所切れる。両方を一度に置き換えないと、不整合の総量が減りません。
結局、name 14本とリンク17箇所を同時に書き換えて、切れているリンクは0になりました。検査と置換を合わせてスクリプトは59行(コメントを除く)です。4か月放置していたものが、書き始めてから20分ほどで片付きました。先に検査だけ書いて、出た数を見てから直し方を決めるとよかったと思っています。
2. メモリを出典にすると間違える
これは前の記事にも書いた失敗の続きです。
公開する記事に「用語26語・仕様12節」と数字を書いたのですが、実物を数えたら29語・13節でした。メモリに書いてあった数字をそのまま写したためです。修正済みですが、3日ほど間違ったまま公開されていました。
そのあとメモリに、こう追記しました。
**メモリは索引であって出典ではない。** 外に出す文章の数字は、
メモリで在り処を特定してから実物で取り直す。
実際、記事の本文に使う数字を実コードから取り直したら、メモリに書いていない精度の情報がコメントに残っていました(「92回失敗」「1か月停止」といった具体的な数字です)。メモリは「どこを見ればいいか」までは正確ですが、「値そのもの」は劣化します。
この記事に書いた数字も、全部この場で数え直したものです。 53本、183,485字、14本、23箇所。
ただし、それでも一度間違えました。最初に字数を数えたとき、Windows PowerShell で (Get-Content -Raw).Length を使ったのですが、UTF-8のファイルをシステム既定の文字コードとして読んでいて、字数が1.3倍に膨らんでいました。 合計238,518字という数字が出て、しばらくそれを信じて書いていました。気づいたのは、同じファイルを別の方法で読んだときに数が合わなかったからです。
私のメモリには、まさにこれについての項目があります。
**確認そのものが壊れている場合もある。**「確かめた」と言うときは、
確認方法が本当にその主張を支えているかまで見る。
書いてあっても踏みます。数えたこと自体は正しくて、数え方が壊れていました。実物を見に行けば安全、というほど単純ではないようです。数字が想定と食い違ったときに、対象ではなく計測のほうを疑うという手順を1つ増やすしかないと思っています。
ついでに分かったことがあります。メモリには、自分が何本あるかがどこにも書いてありません。 種別の内訳も、合計字数も、書いてありません。当然といえば当然で、そういう数字は数えれば出るものだからです。それを書き留めなかったこと自体が、この記事の基準どおりの運用になっていた、ということだと思います。
3. 肥大化して、索引の1行では中身が想像できなくなる
最大のメモリは18,663字あります。1本のプロジェクトについて4か月ぶん追記し続けた結果です。
索引にはこう出ます。
- [◯◯の進捗](project_xxx.md) — 稼働中・◯月に◯◯を削除済み・◯◯の仕様と二重問題
18,663字を1行で表そうとすると、こうなります。「・」で区切って足していくしかなくなり、どれが今も有効なのかが行から読み取れません。 開けば分かるのですが、開くかどうかを判断するための1行なので、判断ができなくなっています。
1ファイル1事実、という原則を守れていない結果です。本来は時期ごと・機能ごとに割るべきでした。ただ、割ると今度はリンクの張り替えが要るので、まだ手を付けていません。
まとめ
4か月53本で、書く基準はこうなりました。
書かない
- コードとgitログを読めば分かること
- 常に効いてほしいルール(CLAUDE.md に置く)
- 今の状態(すぐ古くなる)
書く
- 事故と、そこから作った運用ルール。Why と How to apply をセットで
- 公式ドキュメントに載っていない外部サービスの挙動
- 却下した案とその理由
索引の1行は要約ではなくフック。「何が書いてあるか」ではなく「どういう状況で開くべきか」を書く。
前の記事の3文書(CONTEXT / SPEC / ADR)と役割を並べると、こうなります。
CLAUDE.md 常に効かせたいルール。薄く保つ
memory/ プロジェクトをまたぐ事故と外部仕様。索引から必要な分だけ
CONTEXT.md そのプロジェクトの言葉
SPEC.md そのプロジェクトで作るもの・作らないもの
docs/adr/ そのプロジェクトの判断の理由
分かれている理由は、前の記事に書いたのと同じで更新の頻度と寿命が違うからです。混ぜると、いちばんよく変わるものに引きずられて、全体が「たぶん古い」扱いになります。そうなった文書は、AIも人間も読まなくなります。
書く内容の基準は、種類が違っても1つでした。調べれば分かることは書かない。自分の環境で壊れた場所を書く。 これは以前スラッシュコマンドについて書いたときと同じ結論で、渡す文書の形が変わっても、価値のある中身は変わらないようです。
ほかに作ったものは GitHub に置いています。
書いている人
エンジニアではありません。勤務先の業務ツールを Claude Code で作って運用していて、作ったものと、壊れたときに直した話を書いています。
Claude Code の実務運用については X(@KouritsuONI)でも書いています。スプレッドシート・GAS・LINE・Salesforce まわりの業務自動化について、ご相談は X のDMからどうぞ。
この記事のシリーズ
Claude Code の実務運用について、順に9本書いています。
- 非エンジニアがClaude Codeで社内ツールを6本 本番稼働させるまでにやったこと
- AIに作らせたツールが本番で壊れた5つの原因と、直し方
- Claude CodeにCONTEXT.mdとSPEC.mdとADRを書かせると、途中で破綻しなくなる
- Claude Codeのスラッシュコマンドには、手順ではなく踏んだ罠を書く
- Claude Codeのメモリに53本ためて分かった、書く価値のある事実とない事実(この記事)
- 実行は成功、でも誰にも届いていない。無言で失敗する自動化に気づく仕掛け
- Salesforceの項目は「ある」と「使える」が別だった。外から自動化して踏んだ6つ
- Salesforceのパスワードを変えたら、連携が8箇所いっせいに止まった
- Salesforceのログインが2027年6月に廃止される。自動化10本を調べたら、直す場所は1つではなかった