# Onboarding Developers to AI-Assisted Workflows With Security Built In

> Source: <https://dev.to/coppersundev/onboarding-developers-to-ai-assisted-workflows-with-security-built-in-3p3p>
> Published: 2026-07-22 17:14:04+00:00

Most security tooling gets bolted on after the first incident. A new hire joins, writes a few AI-assisted PRs, and three months later someone notices a hardcoded key in the commit history.

BrassCoders, the scanner that catches what AI assistants structurally miss, changes that timeline. The three-step baseline — install, pre-commit hook, CI gate — can be in place before a new developer pushes their first commit. From that point forward, every developer on the team works with the same scanner, the same output format, and the same noise level. Day one and day one hundred look identical.

BrassCoders integrates into a new developer's environment through three distinct checkpoints: a local CLI install, a pre-commit hook that runs before code leaves the machine, and a CI gate that catches anything that slips through. Each layer is independent — you can adopt all three or start with one — but together they create a security baseline that new developers inherit automatically.

The YAML output format is identical at every layer. A finding that shows up in a local scan looks exactly the same in the pre-commit hook output and in the CI job log. There's no translation step, no different severity scale per layer, and no findings that only appear in CI.

BrassCoders ships on PyPI as `brasscoders`

and requires Python 3.10 or later. The install is a single command.

```
pip install brasscoders
```

macOS ships with Python 3.9 as the system default on many machines. Verify your version before installing:

```
python3 --version
```

If it reports 3.9 or below, use your actual 3.10+ executable explicitly:

```
python3.12 -m pip install brasscoders
```

For team consistency, pin this in a `requirements-dev.txt`

or add `brasscoders>=2.0.10`

to your dev dependencies in `pyproject.toml`

. Every developer gets the same version. Onboarding becomes a `pip install -r requirements-dev.txt`

and nothing else.

Once installed, run a scan against any Python project:

```
brasscoders scan /path/to/project
```

The default scan makes zero outbound network calls. No API key, no account, no telemetry. Apache 2.0 licensed. The `--offline`

flag makes that explicit if you want it spelled out in CI scripts.

BrassCoders plugs into the pre-commit framework — a tool used by Python projects everywhere to enforce linting, formatting, and import sorting before code reaches version control. Adding BrassCoders follows the same pattern as any other pre-commit hook: one entry in `.pre-commit-config.yaml`

.

The pre-commit framework lives at [pre-commit.com](https://pre-commit.com). The full BrassCoders setup is documented in the [pre-commit hook guide](https://coppersun.dev/blog/pre-commit-hook-ai-coder-bugs/). The short version: add BrassCoders to your `.pre-commit-config.yaml`

, run `pre-commit install`

, and every `git commit`

from that point forward runs the scanner against staged changes.

```
repos:
  - repo: local
    hooks:
      - id: brasscoders
        name: BrassCoders security scan
        entry: brasscoders scan
        language: system
        types: [python]
        pass_filenames: false
```

What this gives a new developer: their first `git commit`

runs the scanner. Not when they open a PR. Not when the CI job fires. Before the code leaves their machine. If they're writing AI-assisted code and a phantom API call or a hardcoded secret slips in, they see it in their terminal at commit time — while the context is still fresh.

Pre-commit hooks are local by default. Each developer installs them once per clone with `pre-commit install`

. Include that step in your onboarding docs.

BrassCoders runs as a CI step that catches what the pre-commit hook missed — developers who skipped hook installation, branches created before the hook existed, or direct pushes that bypassed the hook entirely. The CI gate is the backstop.

BrassCoders runs cleanly in any CI environment that has Python 3.10+. The full integration instructions are available for [GitHub Actions](https://coppersun.dev/blog/add-brasscoders-to-github-actions/) and [GitLab CI](https://coppersun.dev/blog/add-brasscoders-to-gitlab-ci/). Both integrations follow the same pattern: install the CLI, run `brasscoders scan`

, fail on findings above a severity threshold.

GitHub Actions snippet:

```
- name: Install BrassCoders
  run: pip install brasscoders

- name: Run BrassCoders scan
  run: brasscoders scan . --offline
```

GitHub Actions documentation describes the `pip install`

step as a standard setup action in Python workflows — the same `setup-python`

+ `pip install`

pattern used in Python CI applies here without modification.

The CI scan and the local scan produce the same YAML. A developer who saw a finding in the pre-commit hook will recognize the same finding format in the CI log. That consistency matters: they already know how to read it.

BrassCoders runs 12 static-analysis scanners against every scan and emits a single unified YAML report. A new developer sees the same scanner coverage as a veteran — no configuration required, no onboarding-specific mode.

Six upstream scanners handle the foundation: Bandit, Pylint, Pyre/Pysa, Semgrep, ast-grep, and detect-secrets.

Six custom detectors extend coverage to secrets, PII, phantom-API calls, performance, content moderation, and JS/TS.

A new developer clones the repo and runs `pre-commit install`

after the dev dependency install. Their first `git commit`

triggers the scanner immediately. The output is a YAML block: each finding names the file, line, scanner, and severity level, plus a `how_to_read_this_file`

guide at the top that explains the format for both human readers and AI assistants.

That last part is the point. The YAML output is structured for Claude Code or Cursor to read directly. The new developer pastes the finding into their AI assistant's context window, and the assistant explains whether the finding is a real bug, a false positive, and how to fix it. BrassCoders generates the report. The AI assistant handles the triage. Neither job bleeds into the other.

A developer who joins the team on day 100 sees the same output as a developer who joined on day one. The format doesn't change as the product evolves; the scanner doesn't add a new scoring system each sprint; the YAML structure is versioned and stable.

BrassCoders releases scanner updates to PyPI as new AI coding patterns emerge. AI assistants introduce new phantom-API patterns and new secret formats arrive as SaaS vendors add key prefixes — the threat model shifts faster than a static scanner install can track.

Keeping the version pinned in `requirements-dev.txt`

and updating it on a regular cycle (monthly works for most teams) pulls in new scanner patterns without requiring any configuration changes. The output format stays compatible across minor versions — findings from an older version look structurally identical to findings from a newer one.

The [team consistency post](https://coppersun.dev/blog/vibe-coding-team-consistency/) covers the argument for a shared scanner version across a team in more depth. The short version: drift between developer scanner versions means different developers see different findings. One developer's pre-commit hook passes a finding; another developer's doesn't. The CI gate catches the difference, but it's better to surface it locally. Pin the version.

```
pip install brasscoders
brasscoders scan .
```

That's the starting point. Add the pre-commit hook before the first PR. Add the CI gate before the first merge to main. The baseline is in place before a new developer has had a chance to ship a finding.

Apache 2.0, zero outbound calls in OSS mode, Python 3.10+. No account required to start.
