Add Swarm to CI

Bring the same attributable quality gate to committed branch changes, before they become shared history.

Before Swarm can scan a branch, your CI job must have the Zedbee package installed and enough Git history to identify that branch’s changes. A normal checkout and dependency install may not provide both. The first two steps show what to check and what to change.

Step 1

Make Zedbee available to the CI job

The CI job needs the Zedbee package installed before it can run Swarm. Zedbee is normally a development dependency, so a production-only dependency install leaves it out. Checking out your repository does not install it.

Add zedbee as a development dependency locally and commit the package manifest and lockfile. Then make sure the CI job uses Node.js 22.13.0 or newer and installs development dependencies from that lockfile. The scan commands in this guide use --no-install: they use the installed package rather than downloading a missing one.

For npm, npm ci --include=dev explicitly includes Zedbee. If your job already installs development dependencies from the lockfile, keep that install step; you do not need a second one. For pnpm, Yarn, or Bun, use the equivalent frozen-lockfile install with development dependencies included.

Set up and review your repository policy

Include Zedbee’s development dependency
npm ci --include=dev
Shared settings

When settings updates take effect

Where does the file go? By default, .zedbeerc.jsonc belongs at the root of the Git repository you are scanning, alongside that project’s code. It is not a file inside the installed Zedbee package or a setting stored in your CI service. It controls things such as which checks run and which findings block the change.

For a local scan, stage your settings edits. After saving the file, run git add .zedbeerc.jsonc. Your next ordinary zedbee scan uses that staged version. You do not have to commit it first. If you edit the file again, stage it again for the next scan to use those newer edits. Saving alone does not replace the settings already staged in Git.

For CI, commit and push the settings with your code. Commit .zedbeerc.jsonc on the branch you want CI to check, then push that branch. A CI scan uses the settings saved inside the commit the job checks out. The update takes effect when a CI run checks out a commit containing it. Rerunning a job against an older commit still uses that older commit’s settings.

The settings do not have to be merged into main first.

Commit them on your feature branch along with the code they should apply to. --base origin/main tells Swarm which branch to compare the code against; it does not tell Swarm to load the settings from main.

Do not rewrite the file during the CI job to change the scan. The scan reads the committed copy, so an edit made after checkout is ignored. Update the file in your branch, commit it, and run CI against the updated code instead.

Local and CI scans normally share this one settings file. Selecting CI output with --format json or --format sarif does not require changing it. If the selected staged or committed version of the repository has no .zedbeerc.jsonc, Swarm uses its recommended defaults.

Which settings does the scan use?
Your changeWhen it takes effect
Save the fileNot yet. Scans still use the previously staged or committed settings.
Stage the fileThe next local scan uses the staged settings. CI is unchanged.
Commit and pushCI uses the update when its job checks out a commit containing it.
Use an edited settings file in a local scan
git add .zedbeerc.jsonc
npx --no-install zedbee scan
Step 2

Give Zedbee the Git history it needs

Zedbee needs more than the files in the current checkout. To identify what your branch changed, Swarm needs the branch’s current commit, the base branch you are comparing against, and their shared Git history.

A CI checkout may download only the latest commit. That can be enough to build your project, but not enough for Swarm to work out which changes belong to your branch. This is a shallow checkout: the earlier commits Swarm needs may be missing.

Configure your checkout step to fetch full history, then make the base branch available locally with the command shown here. Fetching the base branch alone does not necessarily fill in missing history on your checked-out branch. If your existing checkout already includes both full history and the intended base ref, no extra fetch is needed.

The examples use origin/main; replace it with your actual base branch. Swarm finds the shared commit where the branches diverged, called the merge base, and scans the changes from there to your checked-out commit (HEAD). This keeps changes made only on the base branch out of your branch’s results.

Swarm does not fetch for you.

Swarm does not download missing branches or history. If the base ref or shared history is unavailable, it cannot complete the comparison and exits with code 2. That is an incomplete scan, not a clean result. Fix the checkout’s history settings before running the scan in Step 3.

Make the base branch available to Zedbee
git fetch --no-tags origin \
  +refs/heads/main:refs/remotes/origin/main

# Confirm a shared ancestor is available
git merge-base origin/main HEAD
Step 3

Scan committed changes, not an empty index

An ordinary zedbee scan compares the Git index with HEAD. On a clean checkout, those states match: there are no staged changes to inspect.

Pass --base origin/main explicitly to scan committed changes from the merge base through HEAD.

Both source snapshots come from commits. Staged, unstaged, and untracked working-tree files do not replace the selected target.

Your CI provider may check out a branch tip or a generated merge commit. Swarm scans whichever commit is checked out as HEAD, so choose the checkout target and base branch to match the changes you want to check.

CI · scan the branch
npx --no-install zedbee scan \
  --base origin/main \
  --format text
Step 4

Keep a complete report

Choose an explicit output format for your pipeline. JSON is Swarm’s versioned machine-readable contract. SARIF 2.1.0 is intended for systems that ingest code-analysis results. Text gives you a complete human-readable export.

These exports include every finding and incomplete-check notification. They are ANSI-free and are not shortened by the terminal preview limit.

Configure your CI provider’s artifact step to retain the selected report even when the scan fails. Creating a SARIF file does not upload it to a code-scanning service; configure that integration separately if needed.

Keep report access intentional.

Secret findings are redacted. Ordinary source excerpts follow your reporting policy and explicit source flags. Apply appropriate access controls and retention to exported reports.

npx --no-install zedbee scan --base origin/main --format sarif > zedbee.sarif
Step 5

Preserve the scan’s decision

A report and a successful job are different things. Swarm’s exit status remains the gate, regardless of the output format.

0
Scan completed without blocking findings
1
Scan completed and repository policy blocked the change
2
Required analysis could not complete

The shell example captures the scan status before printing a summary, then returns that same status to CI. Configure artifact retention in a separate provider step that runs on failure as well as success.

Make the scan job a required check in your repository’s merge policy if it should gate merges.

Incomplete is not a pass.

Do not discard the exit status with || true or let a later successful command replace it. Resolve incomplete analysis before treating the change as clean.

POSIX shell · retain the exit status
set -eu

scan_status=0
npx --no-install zedbee scan \
  --base origin/main \
  --format sarif > zedbee.sarif || scan_status=$?

case "$scan_status" in
  0) echo "Scan completed without blockers" ;;
  1) echo "Blocked by repository policy" ;;
  2) echo "Required analysis was incomplete" ;;
  *) echo "Command failed: $scan_status" ;;
esac

exit "$scan_status"
Troubleshooting

Check the inputs before changing policy

No changes reported? Confirm you used --base, that HEAD is the intended commit, and that the base ref points to the intended comparison branch.

Missing history? Inspect whether the checkout is shallow and whether a shared ancestor is available. More than one best merge base is also ambiguous; Swarm requires a unique one.

Settings changes not taking effect? For a local scan, stage the updated .zedbeerc.jsonc. For CI, commit and push it, then ensure the job checks out a commit containing the update. Editing the file during the CI job will not change the scan. See when settings updates take effect.

Vulnerability analysis unavailable? Review the reported diagnostic and CI network access. OSV lookups send package names, exact versions, and the npm ecosystem identifier, not source code or file hashes. There is no offline advisory database; the selected policy controls whether a supported OSV outage blocks or warns.

Need to fix a finding? CI scans are read-only: they do not modify HEAD, refs, the index, or working files, and zedbee fix --base is not supported. Make and review fixes locally, then commit them and rerun CI.

Review the scanner’s security boundaries

Git · inspect the checkout
git rev-parse HEAD
git rev-parse --is-shallow-repository
git show-ref --verify refs/remotes/origin/main
git merge-base --all origin/main HEAD