Open source maintainers can use Safeguard to keep a project's dependencies healthy without giving up their evenings. The Safeguard CLI runs on your own machine, finds vulnerable packages, fixes them with your approval, reviews contributor pull requests, builds an SBOM for each release and validates your VEX files. Only results go to the platform; your source stays local.
This guide is for the person who merges the pull requests: a few hours a week, a stream of "is this affected?" issues, and pressure to ship a patch quickly when a dependency goes bad. Everything below fits in those hours.
One thing up front, because maintainers ask it first. Bring the Claude, ChatGPT or Codex plan you already pay for and use it inside the Safeguard CLI. Safeguard adds no extra charge for that usage; your plan's own usage limits and terms still apply. You can also connect Claude or ChatGPT to the Safeguard MCP server and ask about your project's findings from the chat you already use.
What you will have at the end
Work through this guide once and you will have:
- The Safeguard CLI installed and signed in on the machine where you maintain the project.
- A first scan of your repository, with results as JSON files under
./outputthat you can read, diff and keep. - A tested routine for fixing a vulnerable dependency with the assistant: it reads the finding, proposes the change, asks before each command, runs your tests and leaves the commit to you.
- A habit for reviewing contributor pull requests with
safeguard reviewbefore you merge. - A release checklist that produces an SPDX SBOM, validates it and any VEX document you publish, and attaches both to the GitHub release.
- A GitHub Actions job that scans every push to your main branch and every release tag, written so it does not break on pull requests from forks.
- The desktop and phone apps set up so you can approve work on your computer when you are away from it.
Items 1 to 3 are where most of the value is; start there.
Do the work properly with the Safeguard CLI
The Safeguard CLI scans code, container images and SBOMs on your own machine, sends only the results to the platform, and includes an assistant that can fix what it finds. It writes code as well as scanning it. For a maintainer, that means the tool that tells you a dependency is vulnerable is the same one that can upgrade it, run your test suite and explain the change in a commit message.
Install
The CLI is a single static binary. No Node, Python or JVM is needed to run it, which matters when you maintain projects in several ecosystems. It runs on macOS, Linux and Windows, on x86_64 or arm64 (Windows is x86_64 only).
On macOS or Linux:
curl -fsSL https://cli.safeguard.sh/install | bash
safeguard --version
On Windows, in PowerShell:
irm https://cli.safeguard.sh/install.ps1 | iex
safeguard --version
Both install scripts verify the checksum of what they download, and the download page publishes a SHA256SUMS file for each direct archive if you prefer to fetch the binary yourself. Platform specific notes live in our guides for macOS, Windows and Linux.
Later, safeguard self-update --check tells you whether a newer release exists without installing anything, and safeguard doctor prints what is wrong with an installation, in the order that matters, without changing anything.
First session
Change into your project and open the interactive terminal:
cd ~/code/my-library
safeguard
Type /login to sign in through the browser, then /scan . to scan the current folder. When the scan finishes you can ask in plain language: "how many critical vulns do we have", or "which of these come from dev dependencies only". @ attaches a file from the folder you started in, so "@package.json which of these pins is oldest" works as you would expect. /resume picks up the last session in that folder, which is handy when you maintain several repositories and come back to each one a week later.
Writing and fixing code
Here is the request most maintainers try first: "fix the lodash CVE in this repo". The assistant reads the finding, the files involved and the advisory. It then proposes the edit, for example moving lodash to 4.17.21 in package.json, and asks before it runs npm install and npm test. You press y or n for each command. At the end it prints a summary with a suggested commit message. It pushes nothing. The commit and the push stay yours.
The same assistant can find and read files, edit code and run commands for ordinary maintenance work, with your approval: "update the changelog for the 2.3.1 patch release", "find every place we call the deprecated parse function", "run the tests for the Node 18 matrix entry only".
Every file the agent writes or edits is snapshotted first. If a change goes the wrong way, /rewind takes you back, and safeguard checkpoints lets you list and preview a restore with --dry-run from outside the session. Anything a shell command writes is not snapshotted, so keep your work in git as usual.
Using your Claude or ChatGPT plan
You choose the model with /model, which shows the current model and switches it. If you already pay for Claude, ChatGPT or Codex, you can use that plan inside the CLI and Safeguard adds no extra charge for that usage; your plan's own limits and terms still apply. See the CLI docs or /model for connecting a model.
If you already have Claude Code or Codex configured, safeguard import claude or safeguard import codex converts that setup into Safeguard configuration. With safeguard other-agents on, which is the default, the CLI also reads Claude Code, Codex and OpenCode agents, skills, MCP servers and instructions below its own.
Approvals
/permissions sets how much the assistant may do without asking:
| Mode | What runs without asking | Good for |
|---|---|---|
| Ask | Reads. Edits and commands ask first | Your first week, unfamiliar repos |
| Accept edits | Edits in this folder and read-only commands. Other commands ask | Long refactors you are watching |
| Plan | Nothing changes. Read and plan only | Scoping a fix before a release |
| Auto (default) | Read-only commands and what the policy allows. Anything else asks | Daily maintenance |
| Strict | Pre-approved actions only | CI |
There is also a --yolo flag that approves everything. Keep it for throwaway sandboxes only, never for a checkout that holds your signing keys or release credentials.
CI with safeguard exec
safeguard exec "summarise the critical findings in this repository" runs one non-interactive assistant turn and exits, which suits CI. Its default permission mode is strict: nothing is asked, and anything the policy file has not pre-approved is denied. It also refuses to run outside a git repository, because there would be no way to undo what it changes. Our post on running the CLI in CI with safeguard exec covers it in depth.
Here is the CLI session from start to finish, recorded on a real machine against a sample project.
Click through it at your own pace, or open it full screen.
A release routine for your project, step by step
This is the routine to run before you tag a release. It assumes a GitHub hosted project, but every Safeguard command works the same wherever your code lives.
Step 1: scan and read the results
safeguard scan --dir . --output ./output
ls ./output
safeguard scan builds an SBOM and matches it against vulnerability databases. The results land as JSON files under ./output, including vuln.json and license.json. Keep the output folder out of git (add it to .gitignore) but keep a copy per release if you want to compare later.
If you publish under a scope or namespace, tell the scanner which packages are yours so they are not mistaken for third party code:
safeguard scan --dir . --org-namespace @my-org
When you only want a quick look and do not want anything to leave the machine at all, safeguard findings runs one scanner locally and prints a normalized list. Nothing is uploaded and no project is registered, even when the CLI is signed in:
safeguard findings sca --dir .
safeguard findings sca --dir . --json
Step 2: fix what needs fixing
For a single finding, ask the assistant in the interactive terminal, as shown above. For a batch of dependency upgrades, safeguard fix is the direct route. Preview first:
safeguard fix --dry-run --severity high
safeguard fix --severity high --patch-only
--dry-run shows the changes without applying them. --patch-only keeps you to patch version upgrades, which is usually what you want for a patch release. By default it only upgrades, never downgrades, and creates a backup of the original files. If you prefer a pull request to a local change, safeguard fix --create-pr --draft opens a draft PR for you to review.
Then run your own tests. For an npm project, npm ci is the right install in CI because it requires an existing lockfile and exits with an error if package-lock.json and package.json disagree, instead of rewriting the lock.
Step 3: build the SBOM for the release
safeguard sbom --dir . --output my-library-2.3.1-sbom.spdx.json
safeguard sbom writes an SPDX JSON SBOM using the same path the scanner uses internally. SPDX is an open standard for software bill of materials information, hosted by the Linux Foundation and recognised as ISO/IEC 5962:2021, so downstream users can read it with the tools they already have.
Step 4: write or update your VEX
When users open issues asking whether your library is affected by a vulnerability in one of its dependencies, a VEX document is the durable answer. VEX lets a software producer tell consumers whether a vulnerability actually affects a product, and that status can change as you learn more. OpenVEX defines four statuses: not_affected, affected, fixed and under_investigation.
A not_affected statement must carry either a justification or an impact statement. The justification labels are component_not_present, vulnerable_code_not_present, vulnerable_code_not_in_execute_path, vulnerable_code_cannot_be_controlled_by_adversary and inline_mitigations_already_exist.
You can ask the assistant to draft the file: "write an OpenVEX statement for the transitive finding in vuln.json; we never call the affected function, explain why in the impact statement". It asks before writing the file. A minimal document looks like this (the identifiers are placeholders):
{
"@context": "https://openvex.dev/ns/v0.2.0",
"@id": "https://example.org/my-library/vex-2.3.1",
"author": "my-library maintainers",
"timestamp": "2026-10-21T09:00:00Z",
"version": 1,
"statements": [
{
"vulnerability": { "name": "CVE-YYYY-NNNNN" },
"products": [{ "@id": "pkg:npm/my-library@2.3.1" }],
"status": "not_affected",
"justification": "vulnerable_code_not_in_execute_path",
"impact_statement": "my-library never calls the affected function."
}
]
}
Only you can make the call on not_affected. The assistant drafts; you decide. If your project is also scanned on the platform, reachability analysis can show whether the vulnerable code is on a path your project calls, which is useful evidence for the justification.
Step 5: validate both files
safeguard validate my-library-2.3.1-sbom.spdx.json --strict
safeguard validate vex/my-library-2.3.1.openvex.json
safeguard validate ./sboms --recursive -o validate-report.json
safeguard validate checks CycloneDX, SPDX and VEX documents (CSAF and OpenVEX). --strict treats warnings as errors, which is what you want before publishing, and -o writes a report you can keep with the release.
Step 6: attach them to the release
With the GitHub CLI:
gh release upload v2.3.1 my-library-2.3.1-sbom.spdx.json vex/my-library-2.3.1.openvex.json
Or drag the files into the binaries box when you draft the release in the web UI. If your repository uses immutable releases, create the release as a draft first so you can attach every asset before it is published.
Step 7: scan every push and tag in CI
safeguard ci scan scans a commit as a new version of its Safeguard project. For a public repository on github.com, gitlab.com or bitbucket.org, a repository that has not been imported yet is imported on its first run with no integration at all. With --local, the scan runs on the CI runner and only the results are uploaded, never the source. It covers dependencies (SBOM and vulnerabilities) in that mode.
Create a secret key in Safeguard under Settings, Secret Keys, with the scans:trigger scope (and scans:read if you use --wait). In GitHub, go to Settings, Secrets and variables, Actions, and add it as a repository secret named SAFEGUARD_API_KEY. Then:
name: safeguard
on:
push:
branches: [main]
tags: ['v*']
jobs:
scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install the Safeguard CLI
run: curl -fsSL https://cli.safeguard.sh/install | bash
- name: Scan this commit
env:
SAFEGUARD_API_KEY: ${{ secrets.SAFEGUARD_API_KEY }}
run: safeguard ci scan --local --wait --fail-on high
If the scan step cannot find safeguard, add the folder the install script reports to the job's PATH. Note what this workflow does not do: it does not run on pull_request. That is deliberate, and the next section explains why.
Step 8: give reporters a private channel
A scanner finds known issues in your dependencies. People find the rest, and they need somewhere private to tell you. Two GitHub settings cover it:
- Add a security policy. On the repository's Security and quality tab, choose Security policy, then Start setup. GitHub opens a new
SECURITY.md; describe which versions you support and how to report a vulnerability, then commit it on a branch and open a pull request. - Turn on private vulnerability reporting. In Settings, under Security and quality, open Advanced Security and click Enable next to Private vulnerability reporting. Reporters then see a Report a vulnerability button on the repository's Advisories page.
When a report arrives, open the interactive terminal in Plan mode and ask the assistant to walk the affected code with you before anyone writes a patch. Plan mode reads and plans only, so nothing changes while you are still deciding what the report means.
Reviewing contributor pull requests
Most of the code you merge was written by someone else, and more of it every month was written with a coding agent. You need a way to look at it with the same care whether it came from a regular contributor or a first timer.
Why fork PRs need a different approach
GitHub does not pass secrets to the runner when a workflow is triggered from a forked repository; GITHUB_TOKEN is the only exception, and it is read-only in pull requests from forks. So a CI step that needs SAFEGUARD_API_KEY will not have it on a fork PR. You might be tempted to switch to pull_request_target to get the secret back. GitHub's own docs warn that running untrusted code on that trigger may lead to security vulnerabilities, including cache poisoning and secret exposure. Do not build or run fork code there.
The safer pattern is to scan on push to main and on tags in CI, as above, and review incoming PRs on your own machine.
The local review, step by step
-
Check out the pull request. The GitHub CLI checks out PRs from forks by number:
gh pr checkout 482 -
Ask Safeguard to review the change against your main branch:
safeguard review --base mainsafeguard reviewreviews changes for correctness and security;--basediffs against a git ref instead of the working tree. -
If the PR touches dependencies, scan locally without uploading anything:
safeguard findings sca --dir . -
Open the interactive terminal in Plan mode for anything you want to discuss before touching it: "explain what this PR changes in the parser and whether the new dependency is needed". Plan mode reads and plans only.
-
Leave your review on GitHub as usual. If you want the assistant to help write the review comment, ask it; it can draft the text, and you post it.
Our post on reviewing AI generated code before merge goes further on this.
Work from the desktop and your phone
Maintainers rarely do all their work at one desk. A Safeguard CLI session is live: it shows up in the web app, the desktop app and the phone app, and those devices can send work to it. Start in the terminal, continue on the desktop, check findings on your phone.
The desktop app (3.2.2 on the download page) runs on Windows 10 and 11, macOS 12 and later, and Linux as an x86_64 AppImage. The Windows installer is per user and needs no admin rights; it is not yet code-signed, so SmartScreen may warn. Check the SHA-256 first, then choose More info, Run anyway. The Mac build is signed and notarized. The Linux AppImage needs the Safeguard CLI installed and on your PATH.
The mobile apps are on the App Store for iPhone and iPad and on Google Play for Android phones and tablets. A direct APK is offered for phones without Google Play.
From the desktop or phone app you can send work to a computer running the CLI: pick the computer and the folder, then approve each command and file edit there. On the phone, each command waits for Allow once, Allow for turn or Deny. Say a user reports a broken patch release while you are out: ask your home machine to run the failing test, approve it from your phone, and read the result before deciding whether to yank the release.
The CLI can also pass things the other way. safeguard devices lists your signed-in devices, safeguard send --to my-phone --link https://github.com/my-org/my-library/pull/482 sends a link to read later, and safeguard inbox shows what your other devices sent to the CLI. Our Android guide has the phone setup in detail.
This recorded session on an Android phone shows the approval flow end to end.
Click through it at your own pace, or open it full screen.
Troubleshooting and common mistakes
Troubleshooting
The scan finds nothing in a project that clearly has dependencies. Check you ran it from the project root or passed the right --dir. For npm projects, make sure the lockfile is committed; a lockfile gives the scanner the exact versions.
safeguard exec refuses to start. It needs a git repository so changes can be undone. Run it inside your checkout. --skip-git-repo-check exists, but only use it when you accept that risk.
The CI step fails with an authentication error. Confirm the secret is named exactly SAFEGUARD_API_KEY, that the key has scans:trigger (and scans:read with --wait), and that the run was not triggered from a fork, where secrets are not passed.
Something feels wrong with the install. Run safeguard doctor. It changes nothing and lists problems in the order that matters.
Common mistakes
- Running the agent with
--yoloin your main checkout. It approves everything. Use it only in a throwaway sandbox. - Using
pull_request_targetto get secrets onto fork PRs. Scan on push and tags instead, and review forks locally. - Publishing a
not_affectedVEX statement without a justification or impact statement. The OpenVEX spec requires one or the other. - Letting the assistant push. It does not push in the recorded session, and you should keep it that way. Read the diff, run the tests, then commit and push yourself.
- Forgetting that shell commands are not snapshotted.
/rewindrestores files the agent wrote or edited, not files a command created. Commit before large changes. - Treating a scan result as a release decision. Policies and gates are evaluated in the platform, not by the CLI. Use
--fail-onin CI as a floor, not as your whole release process.
FAQ
Can I use my existing Claude or ChatGPT subscription?
Yes. Bring the Claude, ChatGPT or Codex plan you already pay for and use it inside the Safeguard CLI. Safeguard adds no extra charge for that usage; your plan's own usage limits and terms still apply. See the CLI docs or /model for connecting a model. You can also connect Claude or ChatGPT to the Safeguard MCP server and use Safeguard from those chats; our guides for Claude and ChatGPT walk through it.
Does my source code get uploaded?
The CLI scans on your machine and sends only results to the platform. When the local runner runs platform scan jobs, only SBOMs and findings are uploaded, never source. safeguard findings uploads nothing at all.
Will this work for Python, Java or Go projects too?
The scan builds an SBOM from the folder and matches it against vulnerability databases, so it is not tied to npm. The assistant runs whatever test command your project uses (pytest, mvn test, go test ./...), asking before each one.
Which SBOM format do I get?
safeguard sbom writes SPDX JSON. safeguard validate checks SPDX and CycloneDX documents, plus VEX in CSAF or OpenVEX form, so you can validate files produced by other tools too.
Can the CLI open fix pull requests for me?
safeguard fix --create-pr --draft opens a draft PR with dependency fixes. On the platform, autonomous remediation with fix PRs is available and off by default.
What if I already use Claude Code or Codex for this project?
Keep using them. safeguard import claude or safeguard import codex converts your setup into Safeguard configuration, and safeguard other-agents (on by default) reads their configuration below Safeguard's own. Then use safeguard review to check what any agent changed before you merge.
How do I keep the CLI current?
safeguard self-update --check reports whether a new version is available. safeguard self-update installs it after verifying a signed manifest, and keeps the previous binary as safeguard.previous.
Try it yourself
This walkthrough sets up the runner on your own machine: pick the platform, start it, approve it with its device code, then use the same CLI to scan from the terminal.
Click through it at your own pace, or open it full screen.
When you are ready, install from safeguard.sh/download and keep the CLI docs open for your first session.
Quick check
Why should a CI scan that uses SAFEGUARD_API_KEY run on push and tags rather than on fork pull requests?
GitHub does not pass secrets to workflows triggered from forked repositories, so the key would be missing. Switching to pull_request_target to get it back risks running untrusted code with access to secrets. Scan on push and tags, and review fork PRs locally with safeguard review.
What must an OpenVEX not_affected statement include?
Either a status justification, such as vulnerable_code_not_in_execute_path, or an impact statement explaining why the product is not affected.
Which permission mode lets the assistant read and plan but change nothing?
Plan. It reads and plans only, which makes it a good fit for scoping a fix or discussing a contributor's PR before you touch any files.
Sources
- Safeguard CLI documentation
- Safeguard downloads
- GitHub Docs: Using secrets in GitHub Actions
- GitHub Docs: Events that trigger workflows
- GitHub Docs: Configuring private vulnerability reporting for a repository
- GitHub Docs: Adding a security policy to your repository
- GitHub Docs: Managing releases in a repository
- GitHub CLI manual: gh release upload
- GitHub CLI manual: gh pr checkout
- OpenVEX specification
- SPDX overview
- npm Docs: npm ci
Last reviewed: 21 October 2026.