DEV Community

CopperSunDev
CopperSunDev

Posted on • Originally published at coppersun.dev

What a Findings File Does That a Chat Prompt Can't

BrassCoders writes .brass/ai_instructions.yaml after every scan — a file your AI assistant reads instead of guessing at your codebase from scratch. Each finding entry carries its severity level, file path, line number, and a remediation note. A chat prompt asking Claude Code or Cursor to review the same codebase carries none of those properties: no persistent state, no line anchors, no format the tool knows to expect.

That gap is the whole reason the findings file exists.

What the .brass File Actually Contains

BrassCoders emits a .brass/ai_instructions.yaml file in the scanned project directory; each finding entry lists an id, severity (critical, high, medium, low, or info), file path, line number, and a remediation field describing the fix direction. The file sorts findings by severity before writing them, so critical-severity entries appear first regardless of which file they came from.

A representative finding looks like this:

issues:
  - id: bandit-B608-001
    severity: critical
    file_path: api/views.py
    line_number: 47
    title: SQL Injection via String Formatting
    description: Query string assembled with % operator interpolating user input.
    remediation: Replace with a parameterized query using ? or %s placeholders
      with a separate values tuple passed to cursor.execute().
Enter fullscreen mode Exit fullscreen mode

The AI assistant in your editor reads this as a work queue. Severity gives it the review order. File path and line number anchor it to source. The remediation field gives it a fix direction before it reads a single line of code.

Why a Chat Prompt Resets

BrassCoders' findings file persists on disk between scans and shrinks only when a finding gets fixed and you run the scan again; a chat-based code review session starts blank every time.

On a new chat session in Claude Code or Cursor, the AI assistant has no memory of what it found yesterday. You re-describe the codebase, re-state the context, and re-specify what to look for. The findings may come back in a different order, named differently, or missing entirely if the model samples differently this time. A findings file rewrites those variables to constants: the file says what was found, and the AI assistant's job is to confirm it and fix it.

This matters more at scale. A codebase with 500 Python files across a dozen modules produces too many possible findings for a chat prompt to reason about reliably. The 53 findings BrassCoders surfaced across 15 AI-generated files in its published corpus don't need to be described; they're already in the file, sorted, with line numbers, waiting to be triaged.

What an AI Assistant Does with the File

BrassCoders sorts findings severity-first before writing the file, so a critical SQL injection appears at the top above a medium-severity style note; Claude Code reads this ordering and triages the highest-severity findings first without needing a separate instruction to do so.

Beyond ordering, the line number changes how the AI assistant pulls source context. Without a line reference, the model has to read an entire file and infer where something might be wrong. With a line number, it jumps directly to the flagged location, reads a narrow code window around it, and decides whether the finding is real. That's the brass-vs-Claude division of labor in practice: BrassCoders identifies the line; Claude Code judges the context.

The remediation field adds one more layer. A finding that says "Replace with a parameterized query using ? or %s placeholders with a separate values tuple" gives the AI assistant a concrete fix direction. It doesn't have to discover the correct pattern from first principles. It reads the remediation, checks the flagged line, and either generates the fix or dismisses the finding as a false positive. The conversation starts at confirmation, not discovery.

The Offline Guarantee

BrassCoders' open-source core runs with brasscoders --offline scan and sends zero bytes off the machine; the findings file is written locally, read locally, and never transmitted unless you run the Paid-plan enrichment pass.

An AI reviewer sends your source to an external API on every invocation. For any codebase under data-handling rules — internal tooling, financial records, healthcare data, any code your security policy would flag — the offline path is the one that can run on every commit without a policy exception. The findings file captures what matters without source leaving the machine.

GitHub's own guidance for reviewing AI-generated code tells developers to "always run automated tests and static analysis tools first" and to run a code scanner before layering a model review on top. BrassCoders is the scanner that runs first, offline, on every push. The AI reviewer is what you layer on top.

Wiring It Into Your Workflow

BrassCoders writes the findings file with one command: brasscoders --offline scan /path/to/project. The scan runs 12 static-analysis scanners across your Python codebase and writes .brass/ai_instructions.yaml in the project directory. Open Claude Code or Cursor in the same directory and the file is available as project context.

The workflow: scan before you open the editor. Review the AI assistant's triage of the high-severity findings. Fix what's real. Re-scan to confirm the finding is gone. Each scan runs in seconds on most Python codebases. The findings file replaces the "describe the problem" part of a code-review chat with a structured artifact the assistant already knows how to read.

pip install brasscoders
brasscoders --offline scan /path/to/your/project
Enter fullscreen mode Exit fullscreen mode

Top comments (0)