SLOPSHOPPER

diagnostics

Caps the language server's new-diagnostics attachment before the model reads it

newprompt
v0.1.0no licenseupdated 2026-10-14djavrell/dotfile/claude/mods/diagnostics
A shopper browsing a rack in a slop shop
README

diagnostics

Cuts the language server's list of new errors down before the model reads it. A TypeScript error on a typera/zod route spells out the whole inferred type: one list of 5 errors reached 5.6M chars, more than the context window.

Each line keeps its head (file, line, error code, start of the message) and loses the rest past 400 chars; the whole list stops at 20k chars. The display does not change: Claude Code already shows that list as one line (ctrl+o unrolls it).

Example

  ✘ [Line 339:60] Argument of type '(request: RequestFor<"/configurations/:configurationId", ZodObject<…… [+2822633 chars]
Source 2 files
hooks/register.ts 9 lines
1import type { Register } from 'claude-code'
2
3import { capDiagnostics } from './cap'
4
5// the engine keeps a hook's answer per attachment for the process: each list is cut once, history included
6export const register: Register = on => {
7  on('prompt.attachment', { type: 'diagnostics' }, async (_, event, next) => next({ ...event, text: capDiagnostics(event.text) }))
8}
9
hooks/cap.ts 15 lines
1// a TypeScript error on a typera/zod route spells out the whole inferred type: one message reached 2.8M chars (six-942)
2export const MAX_LINE_CHARS = 400
3export const MAX_TOTAL_CHARS = 20_000
4
5// keeps every line's head (file, line, code, the start of the message) and drops the spelled-out types
6export const capDiagnostics = (text: string) => {
7  const lines = text
8    .split('\n')
9    .map(line => (line.length > MAX_LINE_CHARS ? `${line.slice(0, MAX_LINE_CHARS)}… [+${line.length - MAX_LINE_CHARS} chars]` : line))
10  const capped = lines.join('\n')
11  return capped.length > MAX_TOTAL_CHARS
12    ? `${capped.slice(0, MAX_TOTAL_CHARS)}\n… [diagnostics cut: +${capped.length - MAX_TOTAL_CHARS} chars]`
13    : capped
14}
15