Context Engineering for AI Coding Assistants
Feeding structured findings to Claude Code, Cursor, and Continue so your AI assistant triages instead of guessing.
When you ask Claude Code to review your codebase cold — no context, just a prompt — it samples non-deterministically and resets on every session. The same code may return different findings on different runs. There is no guaranteed order, no line anchors, and no memory of what the model found last time.
BrassCoders, the scanner that catches what AI assistants structurally miss, solves the statefulness problem by writing the session's starting point to disk before the session begins. The .brass/ai_instructions.yaml file carries every finding from the last scan, sorted by severity, with line numbers and remediation notes. Open Claude Code or Cursor in the same directory and the file is already in context. This page is the reference for that pattern.
The Findings File vs. the Chat Prompt
BrassCoders writes .brass/ai_instructions.yaml after every scan: a severity-sorted work queue with one entry per finding, each carrying a file path, line number, and remediation note. A chat prompt asking Claude Code or Cursor to review the same codebase resets on every session and carries none of those structural properties.
That gap matters most at scale. A 15-file corpus with 53 findings is too many for a single chat session to prioritize reliably; the findings file sorts them by severity before the session opens, so a critical SQL injection appears before a medium-severity style note without any explicit instruction. Fix a finding, re-scan, and it disappears from the file. The chat session has no record of what it found yesterday.
The findings-file post covers what each field in the YAML does, why the structure produces more consistent triage than an open-ended review prompt, and the offline guarantee: the OSS core makes zero outbound network calls by default, so source code never leaves the machine.
How Claude Code Reads the File
Claude Code reads .brass/ai_instructions.yaml severity-first: critical findings before high-severity, high before medium, low last. The line number field anchors each finding to a specific code location; the remediation field states the fix direction before the model reads a single line of source.
The line number matters because it changes where the session starts. Without a line reference, reviewing a 400-line file means reading the whole thing and inferring where something might be wrong. With line 47 in the finding, Claude Code reads a narrow window of roughly 20 lines around that location and decides whether the finding is real. The model reads what matters.
The remediation field adds the third layer. A finding that says "replace with a parameterized query using ? or %s placeholders with a separate values tuple" gives Claude Code a fix direction before it confirms the pattern. It reads the remediation, checks the flagged line, and either generates the fix or dismisses the finding as a false positive. The session starts at implementation. Not discovery.
The how-Claude-Code-reads post covers all three fields with a full YAML example and the one class of finding where the model wins regardless of the pre-pass: bugs that require intent inference, not pattern matching.
Why a Dumb Pre-Pass Makes the Smart Model Better
A 2025 arXiv paper (ZeroFalse, arXiv 2510.02534) fed static-analyzer output to an LLM for adjudication and reported F1 scores of 0.912 and 0.955 on two independent benchmarks. Both numbers exceeded what either the deterministic scanner or the LLM achieved when each ran alone. BrassCoders is built for that pattern: run the deterministic scanner, write the output, let the model handle what only reasoning can resolve.
The mechanism is scope reduction. A deterministic rule handles the structural layer without reasoning or an API call — SQL injection via string formatting, shell=True in a subprocess call, a hardcoded credential. That layer clears in seconds, before the model opens. What remains are the findings that actually need context: is this MD5 call in a deduplication path or a credential-storage path? Does this eval() ever receive user input?
A second 2025 paper (Gnieciak and Szandala, arXiv 2508.04448) compared LLMs directly against static tools and found the LLMs scored higher recall but mislocated findings at the line level and generated more false positives. The recommendation: deterministic scanners for high-assurance verification, LLMs for early broad triage. The pre-pass post covers both papers and what each found.
The YAML-First Pattern Across Editors
BrassCoders writes .brass/ai_instructions.yaml in plain YAML with no proprietary encoding, so any AI assistant that can read a local file can consume it as context. Claude Code picks it up automatically in a project directory. Cursor and Continue users reference it as a context file.
The workflow is the same in all three: scan before opening the session, point the editor at the file, triage what the scanner found. Claude Code is automatic — open it in the project directory and the file is already in context. Cursor users type @file .brass/ai_instructions.yaml in a chat session. Continue users do the same in the chat panel.
One practical note applies to all three: the file doesn't update automatically. Fix a finding and re-run brasscoders --offline scan before opening the next session. The YAML-first pattern post covers the specifics for each editor in detail.
When BrassCoders Flags Something That Isn't a Bug
BrassCoders scanned 15 AI-generated Python files and produced 53 findings; on triage, 9 of 15 files carried a confirmed real issue. The false positives — three performance flags on integer counter increments and one MD5 flag in a deduplication context — were the mechanism that makes triage useful, not a scanner defect.
A scanner that inferred intent and suppressed the MD5 finding based on variable name would also suppress a real credential-hashing bug in a file that happened to share that name. The structural pattern looks identical in both cases. BrassCoders reports the pattern; the triage layer reads context. That division is load-bearing: if the scanner infers wrong, the AI consumer trusts the suppression and the real bug ships.
One case from the published corpus makes the value concrete. In api_client.py, BrassCoders flagged a false performance finding — a counter increment that matched the string-concatenation loop rule — and missed a real O(N²) bug one line above it. Triage dismissed the false positive correctly and, while reading the surrounding code, spotted the real insert(0) pattern the scanner missed. The false positive was the reason the triage session read that code carefully enough to find the real bug.
The false-positive post documents the full N=15 corpus results: every finding, every triage decision, and why the 53-to-9 ratio is a design property rather than a precision problem.
All Context Engineering Posts
- What a Findings File Does That a Chat Prompt Can't — persistent structured state vs. non-deterministic chat review
- How Claude Code Reads a BrassCoders Findings File — severity ordering, line anchoring, and the remediation-field workflow
- Why Your AI Assistant Needs a Dumb Pre-Pass — the research case: arXiv 2510.02534 and arXiv 2508.04448
- Feeding BrassCoders Output to Any AI Coding Assistant — Claude Code auto-pickup, Cursor @file, Continue context provider
- The False Positive Is a Feature, Not a Bug — the N=15 corpus: 53 findings, 9 real issues, and why the ratio is the point
Frequently Asked Questions
What is the .brass/ai_instructions.yaml file?
BrassCoders writes a machine-readable YAML file after every scan containing one entry per finding with the scanner name, severity level, file path, line number, and a short fix-direction note. An AI assistant like Claude Code or Cursor reads this file to prioritize findings rather than inferring code quality from raw source.
Does BrassCoders send my source code anywhere?
No. brasscoders scan runs offline by default — zero bytes leave the machine. The OSS core has no outbound network calls. The BrassCoders Paid plan sends scanner findings (already redacted at source) and a short project signature to the hosted gateway — never raw source code.
How is this different from asking an AI to review my PR directly?
A direct AI review is non-deterministic and stateless: the same code may produce different findings on different runs, and there is no memory of prior findings between sessions. BrassCoders emits a deterministic file that produces identical findings on identical code every time, so the AI assistant triages a stable structured input rather than a re-sampled prompt.
Which AI assistants can read the .brass file?
Any assistant that can read a local file. Claude Code picks it up automatically in a project directory. Cursor users reference it via @file. Continue users configure it through the local file context provider. The YAML format is plain text with no proprietary encoding.
What does BrassCoders add that Claude Code's built-in review doesn't?
Claude Code's built-in review runs when asked and samples non-deterministically. BrassCoders runs before Claude Code opens, on every scan, with identical findings every time. The .brass file tells Claude Code which lines to review and in what order — it focuses the model's reasoning, it does not replace it.
Are false positives a problem with BrassCoders?
BrassCoders reported 53 findings across 15 AI-generated Python files; on triage, 9 of 15 carried a real issue. The false positives — three PERF flags on counter increments, one MD5 flag in a dedupe context — were the reason triage exists. A scanner that guessed at context and suppressed those flags would also suppress the real findings it couldn't distinguish from them.