Open-source scanner, CI wrappers and Infra Pack
Last updated 7 November 2026
For engineers who want the scanner on their own machine or in their own pipeline, and for anyone who wants to read the code before trusting it. At the end you will have run a first scan, know what the lock and baseline files do, and know where each tool's own reference lives.
Everything here is Apache-2.0, free and works without a Spellwarden account. The hosted product runs the same engine; connecting a pipeline to an organisation is a separate step described in Scan in CI with GitHub or GitLab. This page summarises the tools and links each repository's README, which is the reference for every option.
Plans: Free
The scanner (Apache-2.0, 1.9.1)
The scanner is the open-source engine of the hosted product, version 1.9.1. It finds the agent content in a repository, runs its 65 rules on your machine or CI runner and writes the reports. The code is at github.com/spellwarden-ai/spellwarden, and the rules are listed with their severities in Scanner rules.
Install
The scanner needs Python 3.11 or newer. The quickest way is to run it without installing it:
pipx run spellwarden scan .Or install it with pip install spellwarden and run spellwarden scan .. For a pipeline there are three more ways: the GitHub Action and the GitLab component described below, and, anywhere else, a pinned release or the container image:
pipx run spellwarden==1.9.1 scan
ghcr.io/spellwarden-ai/spellwarden:1.9.1Every part of a release is signed, and the README's "Verifying what you run" section shows the checks for the package files, the image, the Action and component tags and the release manifest. The image's signature, for example, is checked with cosign 3.0 or later:
cosign verify ghcr.io/spellwarden-ai/spellwarden:1.9.1 \
--certificate-identity https://github.com/spellwarden-ai/spellwarden/.github/workflows/release.yml@refs/tags/v1.9.1 \
--certificate-oidc-issuer https://token.actions.githubusercontent.comA first scan
Run spellwarden scan . in a repository. The scanner reads skills, MCP client configuration, Claude Code settings and hooks, plugin marketplaces and A2A agent cards, and prints each finding with its rule, severity, file and line. Inside a git work tree it reads what git tracks plus untracked files that are not ignored; everything it reads is treated as hostile input.
The exit code is what a pipeline acts on: 0 for a pass, 1 when a finding at or above the --fail-on level (high by default) is not accepted, 2 when the scan was incomplete or invalid, and 3 when --locked finds the lock file absent or out of date. An incomplete scan never looks like a pass.
Output formats
Give --format once for each report you want, each with its own --output. The reports are byte-identical for the same files, settings and date.
| Format | For |
|---|---|
text | A terminal (the default). |
json | Tools; the shape is the report schema in the scanner repository. |
sarif | SARIF 2.1.0, for GitHub code scanning. Accepted findings appear as suppressions. |
markdown | The job summary and the pull or merge request comment. |
gitlab-codequality | The GitLab Code Quality report. |
The lock file
spellwarden lock records a hash of every configuration file, MCP server, plugin source and skill the scanner found, in .spellwarden/lock.json. With the file committed, spellwarden scan --locked fails when any of them was added, removed or changed, and names each item, so a change to agent content becomes a visible, reviewed change. The lock holds no scanner version, so upgrading the scanner never makes it stale.
The baseline file
The baseline file .spellwarden/baseline.yml is how a team accepts a finding it has judged: a false positive, or a risk it takes on knowingly. An entry accepts one finding by its fingerprint, from the day it was added to its expiry date, and needs a reason:
version: 1
accepted:
- fingerprint: 9c1d... # 64 hex characters, from the report
rule: SW-SKL-009
path: .claude/skills/deploy/scripts/setup.sh
reason: Installed from our internal mirror, which pins versions.
added: 2026-12-01
expires: 2027-01-31- An entry may last at most 365 days, and at most 30 days for a rule that indicates malicious intent. An invalid entry accepts nothing and fails the scan; an expired one stops accepting, and the report names it.
- Accepted findings stay in every report, marked as accepted with their reason. Nothing is hidden.
spellwarden baseline addadds entries from the command line (--allaccepts every current finding for 90 days by default),baseline listshows each entry's state andbaseline pruneremoves entries that no longer match anything.- On a pull or merge request the scanner reads the baseline and the settings file from the base revision, never from the request itself, so a request cannot accept its own finding. To accept a finding a request introduces, merge the baseline entry first, in a request of its own.
The settings file .spellwarden/config.yml holds the other choices: globs to include or exclude, the default fail level, whether to probe and whether to send the usage ping.
The MCP probe
By default the scanner never opens a connection to a server in your configuration. With --probe it sends the unauthenticated probe of the hosted product to each remote MCP server whose URL is HTTPS, from your machine or runner, and adds the MCP rules' findings and the migration checklist for the 2026-07-28 specification to the report. It sends the URL and the protocol's own requests only: never a header, environment value or argument from your configuration, and never an authorization header or a cookie. Probing is switched off on a pull request from a fork or from Dependabot. Moving MCP servers to the 2026-07-28 specification explains what the checklist asks for.
Connected mode
Connected mode links a run to a Spellwarden organisation, so that its CI policy decides the rules and the results reach the dashboard; it is set up through the wrappers below and described in Scan in CI with GitHub or GitLab.
The usage ping
In CI, and only in CI, each scan sends one small, pseudonymous request that lets Spellwarden count how many organisations run the free scanner: the schema number, the scanner and rules versions, the CI kind, a hash of the installation identity and whether the run checked an agent card. No file, path, finding or repository name is sent, and a local run sends nothing. Switch it off with --no-telemetry, the DO_NOT_TRACK=1 environment variable, or telemetry: false in the settings file. The README lists the fields and how long they are kept.
The GitHub Action and the GitLab component
Both wrap the same scanner and are released at the same version number as it. They add what a pipeline needs: code scanning alerts and a comment kept up to date on each pull request for the Action, GitLab Code Quality for the component, and the job summary. The check fails at the severity you choose. Connecting them to an organisation, with a CI connection that stores no secret in the repository, is covered in Scan in CI with GitHub or GitLab.
GitHub Actions
Pin the Action by the commit of a release tag and keep the version in a comment. The workflow, not the Action, grants the permissions it needs:
on: [pull_request]
permissions:
contents: read
security-events: write # code scanning alerts
pull-requests: write # the pull request comment
jobs:
spellwarden:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@<commit>
- uses: spellwarden-ai/scan@<commit of v1.9.1> # v1.9.1The inputs include path, fail-on, locked, probe and, for connected mode, org. On a pull request the settings and the baseline come from the base commit, so keep the checkout's default persisted credentials or set fetch-depth: 0. Inputs, outputs and the behaviour on forks and Dependabot pull requests are in the Action's README.
GitLab CI/CD
The component adds a scan job for merge request pipelines and one for the default branch:
include:
- component: gitlab.com/spellwarden-ai/scan/scan@1.9.1Your project needs merge request pipelines. The merge request job clones with GIT_DEPTH: "0" so that the settings and the baseline can be read from the merge base. The default-branch job fails only on an incomplete scan, so the pipeline stays green and still records the report that merge requests are compared with. The component's README lists its inputs and the merge request comment.
spellwarden otel normalise
Spellwarden's hosted product keeps only an allow-list of fields from the OpenTelemetry traces and logs that agents and gateways send it. The code that decides what is kept is in the scanner package, and the same code runs on your machine:
spellwarden otel normalise PATH --signal traces|logs [--encoding auto|protobuf|json] [--content] [--max-records N] [--max-bytes N]The command reads one file, an OTLP/HTTP request body as your exporter would send it, and prints as JSON every record Spellwarden would keep and the counts of what it would ignore. It opens no network connection and needs no key, so you can check what leaves your systems before you send anything. --content also prints the content that Spellwarden stores only when an owner of an organisation turns content storage on. The command exits with 0, or with 2 on a usage error or a body it refuses. Runtime traces and sessions describes sending traces and what the hosted product shows from them.
Infra Pack
Infra Pack is five Claude Code skills for infrastructure work, packaged as a plugin marketplace, free and Apache-2.0. Its skills cover reviewing any infrastructure change before acting (infra-change-safety), reading a Terraform or OpenTofu plan (terraform-plan-review), triage of a Kubernetes problem (kubernetes-incident-triage), least-privilege review of AWS IAM policies (iam-least-privilege-review) and repairing a failing CI pipeline (ci-pipeline-repair). Each skill is a single SKILL.md: no scripts, nothing that runs.
Add it to Claude Code
Pin the install to the current version, 0.9.0, in Claude Code:
/plugin marketplace add spellwarden-ai/infra-pack#v0.9.0
/plugin install infra-pack@spellwardenThe pin matters: released skills reach the main branch only in a release commit that raises the version, and a version pin keeps you on the text that was checked. The README gives the same two commands for a shell, and a way to scan the pack with the scanner yourself.
How it was measured
Version 0.9.0 was measured on Infra-Ops 40, a suite of 40 infrastructure tasks, with all five skills loaded: +15.0 points (95% interval 3.6 to 26.4), over five runs. The lift is the difference between the pass rate with the skills and without them, in percentage points. MEASUREMENTS.md sets out how the pack is measured and what may be claimed from a measurement, and the pack is listed in the public catalog.
Where the reference lives
Each tool documents itself in its repository. Go there for every option, error code and release note.
- The scanner's README: the command, the settings, the baseline and lock files, probing, connected mode, the usage ping and how to verify a release.
- The GitHub Action's README: inputs, outputs, permissions and pull requests from forks.
- The GitLab component's README: inputs, the jobs and the merge request comment.
- The Infra Pack's README: the five skills, installation and how the pack is checked.