この記事は Zenn に投稿したものの再掲です。
https://zenn.dev/reona777/articles/context-spec-adr-for-claude-code
教育系の事業所で現場の運営をしています。エンジニアではありません。2026年の春から Claude Code で社内ツールを作り始めて、5か月で6本を本番稼働させました。
最初の記事で「コードより先に言葉を決めさせた」と書き、次の記事の最後で「その言葉にさせるところをどうやっているかは次に書きます」と予告しました。この記事がそれです。
前の2本は起きたことの話でしたが、今回は手順の話なので、実際に使っている文書の中身をそのまま載せます。 題材は個人用に作った学習記録アプリで、CONTEXT.md に用語29語、SPEC.md に13節、ADR が6本あります。3つ合わせて約14,000字、原稿用紙で35枚ぶんです。
AIとの開発は、4つの形で破綻する
先に症状から書きます。私が実際にやられた順です。
1. 前のセッションで却下した案が、また出てくる
一度「それはやらない」と決めたはずの機能を、翌週に「こうすると便利になります」と提案してきます。断った理由は私の頭の中にしかないので、毎回説明し直すことになります。3回目くらいで、自分でも「なんで断ったんだっけ」と思い始めます。
2. 同じものが別の名前で呼ばれ、別物として実装される
これがいちばん高くつきます。私のアプリには「問」「項目」「単元」という似た概念があります。ここを曖昧にしたまま進めると、ある関数では「項目」が単元を指し、別の関数では設問を指す、という状態になります。気づくのはだいたい、その両方を使う3つ目の関数を書いたときです。
3. 頼んでいない機能が付いてくる
AIは親切なので、言っていないものを作ります。通知、統計画面、設定項目。動くので気づきにくく、気づいたときには他の部分がそれを前提にしています。
4. 直したはずの判断が、次の週に戻っている
いちど直した実装が、別の機能を足したときに元の形に戻ります。直した理由がコードに書いていないので、AIから見るとそれは「一貫性のない書き方」に見えて、揃えられます。
4つとも原因は同じで、決定が人間の頭の中にしかないことです。AIのコンテキストは毎回リセットされます。しかしこれはAI特有の問題ではなくて、人を1人雇っても、3か月後の自分に引き継いでも同じことが起きます。違うのは、AIは毎日リセットされるので、遅くとも1週間で症状が出るところだけです。
3つのファイルが、それぞれ別の症状を潰す
私が置いているのはこの3つです。
CONTEXT.md 用語の定義だけ。実装のことは書かない
SPEC.md 何を作るか
docs/adr/ なぜそう決めたか。1決定1ファイル
対応はこうなります。
- CONTEXT.md が症状2(名前がぶれる)を潰す
- SPEC.md が症状3(頼んでいない機能)を潰す
- ADR が症状1と4(蒸し返しと差し戻し)を潰す
なぜ1つのファイルにまとめないか。 更新の頻度と寿命が違うからです。用語は最初に決めたらほとんど変わりません。仕様は作っている間じゅう変わります。ADRは足すだけで、書いたものを書き換えません。これを1つにすると、いちばんよく変わるものに引きずられて、全体が「たぶん古い」扱いになります。そうなった文書はAIも人間も読まなくなります。
CONTEXT.md — 言葉を1つに決める
用語を定義するだけのファイルです。実物から2語ぶん引きます。
**問**:
段と次回日を持つ最小単位。役割ラベルを持つことがある。
項目の形は3つあり、例題と演習題の対なら2問、ミニ講座のような単体なら1問、
独立した小問がN個ある項目ならN問になる。
_Avoid_: カード、タスク、問題、設問
**項目**:
単元の中の通し番号(1、2、3…)。1つ以上の問を持つ。
_Avoid_: 問題(総称としては使わない)
効いているのは定義より _Avoid_ の方です
定義だけ書いても、AIは類義語を使います。「問」と定義してあっても、変数名は question になり、UIには「カード」と出て、テストには item と書かれます。同じ意味だと分かって使い分けているのではなく、その場ごとに自然な語を選んでいるだけなので、一貫しません。
禁止語を並べておくと、ここが揃います。_Avoid_: カード、タスク、問題、設問 と書いてあれば、question も card も出てきません。私のアプリでは、この1行のおかげで「問」が最後まで problem のまま通りました。
「問題」を避けるのはとくに大事でした。日常語として自然すぎて、書いている本人が総称のつもりで使ってしまいます。人間側の口を縛るためにも要ります。
どの語を書くか
29語あります。書いている最中は「これは当たり前すぎるだろう」と思う語が半分くらいありますが、たいてい後で全部使うことになります。
迷ったら、AIが言い換えそうな言葉から書くのが効率的です。私の場合はこういう語でした。
- 一般的な技術用語に近い日本語(記録・状態・履歴・一覧)
- 日常語としても使える言葉(問題、項目、編集)
- そのドメインでしか通じない言葉(脳内再現、詰まり印、梯子)
3つ目は説明が必要なので誰でも書きますが、危ないのは1つ目と2つ目です。説明しなくても通じてしまう言葉が、いちばんぶれます。
SPEC.md — いちばん効いたのは「作らないもの」
何を作るかだけを書くファイルです。13節あります。範囲・データ構造・登録・梯子と次回日・問の状態・本日分・記録の入力・台帳・使い方とバックアップ・構成、そして残り3つが「作らないもの」「未決」「まだ作っていないもの」です。
書いていちばん効いたのは11節でした。そのまま載せます。
## 11. 作らないもの
意図的に持たない機能。それぞれ理由がADRにある。
- 1日あたりの新規投入数の制御(ADR 0004)
- 通知・リマインド
- 原因タグの単元別集計(ADR 0001)
- ease factor による連続的な間隔調整(ADR 0001)
- 段6を通らない自動の早期卒業(ADR 0001。手動の休止で代替)
- 遅延に対するペナルティ(ADR 0001)
- 次回日のゆらぎ。期限を過ぎた問はやるまで本日分に残り続けるため、特定の日に
山ができても翌日以降へ自然に持ち越される。日付を散らす意味が薄い
- 同じ項目の問を別の日に繰り越す処理(ADR 0002)
- 問題文・解答の保持
9項目あって、そのうち6項目にADRの番号が振ってあります。
「作らない」と書いてあると、提案の段階で止まります。 断る作業がゼロになるのが大きくて、断るには理由を思い出して言葉にする必要があるので、そのたびに何往復か消えます。それが「SPEC 11節に書いてあります」で終わります。
もうひとつ、これは自分が寄り道するのを止める効果の方が大きいかもしれません。統計画面はあった方が良さそうに見えます。1行書いてあるだけで、その気持ちが1秒で片付きます。
理由の無い禁止は破られる
9項目のうち、理由がどこにも書いていないのが2つあります。「通知・リマインド」と「問題文・解答の保持」です。
この2つは、しばらくすると「なんで無いんだっけ」となります。禁止だけ書いて理由を書かないと、書いた本人が先に疑い始めます。 そこで理由が出てこないと、結局その場で考え直すことになって、書いていない状態とあまり変わりません。ADRの番号を振るか、その場に1行だけでも理由を添えるかは、しておいた方がいいです。
「未決」と「まだ作っていないもの」を最後に置く
12節と13節は、今はどちらも「なし」です。作っている最中はここに項目が並びます。
この2つを分けているのは、決まっていないものと、決まっているが手を付けていないものを混ぜないためです。前者は人間が決めないと進みません。後者はAIに投げれば進みます。混ぜると、着手のたびにどちらか判別する会話が発生します。
セッションの頭で「SPEC.mdの13節を見て、次にやることを言って」と投げられる場所があるのは、思っていたより便利でした。
ADR — 却下した案を、理由ごと残す
1つの決定につき1ファイルです。6本あります。実物から引きます。
# 段を持つ最小単位は「問」とする
(前略)
当初は「同じ項目の問を同じ日に出さない」という制約も付けていたが、外した。例題を
解いた直後に演習題をやると連続作業になる、というのが根拠だったが、段が問ごとに
独立に動くため同日に揃うこと自体が稀で、揃うのは両方とも同じ評価が続いた場合、
つまり両方順調な場合に限られる。滅多に起きない場面のために繰り越し処理を常時
抱えるのは割に合わない。
却下した案を、消さずに残しているのがポイントです。 消すと、次のセッションで同じ案が新鮮な顔をして出てきます。しかも同じ根拠(連続作業になるから分けた方がいい)で出てくるので、こちらも同じところで納得しかけます。理由まで書いてあると、そこで止まります。
別のADRには、こういう却下も書いてあります。
## 早期卒業は認めない
段3や段4でSが続いた項目を早期に卒業させる案は却下した。2週間や1か月の間隔で
解けることは、6か月後に解けることを何も保証しない。(中略)
コストとしても割に合う。初回からSが続く項目は 2週間 → 3か月 → 6か月 → 卒業 と
進むため、9か月かかっても実際に触るのは4回だけで、早期卒業させた場合と2回しか
変わらない。
これも定期的に提案される種類の話です。「効率化できます」という形で来ます。
Consequences がいちばん効く
ADRの末尾には、その決定によって引き受けた不便を書きます。ここが書き忘れやすくて、そして書くと効きます。実物です。
## Consequences
登録し忘れた単元を、記録が溜まったあとでも目次どおりの位置に入れられる。
これができないと、間違いに気づいた時点で登録し直すしかなく、記録がある冊では
打つ手が無くなる。
一方で、目次の順序は units 配列の並びと order の2箇所に持つことになった。
編集の関数は必ず両方を揃えて返す。片方だけ書き換える経路を作らないこと。
最後の2行は、判断の記録ではありません。将来この部分を触る人間とAIに向けた申し送りです。 順序を2箇所に持つのは普通に見れば冗長なので、これが書いていないと「片方に寄せましょう」と整理されます。整理された結果として、記録が隣の単元にずれます。
症状4(直したはずの判断が戻っている)に効くのは、この欄です。
全部の決定をADRにしない
6本しかありません。基準は**「なぜそうしなかったのか、3か月後の自分が聞きそうか」**です。
聞きそうなのは、他に妥当な選択肢があった場合だけです。たとえば「復習間隔を離散6段にして、ease factor を使わない」はADRになっています(有名な手法をわざわざ捨てているので)。一方で「日付は日本時間で判定する」はADRにしていません。他の選択肢がないからです。これはSPEC.mdに1行書いてあれば足ります。
どう書かせるか
順番はこうしています。
- 作りたいものを一段落で説明する
- 「作って」ではなく「まず質問して」と言う
- 出てきた質問に答える
- CONTEXT.md を書かせる
- SPEC.md を書かせる
- 判断が割れたところだけ ADR にする
- ここまでコードは1行も書かせない
2が全部です。曖昧な指示に対して、AIは黙って解釈を1つ選びます。選んだこと自体を言わないので、こちらは決めた気になったまま進みます。質問させると、自分でも決めていなかった部分がその場で出てきます。
たとえば、こういう質問が出ます。
1日の区切りは何時ですか?
考えていませんでした。私は寝る前に勉強することが多いので、深夜0時で切られると、日付をまたいだぶんが翌日の学習として記録されます。答えは午前5時でした。これがSPEC.mdの1節になり、date.ts という関数になり、テストになりました。
聞かれなければ、当然のように0時で実装されます。 そして使い始めて数日後に「昨日やった分が今日の欄に入っている」で気づき、そのころには日付を扱うコードが何箇所にも増えています。設計のときに5分で済む話が、あとからだと数時間になります。
質問はまとめて何十個も返ってくることがありますが、ほとんどは即答できます。即答できないものが数個残って、それが本当に決まっていなかったことです。
どこまで効いたか
このやり方で作ったアプリの、現在の状態です。
- SPEC.mdに書いたものは、全部実装されています。 「まだ作っていないもの」の節は空です
- テストが308件(11ファイル)通っています
- 本番で毎日使っています
比較として、前の記事に書いた5つのツールには、この3文書がありません。会話だけで作りました。今も動いていますが、半年後に直そうとすると、なぜその値なのかを思い出すところから始まります。 実際、記事を書くために自分のコードを読み直したとき、コメントに書いてあった数字を見て初めて経緯を思い出した箇所がありました。
文書のコストは、CONTEXT.md が2,822字、SPEC.md が6,083字、ADR 6本で5,256字です。合計14,161字。多く見えますが、書いたのは実装前の数時間で、実装にかかった時間に比べれば誤差です。
効かなかったこと
正直に書きます。
最初から全部は書けません。 ADR 0006(記録はサーバの返事を待たない)は、本番で使い始めてから足したものです。評価ボタンを押してから画面が動くまでの待ちが気になるというのは、毎日使ってみないと出てきません。設計の時点では「保存して画面を更新する」以上のことを思いつきませんでした。文書は書き切るものではなく、足していくものでした。
コードの外側は防げません。 前の記事に書いた5つの壊れ方(排他ロックの粒度、トリガーの増殖、リージョンの既定値、スマホのアイコンキャッシュ、デプロイの意味論)は、この3文書があっても全部踏みます。仕様書に書ける種類の話ではないからです。ADR 0006 にリージョンの話が入っているのは、踏んだあとに書いたからです。
小さいものには過剰です。 30行のGASにCONTEXT.mdは要りません。目安として私は「1回の会話で作り終わらないもの」から書くようにしています。逆に言えば、1回で終わるなら要りません。
書いた数字は、覚えていると間違えます。 この記事を書くために実物を数えたら、用語は29語、SPEC は13節でした。最初の記事には「26語・12節」と書いてあり、公開してから3日間そのままでした。当時のファイルを確認しましたが、その時点でも29語・13節です。自分のメモを見て書いて、実物を数えていませんでした(最初の記事は修正済みです)。文書を書かせる話をしておいて、その文書を数え間違えるのは間抜けですが、ここは仕組みで防ぐしかないところだと思っています。
最後に
3つ書きましたが、1つだけやるなら CONTEXT.md です。
コストがいちばん安く、効果がいちばん早く出ます。そして言葉を決める作業は、コードを書く能力とは別の仕事です。「問」と「項目」を分けると決めたのは、紙のノートで復習台帳をつけていたときに、例題は解けるのに演習題が解けない日があると知っていたからで、プログラミングの知識からは出てきません。
作るものの中身をいちばんよく知っているのは、その業務を毎日やっている人間です。Claude Code に何を渡すかを決めるところは、まだそちら側の仕事として残っています。
ほかに作ったものは 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つではなかった