SQLite
イベント
該当するコンテンツが見つかりませんでした
マガジン
該当するコンテンツが見つかりませんでした
技術ブログ
1. はじめに 生成AIのサンプルアプリには、AWS の資格情報がなくても動くようにフォールバック経路を持たせたものがあります。デモとしては親切な作りですが、検証に利用する場合には注意したい点もあります。環境変数を立てて「実際のモデルを呼んでいるつもり」で測った結果が、実はテンプレート生成だった、という取り違えが起こり得るからです。 AWS(Amazon Web Services)の公開サンプル aws-samples/sample-contextforge にも、このような切り替えの仕組みがあります。ローカルの SQLite と OWL オントロジーだけで完結する2つのモードと、A
はじめに こんにちは、ZOZOTOWN開発本部Webバックエンドブロックの和氣です。普段はZOZOTOWNのバックエンドを担当しています。 日々の開発にClaude Codeを使っています。使ううちに、仕様や経緯を毎回プロンプトで説明し直していることに気づきました。そこで、Claude Codeとの会話をMarkdownで残し、作業に合わせたコンテキストをClaude Code自身が組み上げるようにしました。以降、残したMarkdownを「メモリ」と呼びます(Claude Code標準のメモリ機能とは別物です。違いは後述します)。 現在、メモリは個人に閉じず、職種を跨いで十数人で共有しています。他の人が調べたこと、意思決定の背景、その人の考えまで、Claude Codeで追えるようになりました。 本記事では、この仕組みと運用、そしてチームで共有してから起きた変化をご紹介します。 目次 はじめに 目次 背景と課題 同じ説明を何度も書いていた 文脈はコードの外にある コンテキストはセッションを跨げない 採用したアプローチ 正本をMarkdownにした 検索用の索引を別に持つ 標準のメモリ機能との違い 仕組みと運用 メモリ専用のGitリポジトリ メモリディレクトリの構成 保存フロー 読み込みフロー 関連メモリの想起 実作業スキルとメモリの接続 メモリの共有 効果 Claude Codeへ同じ説明をくり返さなくなった プロンプトに書くのはまだメモリにない文脈だけ メモリとスキルがつながり人の作業は文脈集めに寄った チームの記憶になった メモリを通してチームにコンテキストが共有された メモリを通して過去の担当者に聞ける 得られた知見 メモリはなんでも残して検索を強くする メモリの矛盾は問題にならない メインセッションはコンテキストのフィルターにする 見えてきた課題 メモリの鮮度 想起の精度 検索のスケール 今後の展望 メモリを使う人をプロジェクトに関わる職種へ広げる Claude Codeから保存を促すようにする 案件・機能についての文脈集めをClaude Codeのルーティンに任せる まとめ 背景と課題 同じ説明を何度も書いていた 同じ案件・機能のなかで、一度Claude Codeに説明したことを、何度もプロンプトに書いていました。調査を依頼するとき、設計を相談するとき、実装を任せるとき、レビューを見てもらうとき、また同じことを書いているな、と思っていました。 思い返すと、中身は毎回ほとんど同じです。作業ごとに組み合わせが変わるだけで、どれも前にどこかで書いたものでした。 文脈はコードの外にある 毎回プロンプトに書いていたのは、コードにない文脈でした。仕様をどう調整したか、なぜその設計にしたか、調べて何が分かったかなどです。レビューで指摘された点や、そのとき考えた懸念と判断の理由も同様です。 こうした文脈があるのは、次のような場所です。 Slackのやり取り Confluenceなどのドキュメント ミーティングでの会話 GitHubのレビューコメント 人の頭の中 どこに何があるかは、担当者しか知りません。 コンテキストはセッションを跨げない セッションは、毎回新しいコンテキストで始まります。文脈を集めて渡しても、Claude Codeが覚えているのはそのセッションのあいだだけです。次のセッションへは持ち越せず、時間をかけて合わせた認識も一緒になくなります。 同じセッションを長く使い続けても、同じです。コンテキストには上限があり、近づくと会話が自動で要約に置き換わって、細かいやり取りが落ちます。 次のセッションで前回の文脈が必要になれば、集め直してもう一度プロンプトで渡します。ただ、渡した本人でも、すべての文脈を渡せているかは分かりません。文脈を1つ落としたまま進めると、アウトプットが期待と異なることがあります。何が足りなかったのかは、そのとき初めて気づきます。 採用したアプローチ セッションでの会話を、Claude Codeにメモリとして残してもらうようにしました。正本はMarkdownファイルで、検索用の索引はそこから切り離してローカルのSQLiteに置いています。 正本をMarkdownにした 人とClaude Codeが同じファイルをそのまま読めます。専用のビューアーは要らず、気になるところは、その場でファイルを修正できます。Gitで管理できるので、いつ何を変えたかは履歴に残ります。 検索用の索引を別に持つ メモリは作業を重ねるほど増えていきます。索引には2026年8月時点で約7,000件が載っていて、この中から欲しい数件を取り出せるかが問題です。 正本のMarkdownは、grepでも探せます。ただしgrepが見るのは、文字列が一致するかどうかです。よく使われる言葉ほど大量に当たり、少し違えば1件も出ません。たとえば「不具合」で探しても、「バグ」と書かれたメモリは出てきません。 そこで、検索用の索引を別に作り、2種類の検索を並走させています。 全文検索 :書いた言葉にそのまま一致する。チケット番号のような識別子に強い 意味検索 :文の意味を数値にして、近さで探す。「不具合」と打っても「バグ」のメモリが候補に入る 検索のたびに両方を走らせ、順位を混ぜて上位だけを返します。検索のログを集計すると、1件も返らなかったのは2.7%、欲しいメモリが3位以内に入っていたのは68.9%でした。 SQLiteにした狙いは、拡張のしやすさです。検索の手法をあとから足したり替えたりできるようにしました。 索引はGitで管理しません。正本のMarkdownから、いつでも作り直せるからです。 標準のメモリ機能との違い この仕組みを作り始めたあとで、Claude Codeにも 標準のメモリ機能 が入りました。ですが、いまも自前のメモリを使い続けています。理由は、量と共有と拡張性です。 標準のメモリは、起動時に MEMORY.md という一覧ファイルだけを読み、必要なときに詳細を開きます。ただしその一覧から読み込まれるのは、先頭200行か25KBまでです。自前の仕組みはもっと多くのメモリをためるつもりで作ったので、この上限では足りませんでした。 共有もできません。標準のメモリは手元のマシンに閉じているため、他のメンバーからは見えません。 調査や設計といった作業のスキルそのものに、メモリの読み書きを組み込みたいと考えていました。標準の機能では、そこまで手を入れられません。 仕組みと運用 メモリ専用のGitリポジトリ メモリ専用のGitリポジトリを1つ用意しています。開発リポジトリに実体は置かず、 .claude/memories からシンボリックリンクで参照します。リンク先はどの開発リポジトリからでも同じで、案件が変わっても、メモリは1か所に集まります。 開発リポジトリA/.claude/memories ─┐ 開発リポジトリB/.claude/memories ─┼─→ メモリ専用リポジトリ 開発リポジトリC/.claude/memories ─┘ メモリディレクトリの構成 置き場所は、案件・職種・担当者・作業単位・フェーズの5つの軸で決まります。 .claude/memories/ メモリ専用リポジトリへのリンク └── <案件>/ └── <職種>/ ├── 01-context/ 前提・決定事項 ├── 02-meeting/ 議事録 ├── 03-research/ 調査結果 ├── 04-feature/ チーム共通の機能作業 ├── 05-users/ │ └── <担当者>/ │ ├── 01-inbox/ 未整理のメモリ │ ├── 02-feature/ 機能単位の作業 │ │ └── <機能名>/ │ │ ├── 01-concern/ 困りごと │ │ ├── 02-context/ 仕様・要件 │ │ ├── 03-research/ 調査 │ │ ├── 04-design/ 設計・計画 │ │ ├── 05-implementation/ 実装記録 │ │ ├── 06-review/ レビュー結果 │ │ └── 07-testing/ テスト・証跡 │ └── 03-issue/ 課題単位の作業 │ └── <課題名>/ │ ├── issue.md 課題そのもの │ ├── research.md 調査 │ ├── plan.md 進め方 │ └── result.md 結果 └── 06-log/ セッションログ 同じ役割のディレクトリが、2つの階層に出てきます。それぞれスコープが異なり、上の 01-context/ や 03-research/ は案件レベル、機能の下の 02-context/ や 03-research/ は機能レベルです。 担当者ごとの階層は、コンフリクト対策です。最初は案件の下にメモリを直接置いていました。同じ案件を複数人で進めると、同じファイルを取り合うようになったので、担当者ごとに分けました。 個人のディレクトリなら、書きかけのメモや雑多な記録をそのまま置けます。チームに共有するものは、案件共通のディレクトリへ置きます。 保存フロー 保存は、「メモリに保存して」とClaude Codeへ頼むようにしました。人が言うのはこれだけで、置き場所や名前は決めません。 メモリの保存を頼むと、保存の手順をまとめたスキルが動きます。案件・職種・担当者・作業単位・フェーズを判定して、先ほどのツリーの置き場所を決めます。あとで探すための要約とタグを作り、ファイルの先頭(frontmatter)に付けます。保存の前には、同じ置き場所に似たメモリがないかを探します。あれば、そのメモリを示して、書き足すか新しく作るかを聞きます。 このフローにしているのは、メモリを読み込む際に検索しやすくするためです。そのための工夫は3つあります。 置き場所をツリーで判定する :メモリを読み込むとき、ディレクトリも検索の要素の1つになる。検索の精度を上げるために、適切なディレクトリへ機械的に保存されるようにしている 要約とタグを先に作る :メモリを読み込むとき、検索の候補として見えるのは、置き場所と要約とタグだけ。だから保存するときに要約とタグを付けておく。付けたあと実際に検索して、そのメモリが上位に出るかまで確かめている 文脈の単位で積む :置き場所と類似度で、文脈が続いているかを判定する。文脈が違えば、似ていても別のメモリになる。検索したときに、文脈を追いやすくしている 役割分担は、判断がClaude Code、実処理がMCPツールです。 判断(Claude Code) :置き場所や名前を決める。要約とタグ、関連メモリへのリンクを付ける 実処理(MCPツール) :ファイルへ書き込む 読み込みフロー 読み込みも同じです。「この機能のメモリを読んで」と頼みます。手がかりは機能名でなくても構いません。案件名やチケット番号でも、ふわっとした言い方でも探してくれます。 絞り込みの手順は2段階です。Claude Codeはまずプロンプトを解析して検索クエリを決め、先ほどの索引で数千件から数十件を取り出し、並べ替えたうえで候補を10件ほどに絞ります。 次に候補の要約に目を通し、質問の意図に合うものを数件選んで、本文を見出しと要点だけに圧縮して読みます。本文にリンクされている別のメモリがあれば、そちらもたどります。 1回分の流れをイメージで示します。機能名、パス、要約はすべて架空のものです。 人のプロンプト 商品ページの表示項目、前回どう決めたか読んで Claude Codeが組み立てた検索クエリ 商品ページ 表示項目 仕様 決定 索引が返した候補(上位10件のうち2件。置き場所と要約) 02-feature/product-page/02-context/requirements.md 商品ページの要件。表示する項目と並びを確定 本文からのリンク先: 01-context/product-info-rule.md (商品情報の共通ルール) 02-meeting/2026-06-18-定例.md 定例の議事録。商品ページの表示方針を合意 Claude Codeが読んだもの 質問の意図に合う1と2を選び、見出しと要点だけに圧縮して読みました。1の本文からリンクされていた共通ルールも、たどって読んでいます。こうして、機能の要件、定例の議事録、案件共通のルールと、置き場所の違うメモリがつながって、1つのコンテキストになります。 この形にしているのは、コンテキストを膨らませずに、数千件から欲しい数件を取り出すためです。そのための工夫は3つあります。 Claude Codeに検索をさせない :本文を読み比べるのは索引の仕事で、Claude Codeは検索クエリを渡して、置き場所と要約とタグを受け取るだけ。メモリが何千件に増えても、検索でコンテキストが膨らむことも、トークンを余計に消費することもない 1件に決め打ちしない :検索は、正解を上位10件に入れるのは得意でも、1位に当てるのは苦手。だから1位だけを読まず、10件の要約を見比べてClaude Codeが選ぶ 本文は圧縮して読む :数件でも全文を読むとコンテキストを圧迫するので、まずは質問に関係する見出しだけに絞った圧縮版で読む。足りなければ圧縮を緩めて、読む範囲を広げる 読み込みの分担は次のとおりです。 判断(Claude Code) :検索クエリを決める。候補の要約とタグを見て、読むものを選ぶ 実処理(MCPツール) :索引を検索する。本文を圧縮する。リンクを解決する 関連メモリの想起 ここまでは、人が「読んで」と頼んでからメモリを読んでいました。想起では頼みません。会話している内容に近いメモリがあれば、Claude Codeが自分から読みにいきます。 プロンプトを送るたびに、hooksが裏で動いて、読み込みフローと同じ方法で検索します。近いかどうかは1回では決めず、ターンを跨いでスコアを積み上げます。流れは次のとおりです。 検索方法 :全文検索と意味検索で、近いメモリを探す スコアリング :プロンプトのたびに候補へスコアを付け、それを累積していく。スコアは、検索での順位と、プロンプトと重なる語の多さで決まる。ただし、チケット番号や識別子のような特徴のある言葉が、プロンプトと候補の両方に出てくるときだけ スコアの減衰 :スコアは会話が進むにつれて下がり、話題が続かない候補は消えていく Claude Codeに知らせる :しきい値を超えたメモリだけが、「近い記憶がある」としてプロンプトに添えられる チケット番号のような特徴のある言葉が一致すれば、1回でしきい値を超え、ありふれた言葉では、同じ話題が何ターンか続いてはじめて超えます。できるだけ、会話に関係のないメモリを想起させないようにしています。知らされたあとに実際に読みにいくかは、Claude Codeに会話の流れを見て決めてもらいます。 実作業スキルとメモリの接続 保存と読み込みは、プロンプトで頼まないと動きません。作業に集中していると頼むのをよく忘れ、どちらも作業とは別の一手間になっていました。 そこで、調査や設計などを進める実作業スキルに、メモリの読み書きを埋め込みました。人が頼むのは「調査して」だけです。メモリのことは何も言いません。 機能を開発するときは、先ほどのツリーにあった <機能名>/ のディレクトリを作り、以降はその中で作業します。スキルはフェーズごとに1つずつあり、上から順に1本のフローとして流れます。どのスキルも、起動すると前のフェーズまでのメモリを自動で読み込み、終わると決まった先へ成果を書き出します。読み書きの場所が決まっているので、スキルどうしは互いを知らなくてもつながり、フェーズを足すときも置き場所を決めるだけで済みます。 メモリは、フェーズが来る前に置いておくこともできます。懸念なら 01-concern/ 、決まっている仕様や会議のメモなら 02-context/ 、調べてあった内容なら 03-research/ です。ディレクトリごと読み込まれるため、1つのファイルにまとめる必要はありません。 この一連のフェーズを、まとめて実行するスキルも用意しました。人が関わるのは、やりたいことを会話で詰めるところまでです。そのあとは、調査からレビューまで無人で進みます。 フローに乗る作業では、メモリの保存や読み込みを頼む場面がなくなりました。 メモリの共有 保存したメモリは、この仕組みを使うメンバー全員が読めます。いま使っているのは十数人です。案件や職種を問わず、同じ1つのリポジトリへ集まります。一人が調べたことや決めた設計を、チームの資産にするためです。 Claude Codeが応答を終えるたびに、hooksがメモリの差分を確認します。あれば、担当者専用のブランチを作り、コミット・プッシュ・プルリクエスト作成まで自動で進めます。人が手元でGitを操作することはありません。 コンフリクトはめったに起きません。書く場所が担当者ごとに分かれているからです。まれに起きてもhooksが自動で直そうとし、できなければ人に知らせます。 mainへのマージだけは自動化せず、担当者に任せています。破壊的な差分が勝手に入るのを避けるためです。区切りのよいところで中身を見てから、手でマージします。 マージされたメモリは、他のメンバーのローカルにも自動で反映されます。プッシュするときと同じく、応答の終わりにhooksが最新のmainを取り込みます。 効果 メモリを使うと、3つの変化がありました。同じ説明のくり返しが消えたこと、プロンプトがメモリにない文脈だけで済むこと、そして人の作業が文脈集めに寄ったことです。 Claude Codeへ同じ説明をくり返さなくなった 以前は、自分で調べた結果や決めた設計、その理由を毎回プロンプトへ書き並べていました。いまは「この機能のメモリを読んで」の一言でClaude Codeとの認識を合わせられます。それまでの作業で書かれたメモリが機能ディレクトリにたまっているからです。 この読み込みが、直近2か月半で約800回ありました。1つの文脈をClaude Codeへ説明し直すたびに、5分や10分はかかります。5〜10分×800回で、67〜133時間ぶんの説明が浮いた計算です。 作業のコンテキストが連続していることも、説明のくり返しがなくなった要因です。保存したメモリは、次の日にはまた読まれます。読み返されたメモリのうち半分は、保存から18.7時間以内に読まれていました。 Claude Codeへ説明し直すことがなくなり、時間削減につながりました。 プロンプトに書くのはまだメモリにない文脈だけ プロンプトに書くのは、主に新しい要望やいま決まったばかりのことです。作業に要るコンテキストを土台とタスク特有の2つに分けると、土台の部分はClaude Codeがメモリをつなぎ合わせて作ります。人が書くのは、タスク特有の部分だけです。 今回プロンプトに書いたタスク特有のコンテキストも、作業が終わればメモリとして残ります。次の作業では、それが土台側に回ります。実際に、保存したメモリの約3割は、後日の別の作業で土台として読み返されています。土台は作業のたびに厚くなり、人がプロンプトに書く分は減っていきます。毎回、いま話したいことに集中できます。 作業によって、必要になる文脈は違います。案件概要のような汎用的な土台を毎回渡すと、今回の作業との間に差が出て、その差を人が説明で埋めることになります。メモリを使えば、作業に合わせた土台が組み上がるので、その差が小さく、人はタスク特有の説明だけに集中できます。実際に、複数のメモリを読んだ作業は113回ありましたが、同じ組み合わせは一度もありませんでした。たとえばある判定ルールのメモリは7つの作業で読まれていて、一緒に読まれたメモリは7回とも別でした。 土台を説明せずに済むので、Claude Codeとの認識合わせが速くなり、細かいところまで合わせられるようになりました。 メモリとスキルがつながり人の作業は文脈集めに寄った 土台のコンテキストはメモリから組み上がるので、人はタスク特有のことだけを説明すれば、Claude Codeと詳しく認識を合わせられます。そうして合わせた認識は、メモリと実作業スキルがつながっているので、そのまま調査・設計・実装へ流れていきます。人が途中で説明し直す場面はありません。 実際に開発の進め方が、これまでと変わってきています。 文脈を集める :案件の情報を集めて、メモリに残す やりたいことを伝える :作る機能の概要を見て、Claude Codeへざっくり伝える。数ターンで認識を合わせる コンテキストが組み上がる :やりたいことと、メモリから組み上げたコンテキストが合わさって、このあとの作業に必要なコンテキストが決まったディレクトリへ置かれる 開発フローが流れる :調査・設計・実装・レビューと順に進み、プルリクエストができる プルリクエストをレビューする 以前は、各作業フェーズで、人がプロンプトで文脈を渡していました。いまは、人の作業が文脈を集めて渡すところに寄っています。 Slackで仕様が決まったとき、会議で前提が変わったとき、レビューで方針が変わったとき。そのたびに、その場の文脈をメモリに残していきます。アウトプットの品質は、タスク開始前に、点在する文脈をどれだけメモリにできるかで決まります。 チームの記憶になった ここまでは、一人で使ったときの話です。 複数人で共有すると、想像を超えた効果がありました。他のメンバーが調べたことや決めたことを、自分のClaude Codeがそのまま読みます。あとからでも、誰が決めたことか、なぜそう決めたかを詳細に確認できます。 メモリを通してチームにコンテキストが共有された コンテキストが渡る方向は3つあります。 縦 :上流から下流へ。意思決定を背景ごと引き継げる 横 :同じ職種の間で。調査や判断を使い回せる 斜め :職種を跨いで。相手の前提に気づける 縦は、上流から下流へ渡ります。 上流の要件整理や他チームとの認識合わせは、プロジェクトリーダーがまとめて引き受けることが多く、上流の文脈はリーダーにたまります。リーダーは決まったところから、メンバーへタスクを渡していきます。その際、人から人へ伝わるのは結論が中心で、そこに至る背景や経緯は薄くなりやすいです。リーダーが決定事項をメモリに残しておけば、上流で決まった背景がそのまま下流へ渡るので、以下のような効果がありました。 リーダーとの会話が認識合わせだけで済んだ :メモリから意思決定とその背景・判断材料を詳細に読み込める。メンバーはリーダーへ聞きに行かず、リーダーもメンバー一人ひとりへ説明し直さずに済む(コミュニケーションコストの削減) 下流のコンテキストが詳細になった :リーダーの意思決定・背景・判断材料が、そのままメンバーのClaude Codeの作業コンテキストになる(アウトプットの品質向上) 実際に、設計と実装で担当の分かれた機能がありました。担当者は、Claude Codeにリーダーが残した設計メモリを読み込ませ、Claude Codeとの会話で認識を固めてからタスクを始めました。引き継ぎのミーティングは開かず、軽い認識確認だけで済みました。 横は、同じ職種のメンバー同士で渡ります。 同じ案件を複数人で進めていると、誰かが調べたエンドポイントの仕様や、決めた実装方針が、そのまま他のメンバーの役に立ちます。メモリなら、それが同じ場所に集まるので、以下のような効果がありました。 同じ調査をやり直さずに済んだ :一人が調べてメモリに残せば、あとの人はメモリを読むだけで済む(調査時間とトークン消費の削減) 実装の判断を、本人へ聞く前に引けた :メモリからその機能を作った人の意思決定を読める。APIの仕様がなぜその形なのかも、担当者へ聞かずに分かる(設計の手戻り抑制・コミュニケーションコストの削減) 他のメンバーの調査と判断が、自分の作業で使えるようになりました。 斜めは、職種を跨いで渡ります。 職種が違えば受け持つ層が異なり、バックエンドはAPIが何を返すかを、フロントエンドはそれをどう見せるかを決めます。会話に上がるのは主要な部分で、細部の前提までは確認できないことがあります。メモリなら、職種が違っても同じ場所に集まるので、以下のような効果がありました。 職種を跨いで食い違いに気づけた :相手が何を前提にしているかが、自分のClaude Codeにも見える。前提・認識のずれが早い段階で見つかる(手戻り抑制・アウトプットの品質向上) 実際に、バックエンドの設計中に、Claude Codeが自発的にフロントエンド担当者の設計メモリを読み込み、設計の食い違いを指摘してきたことがありました。ある画面にタブを出すかどうかを、バックエンドはAPIが判定してフラグで返すつもりでした。フロントエンドは画面側で判定するのでフラグは要らないつもりでした。片方のメモリだけを見ていたら、気づかないまま進んでいました。 メモリを通して過去の担当者に聞ける 案件を進めながら残してきたメモリは、案件が終わったあともそのまま残ります。担当者の頭の中にしかなかった細かい文脈が、チームの記憶として永続化され、あとから誰でも詳細まで見にいけます。 これまでは、設計書をあとから読み直しても決まったことが中心で、その背景・経緯までは分かりませんでした。このようなドキュメントは読み手のために清書するので、背景・経緯が落ちやすいです。メモリには、読み手向けの作り直しが入りません。作業したときのやりとりがそのまま残っていて、設計内容を当時の背景ごと教えてくれます。 こうして残ったメモリがあれば、以前の案件の仕様を聞かれても、担当者でなくても具体的に答えられます。実際に、以前の案件で作った画面の表示仕様について、他チームから影響確認の問い合わせを受けたことがありました。その際に回答したのは、当時担当ではなかったメンバーでした。当時の案件担当者が5か月前に残した調査・設計メモリから表示している値の参照経路を確認し、最新コードをチェックしてから回答していました。 一人ひとりがClaude Codeとの会話で残したメモリが、チームの記憶になりました。他のメンバーの調査や判断はその場で自分の作業に使え、終わった案件の文脈は担当者がいなくても引き出せます。使う人と職種が増えるほど、つながる文脈も増えていきます。 得られた知見 メモリはなんでも残して検索を強くする メモリは、1件で読み切るドキュメントではありません。小さな断片をたくさん残しておき、作業のたびに検索が関係する数件を拾い、Claude Codeがつなぎ合わせて1つのコンテキストにします。1件の中身よりも、メモリどうしがつながることに価値があります。 人が読むドキュメントは、きれいに書いて1か所にまとめ、粒度も揃えます。メモリを読むのは主にClaude Codeです。きれいに整える必要はなく、検索で見つかればそれで十分です。 最初は、メモリも人が読むドキュメントと同じように、矛盾を解消し、重複をまとめてから保存していました。手間がかかるため、保存の回数は減る一方でした。そこで、保存するメモリの取捨選択をやめ、細かい実装の判断も案件全体の方針も、迷ったら残すことにしました。代わりに検索を強くします。作業に関係ないメモリは検索の上位に来ないだけで、邪魔にはなりません。欲しい1件を上位に出せるかが要になるので、検索ロジックには手を入れ続けています。 なんでも残して検索を強くすることで、いいことが3つありました。 小さな判断も引ける :ドキュメントには書かれない細かい実装の判断や、何を心配していたかも残り、あとから検索で引ける あとで必要になるものを落とさない :あとで必要になるかどうかは、残す時点では分からない。1件まるごとではなく、一部分だけがあとで効くこともある 組み合わせが増える :メモリを増やすほど、検索で拾える組み合わせも増え、作業ごとに合った土台が組める メモリの矛盾は問題にならない この仕組みでは、矛盾や間違いはそもそも入りにくい構造になっています。案件を進めながら、その場の事実をメモリに残していくからです。 とはいえ、矛盾や間違いが混ざってしまうこともあります。ですが、それが原因で困ることはありませんでした。理由は2つです。 同じ話題の作業が続く場合 :正しいことを書いたメモリがあとから積み重なる。メモリには更新日が付いていて、Claude Codeは関連するメモリをまとめて読むので、食い違えば新しいほうを正として扱ってくれる 一度きりの話題で後続のメモリがない場合 :メモリを答えにせず、手がかりにして実装や仕様を確かめる。メモリで当たりをつけ、最新のコードで裏を取ってから答える メインセッションはコンテキストのフィルターにする 検索で拾った数件のメモリにも、いまの作業に要らない部分は残ります。そのままメインセッションで作業まで進めると、要らない文脈に引きずられます。そこで、メインセッションには作業をさせず、メモリから拾った文脈のフィルターにします。サブエージェントに、作業ごとに必要な文脈だけを渡して、実行してもらいます。 見えてきた課題 メモリの鮮度 コードや仕様は変わり続けるので、メモリは放っておくと古くなります。いまは、読み込むときにメモリが参照しているコードを見て、保存のあとで変わっていれば「古いかもしれない」と警告するところまでです。まだ、古いメモリが検索の上位に出てくるのは防げていません。次の課題は、鮮度をどう検索の順位に反映するかです。 想起の精度 想起には、課題が2つ残っています。1つはプロンプトです。Claude Codeへ「近い記憶がある」と知らせるだけでは、一度も読みにいきませんでした(110件で0%)。「答える前に思い出してください」と指示として書くと、ようやく3回のうち2回は読むようになりました(208件で65.4%)。適切なプロンプトを探っています。もう1つは誤発火です。関係のない場面でも想起が出てきてしまうので、その回数を減らしていきたいです。 検索のスケール メモリは捨てずに残していくので、件数は増え続けます。増えるほど、欲しい1件を上位に出すのは難しくなります。いまの約7,000件では取り出せていますが、これが数万件、数十万件へ増えたときにどうなるかは分かりません。メモリが増えた状態を擬似的に作って、検証するところから始めようと考えています。 今後の展望 メモリを使う人をプロジェクトに関わる職種へ広げる いまメモリを使っている十数人は、全員がフロントエンド・バックエンドエンジニアです。これからは、PMやQAのようなプロジェクトに関わる他の職種へ広げていきます。この仕組みは職種を選びません。 PM :開発側の調査結果や進捗をメモリから追える。検討の経緯を残してもらえば、開発側もその背景ごと引き継げる QA :設計や実装のメモリから、この機能はどう動くべきかを読み取って、テストの観点に使える 職種を跨いで文脈が1か所に集まれば、誰が決めたことでも背景ごと引けます。チームの記憶を、プロジェクト全体に広げていきます。 Claude Codeから保存を促すようにする 実作業スキル以外では、まだメモリ保存は人が行っています。「メモリに保存して」の一言が必要です。ここをClaude Codeから「保存しますか」と聞いてくる形に変えていきます。仕組みとしては、hooksでセッション内のコンテキストがたまったことを検知して、一定量を超えると保存を促すようなイメージです。残したくない情報もあるので、保存するかどうかは人が判断します。人が意識しなくても保存ができるようになれば、メモリ量の増加につながり、つなげられるコンテキストも増えます。 案件・機能についての文脈集めをClaude Codeのルーティンに任せる メモリを活用した開発では、タスクを始める前に案件・機能についての文脈をどれだけ集められるかで、アウトプットの品質が変わります。文脈を集めてClaude Codeへ渡すのは、まだ人の作業です。SlackやConfluenceに点在する文脈を集めてメモリにする作業を、Claude Codeの ルーティン で自動化します。人が文脈を集めなくても、Claude Codeが自分で文脈を集められる環境を整備します。 まとめ 本記事では、Claude Codeとの会話をMarkdownのメモリとして残し、次の作業で検索して使い回す仕組みをご紹介しました。一人で使うだけでも、Claude Codeへ同じ説明をくり返さずに済み、次の作業は前回の続きから始められます。チームで共有すれば、他のメンバーが調べたことや決めた理由も、自分のClaude Codeから引けます。担当者の頭の中にしかなかった文脈が、チームの記憶になりました。AIに同じ説明をくり返している方や、チームで文脈をどう共有するか悩んでいる方の参考になれば嬉しいです。 ZOZOでは、一緒にサービスを作り上げてくれる方を募集中です。ご興味のある方は、以下のリンクからぜひご応募ください。 corp.zozo.com
本記事は「 Merpay & Mercoin Tech Openness Month 2026 」の17日目の記事です。 この記事は新しいロールであるPdE (Product Engineer)というClient / Backend の境界をまたぐ「越境開発」ロールの取り組みについて、@anzai, @victoria Li, @ninnin, @panoramaの4名でお送りします。記事本文は、そのうちの1人である anzai が、自分の体験を一人称で振り返る形で書いています。 はじめに 「Client エンジニアが Backend を書き、Backend エンジニアが Client を書く」——そんな体制は実際に成立するのか。Q4 に試した小さな実験を紹介します。 ひとことでまとめると、Android エンジニアが Postgres のデータベース(DB)設計とサーバー実装を書き、Backend エンジニアが iOS/Android の画面を作りました。やってみて成立はしたものの、楽な道ではありません。何が効いて、どこで詰まったのか。本記事では「越境開発」というテーマに絞って、その実際を共有します。 越境開発の背景 私は普段メルペイでClient(Android / iOS)のチームを見ている Engineering Manager です。今回はManagerとしてではなく、自分の手でコードを書く一員として KYC(本人確認)領域のAI pod (小規模な開発チーム)に参加しました。 このチームでは、Product Manager(PdM)を置かず、エンジニアが1人で1プロジェクトを仕様策定からデリバリーまで一気通貫に持つ(1 Person 1 Release)、という体制を試しています。 そしてこの体制を回そうとすると、避けて通れない課題が1つ出てきます。それは「1人で End-to-End(E2E)に持つなら、Clientも Backend も自分で書くことになる」ということです。 KYC のプロジェクトは、ほとんどの場合 iOS / Android のClientと、サーバー側の API・DB の両方に手を入れます。従来はここをクライアント担当とサーバー担当で分けていました。1人1プロジェクトにするなら、その境界をまたぐ必要があります。E2Eで開発する中で「Client エンジニアが Backend も、Backend エンジニアが Client も開発できるか」を、実プロジェクトで検証することにしました。 いくつかのプロジェクトで Client-Backend を一気通貫で開発した結果、今期はどちらも成立しました。Client エンジニアがサーバーの DB と API を書いてリリースし、Backend エンジニアがモバイルの画面を出す。これ自体が、まず確かめたかったことです。 以下では、私がどう開発を進めたかを時系列で振り返り、そのあとで、どこで詰まったかを共有します。 AI を活用した越境開発の進め方 私はClientエンジニアです。今回担当したプロジェクトで最終的に必要としていたアウトプットは、具体的には2つでした。1つはお客さまに見せる UI/UX、もう1つは、その後の業務報告に使うレポートです。この2つの具体的なアウトプットから逆算して、「では、その裏側でどんな仕組みを実装しなければならないか」を決めていく必要がありました。そしてその仕組みの大部分が、私にとって初めてのサーバーサイド(Go / Postgres)です。 そこでまず、既存の実装を AI Agent に読み込ませ、「この2つのアウトプットを満たすには、どんな設計・実装が必要か」を AI に検討してもらうところから始めました。要件は手元にあるので、あとはそれを初めての言語と環境にどう落とすか。 この記事のここから先は、その道のりを時系列でたどります。 AI の説明もコードも、最初はわからない 最初にぶつかったのは、コードを書く以前の問題でした。AI Agent が返してくる説明そのものが、何を言っているのかわからないのです。 たとえば「Postgres を起動して、goose で既存の migration を流して、psql で確認して」と AI に言われても、最初は何を指しているのか、まったく理解できませんでした。goose とは何か、psql で何を確かめればいいのか ── そのひとつひとつが、Client 開発しかしてこなかった私には初めての言葉です。AI は正しいことを言っているのかもしれないけれど、こちらにそれを受け取る前提知識がない、という状態からのスタートでした。 ここでやったのは、ひたすら AI に問い返すことです。「それはどういう意味か」「図にして説明してくれ」と、いろいろなパターンで噛み砕いてもらう。そして自分が納得できたら、その理解を「こういうことですよね」と、今度は別のBackendエンジニアに確認しに行く。これを繰り返すことで、環境がどう動いていて、何をすればテストが回るのか、開発の前提条件をまず頭に入れていきました。 前提が見えてきたところで、いよいよ実装です。さきほどの要件をもとに「設計して実装してみて」と AI Agent にお願いし、コードを書いてもらいます。すると今度は、出てきたコードそのものが読めません。 なぜここで defer を呼んでいるのか。なぜ cancel() しなければならないのか。ここで context を受け取っているのは、つまりどういうことなのか。Go のイディオムが、ことごとくわからないのです。 そこで最初は、作ってもらったコードを一行一行、すべて AI に解説してもらいました。 context のキャンセルでリソースを解放しないと goroutine が漏れる、だからこの位置で defer cancel() する。そうした説明を1つずつ受けながら、文法書ではなく目の前の実コードを教材にして読み解いていきます。 なお、DB についてはまったくのゼロからではありませんでした。モバイルでも端末上の SQLite でテーブルを設計し、クエリを書く機会はあります。正規化やインデックスといった基礎概念そのものは持っていたので、サーバーの Postgres は「知っている概念を別のコンテキストに翻訳する」作業に近く、そこは助けになりました。 チャンクごとの並走型にたどり着く ただ、「全部書いてもらってから一行ずつ解説」では、どうしても効率が良くありません。これを変えたのが、チームのふりかえりでした。 私たちは週に1回レトロスペクティブを開き、チームの進め方を少しずつ改善していました。その中で、メンバーの一人が「チャンク(意味のある塊)ごとの並走型」というやり方を持ち込みます。AI に一気に全部を生成させるのではなく、意味のあるコードブロック単位で実装させる。そのブロックが「なぜ必要なのか」を自分が理解できればそのまま進め、理解できなければきちんと問い返す。「ここは A と B のやり方がありそうだけれど、なぜ A を選んだのか」と都度たずねていくことで、コードの一行ずつの意図を理解しながら前に進みます。 このやり方だと、巨大な生成物を上から順に読み下す必要がなくなり、開発の流れを「意味のある順序」で理解できます。機械的な行順ではなく、設計の意図に沿った順序で頭に入っていく感覚です。質問と回答はログとして残し、読み返せば「今日は何を学んだか」の復習にもなりました。 選んだ理由を残し、AI のコードを自分で理解する この進め方には、思わぬ副産物もありました。「いくつかの選択肢のなかで、なぜこの A を選んだのか」を開発の過程ですでに言語化しているので、それをそのまま Pull Request(PR)の説明に書けるのです。結果として、レビューはそれほど詰まることなく得られました。初めての領域でも、選択の根拠を添えられればレビュアーは判断しやすいですし、「ここまで考えた上でのPRなんだな」という信頼も得られます。ビギナーのPRを読むことはコードオーナーにとって大変な負担ですので、このような越境開発において信頼を作るための調査は必要な工程だったと思います。 ここで1つ、立ち止まって考えるべき論点があります。AI が書いたコードを、人間がわざわざ読んで理解する必要はあるのか。生成して、テストが通って、動けばよいのではないか。これはこれから重要になる議論だと思います。 私の現時点の答えは「理解すべき」です。 これからの生産性は、書いたコード量ではなく、意思決定の回数と質でほぼ決まっていくと考えています。そして意思決定の質と回数を上げるには、ドメインの理解が必要です。「このバックエンドの設計は、これで本当に正しいのか」を判断する場面で、いまのところ最終的な判断は人間がしています。その判断を下せるだけの理解を持っていないと、意思決定の回数も質も上がっていきません。だからこそ、AI が書いたコードでも中身を理解しておく価値がある、というのが今の立場です。 またAIの仕組み的に、永遠にそのPRに対して改善ポイントを考え出すことができます。たとえば、あるPRについて1回目のセッションでAIに聞くと A・B・C の3点を直すよう言われ、その修正結果を別のセッションで聞くと、今度は E・F・G の3点を直すよう言われる、ということが起こります。それを全部反映すると、最終的にはオーバーエンジニアリングした膨大なPRになりがちなので、現状は「どこまでが適切か」を人が判断する必要があるでしょう。 もしこの「理解する」のに2〜3年かかる長期投資なら、学ぶ理由はもっと厳しく問われるでしょう。ですが実際はそうではありませんでした。いまの AI Agent によるオンボーディングは本当にしやすく、いわば優秀な指導役が隣について、いつでもペアプロに付き合ってくれるような状況です。この環境であれば、3ヶ月もあれば、いま開発している領域の一通りの知識は得られるという手応えがありました。もちろん、もともとシニアエンジニアとしての経験がある、という条件付きではあります。投資回収が数年ではなく数ヶ月の単位に縮んでいるのなら、理解する側を選ぶのが合理的だと考えています。 設計の最終確認はシニアエンジニアと とはいえ、AI に聞けばそのまま採用、とはしませんでした。象徴的だったのがインデックスの設計です。 「このカラムにインデックスを張るべきか」を、AI の提案を鵜呑みにするのではなく、なぜ必要なのか/不要なのかを自分で根拠を持って調べました。どんなクエリパターンで引かれるのか、カーディナリティはどうか、読み取りが速くなるぶん書き込みコストとのトレードオフはどうなるのか。こうした観点を1つずつ確かめて、「この設計にはこういう理由がある」と説明できる状態にします。 それでも、最後はシニアエンジニアと一緒にレビューしました。正直に言えば、これは自分の自信のなさを埋めるためでもありました。AI が生成したものが本当に正しいのか、その最終的な判断が、私一人ではどうしてもつかなかったからです。 このレビューには、不安を消す以上の価値がありました。シニアエンジニアが、考え得るパターンをいくつも挙げてくれたうえで「では、この方法でいきましょう」と意思決定でき、いくつかの改善点も見つかりました。よりベターな やり方にたどり着くうえで、人と一緒に見てもらう工程はやはり必要だったように思います。こちらは Backend エンジニアが Client 開発をする場合も同様でした。 AI で下書きと理解を加速し、自分で根拠を固め、最終的には人とレビューする。この3段構えが、初めての領域で品質を担保し、かつ自分が安心して前に進むうえで、現実的なやり方でした。AI は出発点と伴走者としては非常に強力でしたが、設計の最終的な妥当性を見極め、選択肢を広げてくれるのは、まだ人間のレビューだった、というのが実感です。 なお、今回書いた DB 設計は2テーブルだけのシンプルな構成で、本格的な分散やシャーディングの考慮までは要りませんでした。テーブルが増え、複雑なインデックス設計が絡む規模で、AI とこの3段構えがどこまで通用するのかは、まだ検証できていません。「シンプルだったから回った」可能性は十分にあります。 最後に補足すると、こうして進められた背景には、組織図上で「越境させた」のではなく、同じチームの中で互いの領域をペアプロで教え合える環境があったことが大きいです。AI に聞いてもわからないこと、そもそも何を聞けばいいかわからないことは、隣にいる詳しいメンバーにその場で聞く。AI と人、両方に頼れる相手がいたことが、越境のコストを最も下げました。 つまずいたポイントと対策 ここまでは「どう乗り越えたか」を中心に書いてきましたが、実際には数多くの詰まりどころがありました。そしてその多くは設計や実装の難しさではなく、環境・ツール・運用、つまりコードを書く以外の全部にありました。Client しか書いてこなかった人間が Backend に入ると、ここでことごとく足を取られます。代表的なものを課題ごとに紹介します。 現状の開発スタイルがわからない 最初の壁は、開発スタイルそのものの違いでした。 Clientエンジニアの感覚として、まずローカルでビルドして動作を確認しようとしました。ところが、このコードをもともとメンテナンスしていたチームは、開発環境(dev)にまずデプロイしてから動かす、というスタイルを取っていました。つまり、ローカルの docker compose は、実のところほとんど使われていなかったのです。 私はそれを知らないまま、ローカルの docker compose を立ち上げようとして、「Postgres のバージョンが合わない」「環境変数が無効だ」と、動かない環境を前に四苦八苦しました。結果ローカルでテストできるようになったので良かったのですが、リポジトリ固有のこうした暗黙知は、AI ではどうにもならない部分です。 enum を一つ増やしたら、芋づる式にバージョンが上がる 次につまずいたのは、依存関係の更新でした。やりたかったのは、protobuf の定義に enum を一つ増やし、新しく追加された定数を参照することだけです。ところが、その定義を取り込もうと go mod tidy を実行したとたん、直接は触っていないはずのライブラリのバージョンが一斉に上がってしまいました。gRPC まわりから、最終的には Go 本体の要求バージョンまで動いてしまう。たった一つの enum のために、なぜここまで広がるのか、最初はまったく見当がつきませんでした。 やっかいだったのは、その「なぜ」に対して、もっともらしい説明がいくつも出てきて、しかもそれが間違っていたことです。AI に理由を聞くと、それらしい仮説、たとえば「余計な更新を巻き込んでいるだけだから、最小限に戻せる」といった答えを返してきます。ですが、その通りに戻そうとしても差分は収まりませんでした。 ひたすらAIと問答し、ようやく分かりました。原因は依存が構造的に噛み合っていたことでした。新しい生成ライブラリが新しい gRPC 系を要求し、それがさらに別の基盤ライブラリを引き、最終的に Go 本体の下限まで押し上げている構造だったのです。本当にそうなのかの依存関係のグラフを図示し、それでも自信が持てなかったのでPR Reviewでシニアエンジニアにレビューいただきました。 ローカルでのテストと Lint DB アクセス層(DAO: Data Access Object)のテストをローカルで回そうとすると、ただ実行するだけでは通りませんでした。テスト用の Postgres を専用ポートで立て、 PGPORT を明示的に指定する、といった、チームでは当たり前すぎて誰もドキュメントに書かない作法を、1つずつ踏みながら知っていきます。 たとえば DAO テストは、 5556 のような専用ポートでテスト用の Postgres を立て、 PGPORT でそこを向けて初めて通ります。これを知らないと、テストはローカルの既定のデータベースに接続しようとして、原因の見えないまま失敗し続けます。どこにも書かれていないこの一手にたどり着くまで、エラーメッセージとにらめっこする時間が続きました。 Lint も同様でした。ローカルで走らせると、設定のバージョン差(v1 系と v2 系の非互換)でうまく通らず、CI(Continuous Integration)に任せるという割り切りに落ち着きました。「ローカルで全部緑にしてから push する」という前提が、まず崩れます。 E2E 開発のマシン要件 1人で Client も Backend も1台で回すと、マシンへの負荷が一気に上がります。実際、Android ビルド+エミュレータ、iOS ビルド+シミュレータ、Docker コンテナ3つを同時に動かして、メモリを90GB使う場面がありました。スワップなしで E2E 開発をするなら、96GB は欲しいところです。 特にBackendのEngineerは元々高いスペックのPCを持っておらず、Client開発でまず最初のローカルビルドを試す段階で躓いてしまいました。ここからローカルビルドに耐えるPCを支給してもらうまでClient開発に着手できないということが起きてしまっていました。 越境して E2E を1人で持つということは、ツールチェーンも全部抱えるということでもあります。ハードウェアは目立ちませんが、無視できない条件でした。チーム内でも「越境する人ほどマシン要件が上がる」という前提を共有し、開発機の選定では多めのメモリを見込んでおく必要がある、という話になりました。 振り返って これらの課題に共通していたのは、詰まったポイントのほとんどが、設計や実装の難しさではなく、環境・ツール・運用の暗黙知だったことです。コードを書く力そのものよりも、その手前のところで足を取られていた、というのが実感でした。 ここで効いてくるのが、もともと人間のオンボーディングでも重要だった条件です。「DX(Developer Experience)が整っている」「オンボーディング資料や開発ドキュメントが整備されている」という、人にとっての整備状況が、そのまま AI にとっての整備状況でもありました。ドキュメントが薄く暗黙知に頼っている領域では、人も AI も同じように迷います。 今のところは、やってみて初めてわかる問題を踏んでは1つずつ潰していく、いわば「悲鳴駆動」で進めるしかなく、チームを立ち上げてから数ヶ月は生産性を上げるのが難しいのが正直なところです。逆に言えば、ここをドキュメントとセットアップスクリプトであらかじめ潰しておけば、越境のコストは大きく下げられる、という改善の的もはっきり見えました。次に越境に挑むなら、最初に着手するのはこの整備だろうと考えています。 まとめ KYC で試した範囲では、Client ⇄ Backend の越境開発は成立しました。Client エンジニアがサーバーを書き、Backend エンジニアが iOS/Android を出せています。 それを支えたのは、いくつかの条件でした。まず、小規模な開発チームとして一体で動き、ペアプロやオンボーディングセッションをしながら互いの領域を学べたこと。次に、AI Agent が初見の言語やコードを一文ずつ理解する伴走者になってくれたこと。ただし、設計の最終的な妥当性を見極め、そして開発者の不安を払拭するのは、いまも人間のシニアレビューでした。環境構築やツールのバージョン、ローカルテストといった暗黙知を埋めるには、オンボーディング環境とドキュメントが要ります。一方で、選択の根拠を開発の過程で言語化し、それを残しておけば、専門外の領域でもレビューは回りました。そして最後に、これらすべてを1台で回すには、メモリ96GB級の開発機が現実的に必要でした。 そして、これらが揃っていても、最初の数ヶ月は生産性が落ちます。越境は成長痛とセットでやってくる、というのが一番の学びでした。逆に言えば、その成長痛をチームとして引き受ける覚悟と、AI を含めたオンボーディングの仕組みがあれば、「クライアントエンジニア」「サーバーエンジニア」という肩書きの境界は、思っていたより動かせます。 次は、もっと複雑な DB 設計を含むプロジェクトで、AI がどこまで越境を支えられるのかを確かめていきます。エンジニア一人ひとりが領域をまたいで動けるようになることは、巡り巡って、より早く・より確かな価値をお客さまに届けることにつながると考えています。これからもこういった挑戦を続けていきたいと思います。 次の記事は yutaroさんです。引き続きお楽しみください。
動画
該当するコンテンツが見つかりませんでした








