はじめに
Claude Codeで開発をしていると、セッションが変わるたびに「あれ、なんでこの実装にしたんだっけ」「前にこのライブラリ使うって決めたのに別のを使おうとしてる」みたいな事故が起きます。
AIは毎回記憶がリセットされるので、プロジェクトの決定事項を覚えていてくれません。CLAUDE.mdに書いておいても、ファイルが肥大化すると省略して読むようになるし、そもそもCLAUDE.mdは「ルール」であって「なぜそうしたか」の記録には向いていません。
そこで作ったのがsqlewというMCPサーバーです。プロジェクトの技術的意思決定(Decision)と制約(Constraint)をRDBに保存して、AIが必要なときに必要な情報だけを引っ張ってこれるようにするツールです。
つまりコンテキストの永続化です。
今回、MCP Directory申請用にサンプルプロジェクトを整備したので、これを使ってsqlewの機能を一通り紹介します。
リポジトリ: https://github.com/sqlew-io/sqlew-examples
sqlewってなに?
ざっくり言うと「AIコーディング向けのプロジェクト記憶データベース」です。
やっていることはシンプルで:
- Decision 決定方針:「JWTで認証する」「APIはRESTで作る」みたいな技術的意思決定を記録する
- Constraint 誓約:「フロントにAPIキーを置かない」「SQLは必ずプリペアドステートメント」みたいな制約・ルールを記録する
- autoADR: プラン完了時に自動でDecisionを記録する
- suggest: 新しい作業を始めるときに、関連する過去の決定を自動でサジェストする
記録先はSQLite / MySQL / PostgreSQLから選べます。MCPサーバーとして動くので、Claude Codeからシームレスに使えます。
※一般的なADRではDecisionのみを使用しますが、AIでは禁止事項であることを明示したほうがいい場合がおおいため、決定方針と誓約とを分けています。
⇒詳細:方針と誓約:sqlewが分離した2つの記録がAIの思考パターンを変える
準備
必要なもの
- Claude Codeがインストール済み
- Node.js 18以上
autoADRやsuggestの自動機能はClaude Code環境で動作します。
他のコーディングエージェントでも手動登録であれば利用可能です。
インストール
# sqlewをグローバルインストール
npm i -g sqlew
# サンプルをクローン
git clone https://github.com/sqlew-io/sqlew-examples.git
cd sqlew-examples
ADR自動化の有効化(Claude Codeプラグイン)
claude plugin marketplace add sqlew-io/sqlew-plugin
claude plugin install sqlew
claude plugin list で確認して、sqlewが ✔ enabled になっていればOKです。
❯ sqlew@sqlew-plugin
Version: x.x.x
Scope: user
Status: ✔ enabled
このプラグインを入れると、Claude CodeのプランモードでのautoADRとsuggest機能が有効になります。.mcp.jsonの設定もプラグインに含まれているので、プロジェクトごとに個別設定する必要はありません。
autoADR機能やサジェストはClaudeCodeのプランモードで動作します。記録を残したい時は必ずプランモードで。
サンプル一覧
| # | フォルダ | 機能 | ひとこと |
|---|---|---|---|
| 1 | 01-contradiction |
矛盾検出 | 過去の決定と矛盾する指示を自動検出 |
| 2 | 02-decision-driven |
Decision参照 | 毎回ゼロから説明しなくていい |
| 3 | 03-dry-check |
autoADR + suggest | 重複実装を自動検出 |
| 4 | 04-why-search |
理由検索 | git blameでは分からない設計意図を検索 |
各サンプルの使い方は共通で、フォルダに移動してClaude Codeを起動するだけです。
cd 01-contradiction
claude
基本、各サンプルのREADMEの日本語版です。では順番に見ていきましょう。
01-contradiction: 矛盾検出
何ができるか
例えば過去に、ライブラリは「dayjsを使う」と決めたのに、後から「date-fnsを使いたい」と指示してしまった場合に、sqlewが矛盾を検出して警告してくれるデモです。
チーム開発だと「あれ、これ前に別の方針で決まってなかったっけ?」というのが本当によく起きます。一人開発でもセッションが変われば同じことが起きますし、これは人間でも先週決めたことを忘れている事が稀によくあるので、これは地味に助かる機能です。
使ってみる
cd 01-contradiction
claude
ステップ1: 最初のDecisionを登録
Claude Codeで以下のように伝えます:
日付処理にはdayjsを使うことにしました。
moment.jsからの移行が簡単で軽量なのが理由です。
sqlewに記録してください。
手動登録はプランモードでなくてもOKです。
decision:set が呼ばれて、dayjsの採用がDecisionとして記録されます。
ステップ2: 矛盾する指示を出す
プランを作って:日付処理にdate-fnsを使いたい(tree-shaking対応のため)。
sqlewを確認して、コンフリクトがあればどちらを採用するか聞いて。
手動でプランモードにしてもいいですし、「プランを作って」とプロンプトにあると自動でプランモードに切り替わります。
プランを作成する段階で decision:suggest が走り、「dayjsを使うというDecisionが既にありますよ」と警告が出ます。AIが「どちらを採用しますか?」と確認してくれるので、意図せずポリシーが二転三転するのを防げます。
ポイント
過去の決定を忘れて矛盾する指示を出しても、sqlewが過去のDecisionを参照して警告してくれる。
02-decision-driven: Decision参照
何ができるか
プロジェクトに事前登録されたDecisionを、新機能実装時にAIが自動参照するデモです。
「認証はJWT」「APIはREST」「バリデーションはzod」みたいな方針が決まっているプロジェクトで、新しい機能を実装するたびにいちいち説明し直す必要がなくなります。
事前登録されているDecision
このフォルダのデータベースには下記の決定方針が登録済みです。
| キー | 値 | 理由 |
|---|---|---|
auth/method |
JWT | セッション管理不要、マイクロサービス向き、Logto Cloudで発行 |
api/style |
REST | チームにGraphQL経験なし、ドキュメント生成が楽 |
api/versioning |
URLパス (/v1/) | ヘッダーより明示的、デバッグしやすい |
validation/library |
zod | TypeScript互換、エラーメッセージのカスタマイズ可 |
password/hashing |
bcrypt | 業界標準、コストファクター調整可 |
使ってみる
cd 02-decision-driven
claude
プランモードで:../specs/02-user-registration.md に従ってユーザー登録機能を実装してください。
まずsqlewでプロジェクトの決定事項を確認して。
すると decision:suggest が走って、関連するDecisionが自動でサジェストされます:
- 認証 → JWT
- API → REST, /v1/
- バリデーション → zod
- パスワード → bcrypt
AIが「これらのポリシーに従って実装します」と確認してくれるので、POST /v1/users でzodバリデーション、bcryptハッシュ、JWTトークン返却という一貫した実装が出てきます。
ポイント
毎回ゼロから説明する必要がない。プロジェクトの方針はsqlewに入っているので、関連するDecisionが自動で参照される。
03-dry-check: autoADR + suggest
何ができるか
autoADR(自動Decision記録)とsuggest(類似実装サジェスト)を組み合わせて、重複実装を自動検出するデモです。
日付ユーティリティを実装した後に、似たような予約時間ユーティリティを実装しようとすると「既存のdate-utilsを再利用しませんか?」とサジェストしてくれます。
使ってみる
cd 03-dry-check
claude
ステップ1: date-utilsを実装
プランを作って:../specs/03-date-utils.md に従って日付ユーティリティを実装して。
src/utils/date-utils.ts が生成されて、プラン完了時にautoADRが走ります。実装した内容がDecisionとして自動記録されます。
ステップ2: booking-timeを実装しようとする
プランを作って:../specs/03-booking-time.md に従って予約時間処理を実装して。
ここで decision:suggest が走って、「似たような機能がdate-utilsにありますよ」とサジェストされます:
-
formatBookingTime≒formatDate -
parseBookingTime≒parseDate -
addHours≒addDays(時間単位版が必要なら拡張) -
isSameBookingDay≒isSameDay
AIが「date-utilsを拡張する形にしますか?それとも別モジュールにしますか?」と提案してくれます。
ポイント
autoADRが実装完了時に自動記録するので、次に似た機能を作ろうとしたときにDRY違反を検出できる。
04-why-search: レガシー理由検索
何ができるか
レガシーコードの「なんでこうなってるの?」をsqlewで検索するデモです。git blameでは分からない設計意図を即座に回答してくれます。
背景:AIとコメントの問題
// Return value is decimal
public String magic_number(int number, String append_num)
decimal? String?
人間なら「は?」ってなりますけど、AIはコメントを素直に信じます。変数名やコメントが実装と乖離していても、AIはそれを検出できません。
sqlewはコードの外側に意図を記録するので、AIは「実装者が明示的に残した決定」だけを参照できます。
レガシーコード
src/legacy/PriceCalculator.java に、一見不自然な実装があります:
-
calculateWithTaxがなぜかStringを返す -
applyDiscountの引数discountCodeがなぜかString型 -
sumPricesがカンマ区切りの文字列を受け取る
事前登録されているDecision
| キー | 理由 |
|---|---|
legacy/price-calculator/return-type |
外部の販売管理システムがSOAPで文字列しか受け取れない。2019年から技術的負債として認識済み |
legacy/price-calculator/discount-code |
外部クーポンシステムからのコールバックが文字列。バリデーション済み数値文字列が来る前提で、型変換は受信側の設計方針 |
legacy/price-calculator/prices-csv |
レガシーバッチシステムのインポート形式がCSV。配列変換コストを避けてそのまま受け取る。将来的にListに移行予定 |
使ってみる
cd 04-why-search
claude
ステップ1: コードについて質問
src/legacy/PriceCalculator.java を見て。
calculateWithTax がStringを返すのはなぜ?
sqlewで理由を検索して。
Decisionが見つかって、「外部の販売管理システムがSOAP経由で文字列しか受け取らないからです。2019年から技術的負債として認識されています」と回答が返ってきます。
ステップ2: 別の質問
applyDiscount の discountCode が String なのはなぜ?
普通ならintですよね。sqlewで理由を検索して。
「外部クーポンシステムからのコールバックが文字列形式だからです」という回答。
ステップ3: リファクタリング提案
プランを作って:PriceCalculatorをリファクタリングしたい。
sqlewのDecisionを参照して、互換性を維持しながら改善提案して。
3つのDecisionを全部参照した上で、互換性を考慮した段階的な改善プランが出てきます。内部メソッドは適切な型にして、外部連携用のアダプターメソッドを別途用意するような構成ですね。
ポイント
コミットメッセージが「fix」しか書いてなくても、コメントが間違っていても、sqlewに理由が記録されていれば「なんでこうなってるの?」に即答できる。
まとめ
sqlewの効果は使い込むほど出てきます。初日から劇的に変わるツールではないですが、Decisionが蓄積されていくとAIの提案の質が目に見えて変わります。
自分のプロジェクトでは400件以上のDecisionが蓄積されていて、新機能の実装時や機能の修正時には、ほぼ毎回関連する過去の決定がサジェストされるようになっています。
古参のプロジェクトメンバーが「あーそれはこういう経緯で……」というのをAIに教え込んでくれるイメージです。
「AIは毎回別人」という問題に対して、記憶をMarkdownファイルではなくRDBMSに保存してキーワード検索できるようにしたのがsqlewの基本的なアプローチです。興味があればサンプルを動かしてみてください。
