Getting started · 1 of 9

Install and run the open-source CLI

Check a migration locally with npx bolvrk — no account, no config. bolvrk.json defaults, inline suppressions, repository ignores, secret scanning of files and piped output, and the SQLite corpus behind --engine=sqlite.

The public bolvrk package and the free rules it bundles are open source under the Apache License 2.0; the engine core they run on is source-available under the FSL-1.1 and converts to Apache-2.0 two years after each release — see LICENSING.md. It bundles 18 of the 68 SQL rules — the outage core and credential hygiene — plus the credential scanner, runs them locally, and never phones home. Exit codes: 0 clean, 1 findings, 2 usage or parse error, 3 service or database unavailable (nothing was checked — retry or fix the connection). --json emits the findings contract; --format=sarif emits one SARIF 2.1.0 log for code scanning.

Pass a multi-file set together — earlier files declare structure for later ones, and the BS rules only fire on a set.

terminal
npx bolvrk check migrations/*.sql               # several files, globs, or - for stdin
npx bolvrk check migration.sql --json            # structured findings for scripting
npx bolvrk secrets "src/**" ".env*"              # credential rules over any file — always local
./deploy.sh 2>&1 | npx bolvrk secrets -        # or over whatever a command prints

SQLite (beta)

--engine=sqlite (or "engine": "sqlite" in bolvrk.json) runs the SQLite corpus — the SL family — over a real SQLite grammar, locally, with the same report and exit codes. It is static only: no --db, no --remote, and the corpus is still growing, so a finding is real but silence is not yet a guarantee. The credential rules run on every engine.

terminal
# the SQLite corpus (beta) — local only, same report and exit codes
npx bolvrk check migrations/*.sql --engine=sqlite

Scanning output and pipes

bolvrk secrets - reads standard input, so anything a command prints can be checked before it lands in a log, a ticket or a chat: a deploy script's output, a CI job's stderr, a git diff before it is pushed. A match on piped input means the value was printed — that is the leak itself, and the report says so. Findings are line-indexed into the piped text, the value is masked, and --json and --format=sarif work the same as on files (the SARIF location is <stdin>). - can sit next to file arguments, and exit code 1 on a finding fails the pipeline step it runs in.

terminal
# a command's output, stdout and stderr together
./deploy.sh 2>&1 | npx bolvrk secrets -

# a log you already have
npx bolvrk secrets - < deploy.log

# what is about to be committed, as a pre-commit hook or by hand
git diff --cached | npx bolvrk secrets -

# a CI job's log, pulled with the GitHub CLI
gh run view 12345 --log | npx bolvrk secrets -

# a container's log
docker logs api 2>&1 | npx bolvrk secrets -

# piped input next to files, with structured output
cat .env.production | npx bolvrk secrets - "src/**" --json

bolvrk.json

A bolvrk.json at the repo root (found from any subdirectory) holds the defaults; bolvrk check with no files uses the migrations globs. The secrets globs are what bolvrk secrets scans with no arguments. --config=<path> points at another file and --no-policy ignores its policy block for one run. The policy block sets the block threshold only — per-rule overrides live on the dashboard's Policy page, never in a file a commit can change — and bolvrk policy pull writes the team's threshold into the file so local runs block where CI blocks. Team policy is a Team feature: on Team and above the policy governs every connected check — CI, bolvrk check --remote and the API alike.

bolvrk.json
{
  "engine": "postgres",
  "migrations": ["migrations/*.sql"],
  "secrets": [".env*", "src/**"],
  "policy": { "blockOn": "warning" }
}

Suppressing a finding

A bolvrk-ignore comment on the statement's line or the line above suppresses a finding; several ids share one comment (BV003, BV034: reason). The reason is required, and every suppression — honored or not — is recorded in the report.

migration.sql
-- bolvrk-ignore BV003: index built in the maintenance window
CREATE INDEX idx_orders_region ON orders (region);

ALTER TABLE orders ADD COLUMN region text; -- bolvrk-ignore BV003, BV034: maintenance window

Ignoring a rule for a repository

When a rule is right but not wanted in this codebase — house-style notes such as timestamp without a time zone, char(n), serial — silence it once in bolvrk.json with a reason, instead of suppressing every occurrence:

bolvrk.json
{
  "migrations": ["migrations/*.sql"],
  "ignore": {
    "BV040": "timestamp without time zone is our house style",
    "BV043": "serial columns are generated by our ORM"
  }
}

The reason is required. Ignores apply to every local run, and the CLI and the GitHub Action send them with each hosted check, where they are honored on Startup and above — before the team policy. The output always says how many findings were hidden; nothing disappears silently. --ignore=BV040,BV041 does the same for a single run. A rule that misreads your SQL is a different case: dispute it with "This finding is wrong" on the check page rather than ignoring it, so the corpus gets fixed.

One command to start

Check a migration now, sign in when the team wants the rest.

Sign in with GitHub