コードの最も良い説明はチャットログに埋もれている

あなたはClaudeと45分かけてリトライ回路を設計しました。失敗モードを説明し、カスケード圧力を隠してしまうため指数関数的バックオフを却下し、jitter付きtoken-bucket rate limitingで決着し、動作する実装を生成しました。説明は明快で、推論は妥当であり、コードは実際にテストをパスしました。

そしてタブを閉じました。

2週間後、同僚が「なぜリトライロジックは指数関数的バックオフではなくjitterを使うのか」と尋ねます。あなたは新しいClaudeセッションを開き、記憶から議論を再構築します。新しい説明は似ているが同一ではありません。あなたは2つ目の、わずかに異なる口伝を生み出しました。どちらも検索では見つかりません。どちらもpull requestでレビューできません。どちらもあなたが会社を去れば消えてしまいます。

これはツールの問題ではありません。カテゴリの誤りです。私たちはLLMの対話をプライベートなスクラッチパッドとして扱っていますが、それは実際にはほとんどのエンジニアがliterate programmingに最も近づいたものなのです。

Knuthの意図と、なぜLLMが偶然それを実現したのか

Donald Knuthは1984年にliterate programmingを、文学作品としてプログラムを書く行為と定義しました。コードとドキュメントは単一のナラティブの中で織り交ぜられます。読者は著者の推論に従い、検討された代替案を見て、なぜ最終的な形が存在するのかを理解します。

40年間、literate programmingはニッチな実践のままでした。WEBやCWEBのようなツールは規律を必要としました。ほとんどの開発者はコードを1つのファイルに、ドキュメントを別のファイルに書き、両者はすぐに乖離しました。

LLMの対話は偶然の産物としてのliterate programmingです。あなたは散文で問題を述べます。モデルは明確化の質問をします。あなたはconstraintsを洗練させます。モデルはコードを提案します。あなたは提案を却下し、理由を説明します。モデルは修正します。最終的な成果物はコードブロックだけではありません。却下されたアプローチ、トレードオフ、ドメインの仮定を含めた、スレッド全体なのです。

問題は、メディアが短命であることです。チャットインターフェースはタスク完了のために設計されており、知識の保存のためではありません。セッションが終わると、ナラティブは琥珀の中に閉じ込められ、検索不可能で、バージョン管理されず、ベンダーに所有されます。

なぜチャットログは複雑な意思決定において従来のドキュメントを上回るのか

従来のドキュメントは最終状態を記述します。「何を」答えます。良いチャットログは「なぜ」答えます。これはより困難な問いであり、最も早く陳腐化するものです。

典型的なarchitecture decision recordを考えてみましょう。「在庫サービスでは強い一貫性要件のため、DynamoDBではなくPostgreSQLを選んだ」と書かれているかもしれません。それは結論です。どのクエリが遅すぎたのか、どのレプリケーションラグが許容可能だったのか、議論されて却下されたvendor lock-inについては何も教えてくれません。

Claudeのスレッドはそれらすべてを含んでいます。失敗したスキーマの反復、驚かされたクエリプラン、複合インデックスがステータスフィルターをカバーしなければならないと気づいた瞬間がそこにあります。それは完全な文脈を持つdecision recordです。

問題は、その文脈が対話形式に閉じ込められていることです。100ターンのスレッドをスクロールして、インデックス設計についての1つの洞察を見つけるのは苦痛です。知識はそこにありますが、アクセス可能ではありません。

Chat-as-Docsの3つの失敗モード

生のチャットログをドキュメントとして扱うことは、予測可能な形で失敗します。各失敗モードには修正策がありますが、意図的でなければなりません。

Hallucination drift。 ClaudeはAPIをでっち上げ、存在しない論文を引用し、実際のconstraintsを無視した設計を自信満々に提案します。ドキュメントとして保存されたチャットログは、知恵とともにhallucinationsも保存します。どの部分が検証され、どの部分が推測的であったかをマークしなければ、次の読者はすべてを福音として扱います。

Narrative sprawl。 良い対話は蛇行します。行き止まりを探索し、エッジケースに気を取られ、引き返します。その蛇行は理解にとって価値がありますが、参照には最悪です。リトライポリシーを必要とする新しいエンジニアは、TCP congestion controlへの20分の脱線を読む必要はありません。

Vendor lock-in。 あなたのドキュメントはAnthropicのデータベースの中にあり、彼らの検索インターフェースの背後にあり、彼らの保持ポリシーに従っています。アカウントが期限切れになったりインターフェースが変更されたりすると、あなたのドキュメントは消えます。grepできないドキュメントはドキュメントではありません。

短命なチャットから永続的なドキュメントを抽出する方法

解決策は、チャットを最終成果物ではなく、第一稿として扱うことです。抽出し、検証し、公開します。ワークフローはシンプルで、重要な決定ごとに約10分かかります。

ステップ1:ターンにタグを付ける。 対話中に重要な決定に印をつけます。私は単純な規約を使っています。Claudeが保持するつもりのコードブロックを生成したとき、KEEP: <1行の理由>と返信します。却下する提案があったときはREJECT: <理由>と返信します。これらのタグによって抽出は些細な作業になります。

ステップ2:Markdownに抽出する。 セッション後、スレッドをMarkdownファイルにコピーしてノイズを取り除きます。挨拶、「考えさせて」という埋め言葉、両方が混乱していたターンを削除します。問題文、検討された代替案、最終決定、検証済みのコードを保持します。結果はトランスクリプトではなく、技術的ノートとして読めるべきです。

Claude APIを使用している場合や、対話をJSONとしてエクスポートしている場合に、抽出を自動化するスクリプトは以下の通りです。

#!/usr/bin/env python3
"""
Extract a readable technical note from a Claude conversation export.
Expects Anthropic's conversation JSON format.
"""

import json
import argparse
from pathlib import Path


def extract_note(conversation_path: Path, output_path: Path) -> None:
    with open(conversation_path) as f:
        data = json.load(f)

    turns = data.get("chat_messages", [])
    lines = []

    for turn in turns:
        sender = turn.get("sender", "unknown")
        text = turn.get("text", "").strip()

        if not text:
            continue

        # Skip pleasantries and meta-turns
        if any(phrase in text.lower() for phrase in [
            "hello", "how can i help", "you're welcome", "glad i could help"
        ]):
            continue

        if sender == "human":
            lines.append(f"**Q:** {text}\n")
        else:
            lines.append(f"**A:** {text}\n")

    with open(output_path, "w") as f:
        f.write("# Technical Note: Extracted from Claude Session\n\n")
        f.write("\n".join(lines))


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--input", type=Path, required=True)
    parser.add_argument("--output", type=Path, required=True)
    args = parser.parse_args()
    extract_note(args.input, args.output)

ステップ3:すべてのコードブロックを検証する。 抽出したコードを実行します。コンパイルできない、またはテストにパスしない場合は、Markdown内で修正し、修正を記録します。抽出されたドキュメントは、間違いを含んでいたかもしれない対話のトランスクリプトではなく、信頼できる情報源でなければなりません。

ステップ4:リポジトリにコミットする。 Markdownを、それが記述するコードの隣のdocs/decisions/またはdocs/notes/に保存します。意味のあるファイル名を付けます:retry-circuit-jitter-over-exponential.mdであって、claude-chat-july-19.mdではありません。コード変更と同じpull requestに追加するか、すぐにフォローアップPRを開いてください。ドキュメントがバージョン管理に入っていなければ、それは存在しません。

これが機能する場合と機能しない場合

このアプローチは、推論が結果と同じくらい重要な、複雑で曖昧な決定において優れています。回路設計、スキーマ移行戦略、API versioningポリシー、パフォーマンスのトレードオフはすべて良い候補です。

参照ドキュメントには機能しません。内部APIで認証する方法についてのチャットログは、構造化されたOpenAPI specとcURL例の代替にはなりません。仕事には適切なツールを使ってください。

また、キュレーションなしでは機能しません。生のチャットログをwikiにダンプすることはドキュメントではありません。それは溜め込みです。10分の抽出と編集は譲れません。それを省略すると、検索可能なゴミを生み出すことになります。

実用的な出発点

新しいツールは必要ありません。習慣が必要です。

次に、些細でない設計判断についてClaudeと長く生産的なセッションをしたときは、タブを閉じる前にスレッドをエクスポートしてください。3つの問いに答えるMarkdownノートに編集するのに10分かけてください:どんな問題を解決していたのか?どんな代替案を検討して却下したのか?何に決着し、なぜか?

そのノートをリポジトリにコミットしてください。それが記述する関数の上のコードコメントからリンクしてください。そのコードに触れる次のエンジニアは感謝し、あなたの推論を再構築するためにClaudeを開く必要はありません。

Claudeとのチャットはドキュメントになりえます。それは、コードのように扱う必要があるだけです:抽出され、検証され、バージョン管理され、保守される。