I gave up console.log: redesigning frontend logs for AI
React development with Claude Code has one quietly annoying chore — checking the browser console.
Open DevTools → copy the relevant logs into Claude. That round trip started feeling like wasted effort.
Vite’s forwardConsole as an option
server: {
forwardConsole: {
unhandledErrors: true,
logLevels: ['error', 'warn', 'log'],
},
}
This pipes the browser console into the terminal, which pairs nicely with Claude Code.
But there’s a catch. Every log gets through.
[vite] hmr update /src/App.tsx
[vite] connecting...
Download the React DevTools for a better development experience
[HMR] connected.
Actual application logs get buried in this noise. Grepping is painful, and feeding it to AI is worse.
My own logger plus a log server
So I went with this:
- Drop console.log
- Only send the logs I want Claude to see
- Push them through the logger to a log server
The architecture is simple.
[ Browser ]
│ logger.debug(event, payload)
▼
[ Log Server ]
│ log file
▼
[ Claude Code ] ← reads the file
The call site is just this:
logger.debug('USER_LIST', {
count: users.length,
users,
})
Format design: shape logs so AI can read them
The first axis of log design is format.
logger.debug('API_RESPONSE_USER_LIST', {
url: '/api/users',
status: 200,
count: users.length,
})
- What kind of log it is (event name)
- Which operation (URL or function)
- Success or failure (status, error fields)
Once the rule is fixed, AI writes new logs at the same granularity as the existing ones.
Operation flow: hand both sides to AI
The second axis is role allocation. Once the format is fixed, the work surrounding logs can be handed to AI.
- Output side — where and what to log → AI writes it
- Receiving side — read the logs and judge what happened → AI reads it
Hand both sides to AI, and the debugging loop runs on its own.
Bug occurs → AI adds logs → reproduce → AI reads logs → AI finds the cause → AI fixes
The human just says “it’s broken.”
Where each tool fits
| Method | Use case |
|---|---|
| forwardConsole | Error checking |
| console.log | Throwaway debugging |
| custom logger | Logs for Claude (main) |
Considered MCP, dropped it
I briefly thought about turning the log server into an MCP server — letting Claude pull logs through structured queries.
I decided it was overengineering and dropped it.
- The browser can’t call MCP directly. The send side still needs an HTTP endpoint, so MCP would sit on top of the log server, not replace it. One more layer, same problem being solved.
- A file is the most universal interface.
tail,grep, other AIs, human review — everyone reads the same file. MCP locks the entry point to Claude Code.
A plain file sitting on disk plugs into more things than a custom protocol does.
What changed after introducing it
- Copy-pasting from DevTools to Claude went to zero
- Throw “fix this bug,” and AI walks the loop: add logs → reproduce → fix
- I only judge spec questions and do the final review
It is less like changing log design, more like handing the subject of debugging over to AI.
Summary
- forwardConsole is convenient but noisy
- If Claude Code is the premise, logs need to be designed
- “Show only what matters” beats “show everything”
- Once the format is fixed, both output and reception can be handed to AI
Logs aren’t just for humans anymore — they’re for AI to read. That premise changes what good design looks like.