console.logをやめた。AI前提のログ設計に変えた話
React開発をClaude Codeでやっていて、地味に面倒なのがブラウザのconsole確認。
DevToolsを見る → 必要なログをClaudeにコピペ これが無駄に感じた。
ViteのforwardConsoleという選択肢
server: {
forwardConsole: {
unhandledErrors: true,
logLevels: ['error', 'warn', 'log'],
},
}
これでブラウザのconsoleがターミナルに出るので、Claude Codeと相性はいい。
ただし問題がある。ログが全部流れる。
[vite] hmr update /src/App.tsx
[vite] connecting...
Download the React DevTools for a better development experience
[HMR] connected.
実際のアプリのログがこの中に埋もれる。grepで探すのも、AIに読ませるのもしんどい。
自分用logger + ログサーバにした
結論、こうした。
- console.logは使わない
- Claudeに見せたいログだけ送る
- logger経由でログサーバにPOST
構成はシンプル。
[ ブラウザ ]
│ logger.debug(event, payload)
▼
[ ログサーバ ]
│ ログファイル
▼
[ Claude Code ] ← ファイルを読む
呼び出し側はこれだけ。
logger.debug('USER_LIST', {
count: users.length,
users,
})
フォーマット設計:AIが読める形にする
ログ設計の1軸目はフォーマット。
logger.debug('API_RESPONSE_USER_LIST', {
url: '/api/users',
status: 200,
count: users.length,
})
- 何のログか(イベント名)
- どの処理か(URL・関数)
- 成功/失敗(status・errorフィールド)
このルールを固定すると、AIは過去のログと同じ粒度で新しいログを書けるようになる。
運用フロー:出力も受信もAIに任せる
ログ設計の2軸目は役割分担。フォーマットが固まると、ログを取り巻く作業を全部AIに渡せる。
- 出力側:どこに何のログを仕込むか → AIが書く
- 受信側:ログを読んで何が起きたか判断する → AIが読む
両方をAIに渡すと、デバッグのループが自動で回る。
バグ発生 → AIがログを追加 → 再現 → AIがログを読む → AIが原因特定 → AIが修正
人間は「壊れた」と伝えるだけになる。
使い分け
| 方法 | 用途 |
|---|---|
| forwardConsole | エラー確認 |
| console.log | 一時デバッグ |
| custom logger | Claude用ログ(本命) |
MCP化も検討したが、やめた
ログサーバをMCPサーバにする案も一瞬考えた。Claudeが構造化クエリでログを引ける、というやつ。
結論、オーバーエンジニアリングだと判断してやめた。
- ブラウザはMCPを直接叩けない。送る側はどのみちHTTPエンドポイントが要るので、MCPはログサーバの「上」に乗る形になる。層が増えるだけで、解いている問題は変わらない。
- ファイルが一番汎用的。
tail、grep、別のAI、人間のレビュー、全部が同じファイルを読める。MCPにするとClaude Code専用の入口になる。
シンプルにファイルが置いてあるだけの構成のほうが、結局いろいろ繋ぎやすい。
入れてみて変わったこと
- DevToolsを見てClaudeにコピペする作業がゼロになった
- 「バグ直して」と投げると、ログ追加 → 再現 → 修正までAIが進める
- 自分は仕様判断と最終レビューだけやればいい
ログ設計を変えたというより、デバッグの主語がAIに移った感覚に近い。
まとめ
- forwardConsoleは便利だけどノイズが多い
- Claude Code前提ならログは設計する
- 「全部出す」より「見せたいものだけ出す」
- フォーマットを固定すれば、出力も受信もAIに任せられる
ログは人間だけじゃなく、AIに読ませるもの。それを前提にすると、設計の答えが変わる。