Skip to content
Latchkey

semgrep ci: The Diff-Aware CI Subcommand

semgrep ci auto-detects the CI environment and diff, scans only changed code on pull requests, and uploads results when SEMGREP_APP_TOKEN is set.

Where semgrep scan is general purpose, semgrep ci knows it is in a pipeline. It reads the PR base automatically and is diff-aware out of the box.

What it does

semgrep ci detects the provider (GitHub Actions, GitLab CI, etc.), figures out the base ref, and scans only new findings on a pull/merge request. With SEMGREP_APP_TOKEN it pulls your configured rules and uploads findings to the Semgrep platform; without a token it falls back to a default rule set. It exits 1 on blocking findings.

Common usage

Terminal
# connected to Semgrep AppSec Platform
SEMGREP_APP_TOKEN=${{ secrets.SEMGREP_APP_TOKEN }} semgrep ci
# standalone, no platform, with explicit rules
semgrep ci --config p/ci

Options

Flag / envWhat it does
SEMGREP_APP_TOKENAuth to pull rules and upload findings
--config <src>Use explicit rules instead of the platform set
--sarif --output <f>Also write SARIF to a file
--baseline-commit <sha>Compare against this commit for new findings
--no-suppress-errorsFail on scan errors instead of skipping them

In CI

On pull requests semgrep ci reports only newly introduced findings, which keeps PR noise down; on a push to the default branch it scans the full project. It needs the base branch present, so use fetch-depth: 0. semgrep ci already exits non-zero on blocking findings, so no extra --error flag is needed.

Common errors in CI

"Failed to clone the baseline ref" or "could not find baseline commit" means a shallow checkout; set fetch-depth: 0. "Invalid API token" or "401" means SEMGREP_APP_TOKEN is unset or wrong (a fork PR cannot read the secret). With no token and no --config you still get a default scan, which can surprise teams expecting their own rules.

Related guides

Run this faster and cheaper on Latchkey managed runners. Start free →