The xyz command,
the full reference.
Every xyz command, checked against --help in 1.4.74: browser sign-in, the
always-on install firewall for npm, pip, Go and NuGet, machine audits, code scanning, CI/CD gating
and MCP for AI coding agents, on macOS, Linux and Windows.
or pip install cyberxyz-scanner · Python 3.8+
Install
The CLI is published on PyPI as cyberxyz-scanner; the command it installs is xyz.
It runs on macOS, Linux and Windows with Python 3.8 or newer (3.10 or newer for xyz mcp).
pipx keeps it in its own environment, which is what we recommend:
pipx install cyberxyz-scanner
# or
pip install cyberxyz-scanner
uv pip install cyberxyz-scanner
# verify
xyz --version
xyz --helpThis page describes 1.4.74. xyz upgrade installs the latest release.
Quick start
xyz login # sign in through your browser
xyz proxy setup # route npm, pip, Go and NuGet installs through CyberXYZ (sudo ... --system on managed machines)
xyz proxy status # is every package manager routed? is the agent current?
xyz audit # inventory and check what is already installedFrom then on every install on the machine goes through the CyberXYZ proxy: the exact version is checked before it downloads, blocked or quarantined packages are refused with the reason, and the install shows up in your dashboard.
Sign in
xyz login # opens your browser and shows a code (XXXX-XXXX)
xyz login --no-browser # SSH / headless: prints the link and code instead
xyz login uses the browser device flow. It opens app.cyberxyz.io/cli/activate and prints a
code. Sign in on the dashboard the way you usually do (password plus an authenticator app or a passkey, or SSO),
check that the code matches the one in your terminal, and click Approve. The CLI never sees your
password. Over SSH, or on Linux with no display, the link and code are printed automatically. Codes expire after
10 minutes and work once.
Only approve a code you just requested yourself. Approving a code someone sent you signs their terminal in as you.
Sessions are 90 days, sliding. The session stays signed in while you use it and expires after 90
days without use. While the CyberXYZ agent runs on the machine it refreshes the session daily, so you sign in once;
a machine that stays off for 90 days signs out. The session is stored owner-only in ~/.xyz/config.json
and listed in the dashboard under Settings > CLI sessions, where you or an org admin can revoke it.
xyz logout revokes it on the server and removes it locally.
xyz login --password is the legacy email and password prompt (--email, or
$XYZ_EMAIL and $XYZ_PASSWORD for scripts). Accounts with MFA, and organizations that
require MFA or enforce SSO, must use the browser login.
API keys
For CI runners and headless servers, create an API key in the dashboard (Settings > API keys,
it starts with sk_xyz_) and set it in the environment. No xyz login is needed.
export XYZ_API_KEY=sk_xyz_...
xyz check axios 1.7.7 --ecosystem npm # confirms the key authenticates
xyz --api-key sk_xyz_... audit npm # or pass it for one command
xyz status and xyz info show the sign-in stored in ~/.xyz/config.json, so
with only XYZ_API_KEY set they can say "Not logged in" while every request still uses the key. Use
xyz check or xyz scans list to confirm the key works. For fleets, use an enrollment token
instead (Managed machines).
The proxy and the agent
xyz proxy setup
xyz proxy setup
xyz proxy setup --machine-name "Alex MacBook"
xyz proxy setup --no-install-daemon # CI agents and sealed builds: no background serviceOne command registers the machine with your organization, points npm, pnpm, yarn, bun, pip, uv, Go and NuGet at the CyberXYZ proxy (each one only if it is installed), and installs the background agent that keeps them routed and runs dashboard Scan now jobs. If you are not signed in and the terminal is interactive, it offers the browser sign-in first.
| Option | What it does |
|---|---|
--machine-name TEXT | The name shown on the Machines page. Defaults to the hostname |
--system | Install the agent as a root/SYSTEM service (needs sudo, or an elevated PowerShell). See Managed machines |
--enrollment-token TEXT | Org enrollment token (pxe_xyz_...) for zero-touch setup with no xyz login. Also read from $XYZ_ENROLLMENT_TOKEN or /Library/Application Support/CyberXYZ/enrollment-token |
--install-daemon / --no-install-daemon | Also register the background service (default on) |
--proxy-url, --pip-proxy-url, --go-proxy-url, --nuget-proxy-url | Override the proxy endpoints (defaults: npm-proxy, pip-proxy, go-proxy and nuget-proxy.cyberxyz.io) |
--local | Point at a local proxy (http://localhost:4873) for testing |
Always-on protection
Every minute the agent checks what each package manager will actually use, repairs anything that no longer points at the proxy, and reports the result to the dashboard. Repairs never remove a private or internal registry, and config files are only written for tools that are installed.
| Tool | What is checked and repaired |
|---|---|
| npm, pnpm | ~/.npmrc registry and token, pnpm's global rc; as root also the global npmrc |
| yarn | ~/.yarnrc.yml npmRegistryServer and registry in ~/.yarnrc |
| bun | ~/.bunfig.toml [install] registry |
| pip | The user pip.conf / pip.ini: the proxy is the index-url; extra indexes on pypi.org are removed, private indexes are kept |
| uv | uv.toml: the proxy is the default index; pypi.org indexes are removed, private indexes are kept |
| Go | GOPROXY=<proxy>,direct (the proxy refuses blocked modules with 403, so there is no fall-through); proxy-only while the network lock is on |
| NuGet | NuGet.Config: the CyberXYZ source is added and nuget.org sources removed; private feeds are kept |
| Poetry | Cannot be forced globally, so it is covered by the network lock only |
Registry overrides in shell startup files (NPM_CONFIG_REGISTRY, PIP_INDEX_URL,
GOPROXY=direct, ...) and in the Windows user environment are reported, never edited.
If CyberXYZ is unreachable
The proxy reuses its verdict for any package it checked in the last 24 hours. For anything else your org's setting decides: block (the default, fail-closed; the developer sees "retry in a minute") or allow unchecked. Org admins change it under Settings > Supply-chain proxy.
xyz proxy status
xyz proxy statusShows the routing report for each package manager, the service level (per-user or system), the network lock, when the agent last reported (a report older than 15 minutes is flagged), and whether the agent runs the CLI version that is installed. It works without sudo under the system service.
xyz proxy restart
sudo xyz proxy restart # macOS / Linux, system service
xyz proxy restart # per-user service, or an elevated PowerShell on Windows
pipx upgrade and pip install -U replace the code but cannot restart a root service.
From 1.4.66 the agent notices the new version and restarts onto it by itself within a few minutes, between jobs.
xyz proxy restart does it now. The first CLI run after an upgrade prints the restart command when the
system agent is still on older code (XYZ_NO_UPGRADE_HINT=1 turns that off).
xyz proxy whoami and xyz proxy remove
xyz proxy whoami # what (organization, machine) does my proxy token resolve to?
xyz proxy remove # restore the default registries (sudo under the system service)
whoami tells you whether your npm and pip config carry a machine token (px_xyz_) or a
credential with no machine attribution. remove reports the removal to the platform first, then clears
the proxy entries and the service. To retire a machine and its token, delete it from the dashboard's Machines page.
To rotate a machine's token, run xyz proxy setup --machine-name "..." again as the same user.
xyz proxy daemon
You do not start the agent by hand: xyz proxy setup installs it (a LaunchAgent on macOS, a systemd
user unit on Linux, a Task Scheduler entry on Windows). It polls for Scan now jobs from the
dashboard and runs the matching audit. For debugging:
xyz proxy daemon --once # one poll, then exit
xyz proxy daemon --max-jobs 3
xyz proxy daemon --install-service # add --system for the root/SYSTEM service
xyz proxy daemon --uninstall-serviceManaged machines
# macOS / Linux
sudo xyz proxy setup --system
# Windows, from an elevated PowerShell
xyz proxy setup --system
--system installs a root/SYSTEM service (macOS LaunchDaemon io.cyberxyz.agent, Linux
cyberxyz-agent.service, Windows scheduled task CyberXYZAgent) that starts at boot, restarts
if it is killed, cannot be stopped by the developer, and repairs every local user's package-manager config. The
machine token is kept where only the agent can read it, so deleting a config file only gets it rewritten. Drift,
tampering, uninstalls and machines that stop reporting raise alerts for org admins. Under the system service only
an administrator can remove it.
MDM enrollment
An org admin creates an enrollment token in the dashboard (Machines > Enrollment). The macOS
.pkg installs the system service and enrolls automatically when MDM places the token at
/Library/Application Support/CyberXYZ/enrollment-token. Otherwise pass it:
sudo xyz proxy setup --system --enrollment-token pxe_xyz_...Network lock
When an org admin turns it on (Settings > Supply-chain proxy), the system agent maps the public
registries (registry.npmjs.org, registry.yarnpkg.com, registry.npmmirror.com,
pypi.org, files.pythonhosted.org, proxy.golang.org) to 0.0.0.0
in the hosts file, so tools that ignore config still cannot reach them. Edits to the lock are reverted and
reported. NuGet is not locked yet; it relies on config. xyz proxy status shows whether the lock is on.
Audit a machine
The proxy covers what is installed from now on. xyz audit covers what is already there: it checks the
packages against the malicious-package watchlist, deep-checks the suspects, and uploads the full inventory to your
dashboard.
xyz audit # npm, python, venvs, go, ide, browser and system, back to back
xyz audit npm # node_modules on this machine, global packages included (--no-global to skip)
xyz audit python # the active Python environment (pip list)
xyz audit venvs # every virtualenv, conda and pipx environment on the disk
xyz audit go # go list -m all
xyz audit nuget # packages.lock.json under the current directory (--lock-file PATH)
xyz audit ide # VS Code, Cursor, Windsurf and VSCodium extensions
xyz audit browser # Chrome, Edge, Brave and Firefox extensions
xyz audit system # Homebrew, apt, rpm, winget, Chocolatey, macOS apps
xyz audit models # local AI model files and Hugging Face references| Option | Where | What it does |
|---|---|---|
--full | npm, python, go, nuget | Check every package instead of only the watchlist matches. Slower; covers advisory matches at scan time |
--json | all | JSON instead of the table |
--output FILE, --format json|sarif | npm, python, go, nuget | Write findings to a file; .sarif is for GitHub Code Scanning |
--legacy | python, go | The pre-1.4.13 scripts (much slower) |
--no-verify | ide | Skip the upstream phantom-version check (no network calls) |
xyz audit models
xyz audit models # current directory and the Hugging Face cache
xyz audit models ./ml --no-hf-cache
xyz audit models --aibom -o aibom.cdx.json # CycloneDX 1.6 ML-BOM
Finds model files (.safetensors .bin .pt .pth .ckpt .gguf .onnx .pkl .h5) and hashes them with a
streamed sha256, finds Hugging Face references in code (from_pretrained, hf_hub_download,
pipeline(model=...), snapshot_download, and flags trust_remote_code=True), and
reads ~/.cache/huggingface/hub. Files are never loaded or unpickled. Files larger than
--max-hash-size (default 20 GiB) are listed as UNHASHED. NOT WATCHED, PENDING and UNSCANNED are not
verdicts. Exits 1 when anything is MALICIOUS. AI model coverage is part of the Business plan and above
(pricing).
Check, fix, impact, SBOM
xyz fix, xyz sbom and xyz depalert scan read the manifests and lockfiles in the
current directory: package.json / package-lock.json, requirements*.txt,
Pipfile / Pipfile.lock, pyproject.toml / poetry.lock /
uv.lock, go.mod / go.sum and NuGet packages.lock.json.
xyz check
xyz check axios 1.7.7 # npm by default
xyz check requests 2.31.0 --ecosystem pypi --json
xyz check org.apache.logging.log4j:log4j-core 2.14.1 -e mavenThe proxy's verdict for one PACKAGE VERSION, with the signals and a safe version.
xyz fix
xyz fix # plan only: package, current, issue (KEV badge), target, why
xyz fix --write # show a diff, confirm, then edit the specs
xyz fix --write --yes # no prompt (bots)
xyz fix --json
For each flagged package (block, quarantine, alert or any advisory) the plan gives the nearest clean release above
the installed version. A transitive package is traced to the direct dependency that pulls it in ("via express
→ debug, bump express"). --write edits only direct specs in package.json (keeping
^, ~ and >=) and == pins in requirements*.txt;
lockfiles are never edited, so run npm install, poetry lock, uv lock or
pip-compile afterwards. The plan is uploaded to your dashboard when you are signed in
(--no-upload to skip). Exit codes: 0 plan complete, 1 a flagged package has no
clean target, 4 backend unreachable.
xyz impact
xyz impact debug --version 2.6.8 # ecosystem guessed from the project, else npm
xyz impact requests -e pypi --json
xyz impact lodash --top 20 --no-localThe blast radius of a package: its direct dependents and whether each declared range admits the affected version, how many packages reach it on a required path versus only through an optional extra, and the top paths. Inside a project it also says whether this project reaches it, and through which direct dependency. "Not yet indexed" means the path is unknown, not that there is none.
xyz sbom
xyz sbom -o sbom.cdx.json # CycloneDX 1.5 JSON, with a vulnerabilities section
xyz sbom --format spdx -o sbom.spdx.json # SPDX 2.3 JSON
xyz sbom --no-verdicts # components only, no network call
Components carry a purl, the version and a scope (dev dependencies are excluded); the dependency graph
comes from the lockfile when it records one. Vulnerabilities list the advisory ids, CVSS and EPSS, a
cyberxyz:kev property for CISA KEV entries, and the safe version.
KEV
When an advisory is in CISA's Known Exploited Vulnerabilities catalog, a bold KEV marker leads the
score in depalert scan, the vulnerability tables and the xyz fix plan, and SARIF results
carry "kev": true.
Code scanning
xyz code-scan runs open-source engines installed on your machine and merges what they report into one
table, JSON document or SARIF 2.1.0 file. It works without signing in; when you are signed in the results also go to
the dashboard's XYZ Scan page: each finding with its rule, file, line and a short snippet. Secret findings carry
no snippet and secret values are never sent. --no-upload or XYZ_NO_UPLOAD=1 keeps a run local.
xyz code-scan secrets . # hardcoded credentials (values always redacted)
xyz code-scan iac ./infra # Terraform, CloudFormation, Kubernetes, Helm, Dockerfiles
xyz code-scan code . # SAST with the built-in xyz rules
xyz code-scan code . --config ./my-rules.yml
xyz code-scan ci . # GitHub Actions, GitLab CI and Azure Pipelines hardening
xyz code-scan image python:3.11-slim --sbom sbom.cdx.json
xyz code-scan all . --format sarif -o xyz.sarif --fail-on high
xyz code-scan engines # what is installed, versions, paths| Command | Engine | Fallback or option |
|---|---|---|
secrets | gitleaks | trivy, or --engine trivy |
iac | trivy | checkov with --engine checkov |
code | opengrep + the built-in xyz rules + any --config | without opengrep: bandit (Python), gosec (Go) |
ci | built in, no engine to install | GitHub Actions, GitLab CI and Azure Pipelines; --first-party-pins sets the severity for tag-pinned actions/* and github/* actions |
image | trivy (vulnerabilities, misconfigurations, secrets) | --sbom FILE writes CycloneDX |
all | secrets + iac + code, merged | --skip-missing, --fail-on-partial |
The built-in rules cover supply-chain patterns: shell=True and os.system with dynamic
commands, eval of downloaded data, curl | sh in scripts, CI files and Dockerfiles,
pickle.load, torch.load without weights_only=True,
trust_remote_code=True, hardcoded cloud and private keys, disabled TLS verification,
child_process.exec with template strings, and npm install scripts that download binaries. Without
opengrep they do not run, and xyz says so.
Installing the engines
xyz never downloads an engine binary itself. When one is missing and you are at a terminal, it asks once for all of them and runs your own installer: Homebrew (macOS and Linux), winget then Scoop (Windows), and opengrep's official install script (there is no Homebrew formula or PyPI package for it). Linux apt and rpm steps need sudo, so they are printed, not run. After installing, it re-checks and continues the same scan.
xyz code-scan engines # found or missing, version, path, install command
xyz code-scan engines --install # install the missing core engines (add --yes to skip the question)
xyz code-scan all . --install-engines # install without asking (setup scripts)
xyz code-scan all . --no-install # never askIn CI, or without a terminal, xyz never asks and never installs, even with --install-engines; it prints the command.
What gets scanned
Inside a git repository, the files git would commit (tracked, plus untracked but not ignored). Gitignored local
secret files such as .env are listed apart at INFO. Dependency, build and cache folders
(node_modules, venv, dist, build, .next,
target, caches, browser profiles) are always skipped. --all-files scans everything;
--exclude GLOB skips more.
Target guard. /, your home, the temp directory, or a folder with no project markers
(.git, package.json, pyproject.toml, go.mod, *.csproj, ...)
is scanned only after a yes on a terminal. In CI or without a terminal it is refused (exit 2) unless
--force-target (or XYZ_CODE_SCAN_FORCE_TARGET=1).
Partial scans and exit codes
A run that skipped a scanner is never reported as clean. The table ends with, for example,
Partial: secrets scanned, IaC and SAST skipped (engines missing), and JSON, SARIF and the dashboard upload
carry status (complete, partial or failed), coverage and one entry per scanner.
Common options: --format table|json|sarif, -o FILE,
--fail-on critical|high|medium|low|none (default low: any non-info finding fails) and
--timeout SECONDS per engine (default 900).
| Exit | Meaning |
|---|---|
0 | Clean: nothing at or above --fail-on |
1 | Findings at or above --fail-on |
2 | Usage error, including a refused target |
3 | Engine not installed (the install command for your OS is printed) |
4 | Engine error: non-zero exit, timeout or no report |
5 | Partial, opt-in: all --skip-missing --fail-on-partial found nothing in the scanners that ran, but one was skipped. Without --fail-on-partial, --skip-missing exits 0 in that case |
In GitHub Actions
- run: pip install cyberxyz-scanner "bandit[sarif]"
- run: xyz code-scan all . --skip-missing --format sarif -o xyz.sarif --fail-on high
- uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: xyz.sarif
Each run is tagged automationDetails.id = xyz-code-scan/<scan>/, so secrets,
iac and code can be uploaded separately. In GitLab CI, keep the SARIF or JSON as a job
artifact and treat the exit code as the gate. The engines are separate programs, none of them bundled: Trivy
(Apache-2.0), Gitleaks (MIT), Opengrep (LGPL-2.1), plus bandit, gosec and checkov (Apache-2.0) when present.
CI/CD
Two steps work together. Protect runs early in the job and routes the job's own npm, yarn, pip, uv, Go and NuGet installs through the proxy, so a malicious version is refused at install time on the runner. Scan gates the build on the lockfiles. The CI/CD gate guide has the full GitHub Actions, GitLab CI and Azure DevOps templates, thresholds and a live blocked pull request.
- 01GitHub Actions:
CyberXYZSecurity/depalert-action@v1, withmode: protect(optionalnetwork-lock: true,strict: true) and the defaultmode: scan. - 02GitLab CI/CD catalog:
gitlab.com/cyberxyz/depalertprovidesscan@1.2.0andprotect@1.2.0; protect is a hidden job,.cyberxyz-protect, used withextends:or!reference [.cyberxyz-protect, before_script]. - 03Any other CI:the two commands below, with
XYZ_API_KEYset as a secret.
xyz ci init
xyz ci init # provider detected from the git remote
xyz ci init --fail-on quarantine
xyz ci init --provider gitlab --print # print the file instead of writing it
Writes the xyz depalert scan gate into the repository's CI (--provider auto|github|gitlab|azure,
--path, --force to overwrite). It then tells you the one step it cannot do: adding
XYZ_API_KEY as a CI secret.
xyz ci protect
xyz ci protect --format github # GitHub: appends to $GITHUB_ENV, masks the token
eval "$(xyz ci protect --format shell)" # GitLab and any shell
xyz ci protect --format azure # Azure: ##vso[task.setvariable] lines| Option | What it does |
|---|---|
--format github|gitlab|shell|azure | How the environment is handed to later steps (default shell) |
--network-lock | Also blackhole the public registries in /etc/hosts (needs root or passwordless sudo) |
--strict | Exit non-zero when protection could not be applied. Without it the job continues unprotected with a warning |
--machine-name TEXT | Default ci/<provider>/<repo> |
--dotenv FILE | Also write the non-secret variables to a dotenv file (GitLab artifacts:reports:dotenv); token-bearing variables are never written there |
--no-config-files | Only emit environment; do not write ~/.npmrc, pip.conf, NuGet.Config or the Go env file |
--api-key, --api-url | Default $XYZ_API_KEY and $XYZ_API_URL |
xyz depalert scan
xyz depalert scan --package-lock package-lock.json
xyz depalert scan --requirements requirements.txt --fail-on quarantine
xyz depalert scan --requirements poetry.lock # also Pipfile.lock and uv.lock, detected from the file
xyz depalert scan --go-sum go.sum
xyz depalert scan -p axios@1.14.1 -p lodash@4.17.21
xyz depalert scan --package-lock package-lock.json --upload # also send the result to the dashboard's CI gates
--fail-on block|quarantine|alert sets the narrowest verdict that fails the build (default
block). Also --pipfile-lock, --poetry-lock, --uv-lock,
-e ECOSYSTEM for -p input, and --json.
| Exit | Meaning |
|---|---|
0 | All clean |
1 | Block: a known malicious version, a critical advisory on that version, or your org block list |
2 | Quarantine |
3 | Alert only |
4 | Could not check: backend unreachable, or a manifest was unreadable. Never treated as clean |
AI coding agents (MCP)
xyz mcp serve is a Model Context Protocol
server that Claude Code, Cursor, VS Code (Copilot agent mode), Windsurf, Codex CLI and Gemini CLI call to check
packages, advisories, dependencies and AI models before they add or install anything. It uses your
xyz login session (or XYZ_API_KEY) and needs Python 3.10 or newer.
xyz mcp install --client claude-code --hooks # MCP server + install hook, user scope
xyz mcp install --client cursor --scope project --rules
xyz mcp install --client all --dry-run # show every diff, change nothing
xyz mcp status # which clients are configured, does auth work
xyz mcp serve --tools # list the tools| Option | What it does |
|---|---|
--client | claude-code, cursor, vscode, windsurf, codex, gemini or all (repeatable, required) |
--scope user|project | Every project on this machine, or files in the current directory (default user) |
--hooks | Claude Code: add a PreToolUse hook that checks package installs (--hook-strict asks on alerts, --hook-fail-closed denies when CyberXYZ is unreachable) |
--rules | Add the CyberXYZ dependency policy to the client's agent rules (CLAUDE.md, AGENTS.md, GEMINI.md, .cursor/rules, ...) |
--dry-run, --yes | Show the diffs only; do not ask before appending to rules files |
Every edited file is merged, never overwritten, and the previous version is kept as .bak. The tools:
check_package and check_packages (install-time decision, signals, advisories with CVSS,
EPSS, KEV and fixed-in, a safe version), upgrade_plan, scan_project,
dependency_paths, package_dependencies, blast_radius,
get_vulnerability, search_vulnerabilities, model_risk,
model_load_safety, check_model_file and machines_with_package, plus the
cyberxyz-dependency-policy prompt.
xyz hook check-install
The hook that --hooks installs. Before Claude Code runs a shell command, it reads the command the way
the shell does and checks npm|pnpm|yarn|bun add/install <pkg>, pip and
uv pip install (including the exact pins in -r requirement files), uv add,
poetry add, pipx install, go get / go install and
dotnet add package in one call. Blocked or quarantined packages are denied with the reason and a safe
version. Lockfile installs pass: the proxy checks what they fetch. It fails open with a warning if CyberXYZ is
unreachable unless --fail-closed, and it never auto-approves a command.
The hosted MCP server
Nothing to install: https://mcp.cyberxyz.io/mcp speaks MCP over HTTP. Without a token it offers the
public tier (the public verdict, advisories, package search and model reports). With
Authorization: Bearer <token>, where the token is a dashboard API key (sk_xyz_) or the
token xyz login creates, it offers the signed-in tools; scan_project is replaced by
check_dependencies because the hosted server cannot read your files.
claude mcp add --transport http cyberxyz https://mcp.cyberxyz.io/mcp \
--header "Authorization: Bearer <token>"Lookups from the MCP servers and the hook identify themselves, so asking about a package is never counted as installing it.
The dashboard
Signed in, the CLI reports to your organization. Where each run lands:
| Command | In the dashboard | Opt out |
|---|---|---|
xyz audit (all subcommands) | XYZ Scan page, machine audits; the machine's inventory | always uploads |
xyz audit models | XYZ Scan page, AI models | --no-upload |
xyz fix | XYZ Scan page, project dependencies | --no-upload |
xyz code-scan | XYZ Scan page, code; secrets triage | --no-upload, XYZ_NO_UPLOAD=1 |
xyz depalert scan --upload | XYZ Scan page, CI gates | off by default |
| The proxy and the agent | Proxy Monitor (every install) and Machines (routing report, agent version, network lock, alerts) | xyz proxy remove |
Secrets triage. On a code scan's report, mark each secret rotated, removed, false positive, accepted risk (with an expiry) or assigned. A removed secret is verified by the next scan.
From the terminal:
xyz scans list --limit 10 --type npm # your organization's scan history (--user EMAIL, --output-json)
xyz scans show <scan_id>
xyz history # short form of scans list
xyz report html scan.json --open # render a saved scan, audit or SARIF file
xyz report pdf scan.json # needs WeasyPrint
xyz report last
xyz diff base.json head.json --fail-on high # compare two scan or SARIF files; fails only on ADDED findings
xyz remediate run --dry-run # admin-approved removals queued for this machineSBOM inventory
xyz inventory upload ./my-app # runs syft locally
xyz inventory upload --sbom syft.json --source-ref "release-2026-09"
xyz inventory exposure <inventory_id> --all-rowsExit codes for inventory upload: 0 no flagged rows, 1 a known-malicious row, 2 critical or high advisories only.
Command reference
Every command in 1.4.74. xyz COMMAND --help shows the options.
| Command | What it does |
|---|---|
login, logout | Browser sign-in (MFA, SSO, passkeys); revoke and clear the session |
status, info | Session, machine and environment; API version, health and your sign-in |
proxy setup | status | restart | whoami | remove | daemon | agent-hints | Route installs through the proxy and manage the agent; optionally tag installs made by AI coding agents |
audit [npm | python | venvs | go | nuget | ide | browser | system | models | exposure] | Audit what is installed on this machine; exposure lists the credentials an install-time payload could read |
check PACKAGE VERSION | The proxy's verdict for one package version |
fix, impact, sbom | Upgrade plan; blast radius; CycloneDX or SPDX SBOM |
code-scan secrets | iac | code | ci | image | all | engines | Secrets, IaC, SAST, CI pipeline hardening and container-image scanning |
depalert scan | CI/CD gate on lockfiles or inline packages |
ci init | protect | Write the gate into your pipeline; route a CI job's installs through the proxy |
mcp install | serve | status | MCP server for AI coding agents |
hook check-install | Claude Code install hook |
scans list | show, history | Scan history |
report html | pdf | last, diff | Render and compare saved scans |
inventory upload | exposure | Upload an SBOM and get exposure |
remediate run | Run admin-approved removals queued for this machine |
package NAME, vuln ID, recent, stats | Search advisories by package or id, recent advisories, database statistics |
upgrade | Upgrade the CLI to the latest release |
Global options: --api-key, --api-url, --debug, --version.
Upgrade and sign out
xyz upgrade # or: pipx upgrade cyberxyz-scanner
xyz logout
xyz upgrade upgrades cyberxyz-scanner in the environment that runs the CLI and restarts a
per-user agent. A root agent restarts onto the new version by itself within a few minutes; sudo xyz proxy
restart does it now. xyz logout revokes the CLI session and clears it; the proxy stays wired up.
Config and env vars
| Variable | Effect |
|---|---|
XYZ_API_KEY | API key (sk_xyz_) used instead of a login session. The usual choice for CI |
XYZ_API_URL | Platform base URL. Default https://api.cyberxyz.io |
XYZ_ENROLLMENT_TOKEN | Org enrollment token for xyz proxy setup |
XYZ_NPM_PROXY_URL, XYZ_PIP_PROXY_URL, XYZ_GO_PROXY_URL, XYZ_NUGET_PROXY_URL | Proxy endpoints the agent enforces when setup did not record one |
XYZ_EMAIL, XYZ_PASSWORD | Legacy password login only |
XYZ_NO_UPLOAD=1 | Turn the dashboard upload off by default (--upload still wins) |
XYZ_NO_UPGRADE_HINT=1 | Hide the "system agent is on older code" line |
XYZ_CODE_SCAN_FORCE_TARGET=1 | Same as --force-target |
XYZ_DASHBOARD_URL | Dashboard base URL for links in the output |
Local state lives in ~/.xyz/: config.json holds the CLI session (owner-only). Under the
system service the machine token lives in /Library/Application Support/CyberXYZ/,
/etc/cyberxyz/ or %ProgramData%\CyberXYZ\; otherwise in ~/.xyz/machine-token.
Pass --debug for verbose output.
Troubleshooting
| You see | What to do |
|---|---|
Agent code : 1.4.68 running, 1.4.74 installed in xyz proxy status, or the upgrade hint | The agent is outdated. Run sudo xyz proxy restart (an elevated PowerShell on Windows), or wait a few minutes: agents from 1.4.66 restart themselves |
| A tool shows NOT ROUTED | Run xyz proxy setup again, or wait for the agent's next check (every minute). Check your shell startup files for NPM_CONFIG_REGISTRY, PIP_INDEX_URL or GOPROXY=direct, which are reported but never edited |
| The last report is older than 15 minutes | The agent is not running. xyz proxy restart; if it is not installed, xyz proxy setup (add --system on managed machines) |
engine not installed: IaC scanning needs trivy on PATH (exit 3) | xyz code-scan engines --install, or the printed command. --skip-missing runs what is installed |
Partial: secrets scanned, IaC and SAST skipped | Some engines are missing, so this is not a clean result. Install them, or add --fail-on-partial so CI fails (exit 5) |
| Code scan refuses the target (exit 2) | You pointed it at /, your home, the temp directory or a folder with no project markers. Run it from the project, or pass --force-target |
xyz fix exits 1 | A flagged package has no clean release above the installed version. See the options for findings with no fixed version: a partial upgrade, removal, or an ignore with an expiry |
| Session expired, or "not logged in" | The session was unused for 90 days or revoked. Run xyz login. With only XYZ_API_KEY set, xyz status says "not logged in" but requests still use the key |
xyz login --password: "This account requires MFA/SSO" | Use plain xyz login (browser sign-in) |
| Installs land as unattributed in the dashboard | xyz proxy whoami. If the config carries no machine token, run xyz proxy setup --machine-name "..." again |
| A package still installs from nuget.org | NuGet is not covered by the network lock; check NuGet.Config in xyz proxy status |
| Scan now does nothing | xyz proxy status shows whether the agent runs and when it last reported. xyz proxy restart, or xyz proxy daemon --once to debug. Machines set up with --no-install-daemon cannot run Scan now |
depalert scan exits 4 | CyberXYZ could not be reached or a manifest could not be read; the result is never treated as clean. Check XYZ_API_KEY and the file path |
Resources
- 01Package on PyPIcyberxyz-scanner
- 02GitHub ActionCyberXYZ DepAlert
- 03GitLab componentcyberxyz/depalert
- 04Dashboardapp.cyberxyz.io
- 05Supportsupport@cyberxyz.io · security: security@cyberxyz.io
Questions, answered.
How do I install the CLI?
pipx install cyberxyz-scanner (or pip install cyberxyz-scanner), then xyz login (browser sign-in) and xyz proxy setup. The command is xyz, and xyz upgrade keeps it current.
Do I need an account to scan a package?
Enrolment ties results to your organisation and unlocks the install proxy and the dashboard. For a single public verdict without an account, the package checker on the website answers the same question.
What is the difference between the CLI and the install proxy?
The CLI answers when you ask. The proxy answers on every install, including the ones a script starts without you. Most teams run both: the proxy as the always-on gate, the CLI for audits and CI.
Does scanning send my source code anywhere?
Dependency scans send only package names and versions. xyz code-scan runs its engines on your machine; when you are signed in it uploads each finding with its file, line and a short code snippet (secret findings carry no snippet, and secret values are never sent). --no-upload keeps everything local.
Catch it in the editor,
not in production.
See the extension, the CLI and the dashboard in a 15-minute walkthrough. The extension is included in every plan, from $25 per developer per month, with a 30-day proof of value.
- ✓ In every plan, from $25/dev/month
- ✓ npm · PyPI · Go · NuGet
- ✓ 30-day proof of value
Thanks! We'll be in touch.
Check your inbox. We'll reach out within 24 hours.