Install
The CLI installs from PyPI. Pick whichever installer fits your stack.
# With pip
pip install cyberxyz-scanner
# With uv
uv pip install cyberxyz-scanner
# Verify the install
xyz --help
The package name is cyberxyz-scanner; the installed binary is
xyz. Python 3.10 or newer is required.
First-time setup
Two commands wire up a machine end to end: authenticate, then enroll the machine with the proxy. Both are idempotent; running them again on the same machine refreshes the local credentials.
1. xyz login
xyz login
Email: you@example.com
Password: ********
Stores a session token at ~/.xyz/config.json. The token is valid for
24 hours; re-run xyz login whenever it expires. Email lookup is
case-insensitive, so any casing of your address works.
2. xyz proxy setup
xyz proxy setup
That is the whole command. No flags required. It detects the hostname, picks up the public CyberXYZ proxy endpoints for every ecosystem you have installed, and does all of the following in one shot:
- Registers the device on the dashboard under your org.
- Writes the proxy token to
~/.npmrc. - Configures pip's global index URL.
- Writes
~/.nuget/NuGet/NuGet.Configwith the NuGet feed. -
Installs and starts the OS service so the dashboard
Scan nowbutton can trigger a fresh inventory audit (LaunchAgent on macOS, systemd user on Linux, Task Scheduler on Windows).
Optionally pass --machine-name "..." to override the hostname with a
friendlier label that shows up on the Machines page:
xyz proxy setup --machine-name "Alex MacBook"
For CI/CD runners and sealed build agents that should not run a long-lived background
process, opt out of the OS service with --no-install-daemon:
xyz proxy setup --no-install-daemon
Using an API key instead of login
For machines where running xyz login isn't practical (CI runners,
headless servers, shared developer endpoints), set XYZ_API_KEY in the
environment. The CLI picks it up automatically and uses it as the bearer credential
for every command. No xyz login is required, and the session never
expires the way a 24-hour login token does.
# Generate the key from the dashboard: Settings, then API Keys.
# Key value must begin with sk_xyz_ to be accepted.
export XYZ_API_KEY=sk_xyz_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# Verify the key is authenticating against the platform.
# This hits /api/v1/proxy/check which requires a valid session,
# so a successful response confirms the API key is being applied.
xyz check axios 1.7.7 --ecosystem npm
# Then enroll the machine and audit. No xyz login required.
xyz proxy setup
xyz audit npm
The xyz info and xyz status commands display login
state from the local config file at ~/.xyz/config.json, not from
a live API call. If you have only set XYZ_API_KEY without running
xyz login, those commands report "Not logged in" even though the
key is being used on every request. Use xyz check or
xyz scans list to verify the key is actually authenticating; if
they return data, your CLI is wired up correctly.
Persist the variable in your shell profile, your CI secret store, or an
EnvironmentFile entry in the systemd unit. Make sure the key has
the scan permission at minimum; read is also useful
for xyz check. Rotate the key from the dashboard if it leaks;
the CLI picks up the new value the next time the env var loads.
A user with both an active xyz login session and
XYZ_API_KEY set in the environment will use the login session
first; the API key is the fallback. Run xyz logout to clear
the session and force the API key path.
Audit installed packages
Each command below audits the matching ecosystem on this machine, runs the CyberXYZ watchlist plus deep checks on suspect packages, and uploads the full inventory to the platform. Results show up under the Inventory tab on the dashboard.
xyz audit npm # local + global node_modules
xyz audit python # active Python environment via pip
xyz audit go # $GOPATH module cache
xyz audit nuget # packages.lock.json files under cwd
xyz audit # npm + python + go back-to-back
Full vs watchlist mode
By default each command uses the watchlist pre-filter for speed (around 25 to 40
seconds on a typical machine). Pass --full to skip the pre-filter and
deep-check every package. Slower, but covers advisory-only matches at scan time.
xyz audit python --full
JSON output
Append --json to any audit subcommand to emit machine readable JSON
instead of the human report.
xyz audit npm --json > npm-audit.json
Proxy management
Once the machine is enrolled, the proxy intercepts every npm install,
pip install, go get, and dotnet add package.
The decisions show up in real time on the Proxy Monitor page.
xyz proxy status
Show whether the proxy is wired up correctly and which token is in use.
xyz proxy status
xyz proxy whoami
Verify the proxy token resolves to your organization. Useful when CI runners misconfigure the token and start landing as Unattributed.
xyz proxy whoami
xyz proxy remove
Reverse xyz proxy setup. Clears the npmrc / pip / nuget config entries
and uninstalls the OS daemon. The proxy token is also deleted on the server.
xyz proxy remove
Check a single package
One-off safety check without changing your install pipeline. Useful inside CI scripts where you want to gate a specific dependency before promotion.
xyz check axios 1.7.7 --ecosystem npm
xyz check requests 2.31.0 --ecosystem pypi --json
Scans and history
The scan history surfaces every audit you have run from this machine and every
dashboard-triggered Scan now job.
xyz scans list --limit 10
xyz scans show <scan_id>
Inventory and SBOMs
For pipelines that produce a CycloneDX or SPDX SBOM, upload it directly instead of letting the CLI generate one from the local install state.
xyz inventory upload --sbom-path ./build/sbom.cdx.json \
--source-ref "release-2026-q2"
# Show the exposure breakdown for an upload
xyz inventory exposure <inventory_id>
--only-flagged trims the upload to packages the platform has advisories
on, keeping the payload small on large monorepos.
Background daemon
You do not start the daemon manually. xyz proxy setup installs and
starts it automatically as part of first-time setup (LaunchAgent on macOS, systemd
user on Linux, Task Scheduler on Windows). The daemon polls the platform for
Scan now jobs queued from the dashboard and runs them in the background.
Useful commands if you want to inspect or restart it:
xyz status # is the daemon running?
xyz daemon --once # process one job and exit (debugging)
On CI runners and sealed build agents you opted out of the daemon by passing
--no-install-daemon to xyz proxy setup. That is fine;
the proxy enforcement on npm install / pip install still
works, you just can't trigger Scan now from the dashboard for those
machines.
CI/CD integration
For CI/CD pipelines, the recommended pattern is xyz depalert scan
against your lockfiles. It returns a non-zero exit when a flagged package shows
up, so the build fails with a clear reason instead of merging a malicious
dependency. The CLI auto-detects GitHub Actions, GitLab CI, and Azure DevOps and
tags every scan with the runner identity.
Ready-to-drop YAML templates for all three platforms are surfaced on the
Proxy Monitor page on the dashboard, under the Setup
tab. Click Copy on the card that matches your CI provider and paste the file at
the path it indicates (.github/workflows/xyz-depalert.yml,
cyberxyz-supply-chain.yml, or .gitlab-ci.yml).
Common shape across all three:
# 1. Generate XYZ_API_KEY from the dashboard (Settings, API Keys).
# Scope to "scan" permissions only.
# 2. Add it as a CI secret:
# GitHub: Settings, Secrets and variables, Actions
# GitLab: Settings, CI/CD, Variables (Masked + Protected)
# Azure: Pipeline variable XYZ_API_KEY (secret)
# 3. Set XYZ_FAIL_ON to choose the gating threshold:
# block fail on confirmed malicious only
# quarantine fail on quarantined + block (recommended)
# alert fail on anything flagged (strictest)
# The job runs:
pip install --quiet cyberxyz-scanner
xyz depalert scan --package-lock package-lock.json --fail-on "$XYZ_FAIL_ON"
xyz depalert scan --requirements requirements.txt --fail-on "$XYZ_FAIL_ON"
xyz depalert scan --go-sum go.sum --fail-on "$XYZ_FAIL_ON"
Or pass packages directly without a lockfile, useful for ad-hoc gating:
xyz depalert scan -p axios@1.14.1 -p lodash@4.17.21 --fail-on block
Pulling the templates from the dashboard Setup tab keeps them in sync with the CLI defaults the rest of the platform expects. If you change the templates locally, mirror them back into the dashboard so other admins copying the YAML pick up the same patches.
Upgrade and uninstall
Upgrade in place
xyz upgrade
Runs pip install --upgrade cyberxyz-scanner against the same Python
environment that owns the CLI. The current version is printed first; check it
manually with xyz info.
Sign out without uninstalling
xyz logout
Clears ~/.xyz/config.json. The proxy stays wired up; only the login
session is cleared. The next xyz audit will prompt for
xyz login again.
Config and env vars
| Variable | Effect |
|---|---|
XYZ_API_URL |
Override the platform base URL. Defaults to https://api.cyberxyz.io. |
XYZ_API_KEY |
Use this API key instead of the login session. Required for CI. |
XYZ_PROXY_URL |
Override the npm proxy endpoint. Same shape for XYZ_PIP_PROXY_URL, XYZ_GO_PROXY_URL, XYZ_NUGET_PROXY_URL. |
XYZ_DEBUG |
Set to 1 to log every API call to stderr. |
Local state lives under ~/.xyz/: config.json holds the
session token, proxy_token holds the machine token written by
xyz proxy setup.
Troubleshooting
xyz login returns Incorrect email or password
The error is intentionally identical for missing accounts and wrong passwords so
that login responses do not leak which emails are registered. Confirm the password
works in the dashboard first; if it does, check that the XYZ_API_URL
env var is not pointing at a stale host.
xyz proxy setup fails with permission denied on /usr/local/bin
Re-run with sudo, or install the CLI into a user-owned virtualenv so it
does not need to touch system paths.
Installs land as Unattributed in the dashboard
The CLI version is older than 1.4.6, or the proxy token is missing from the local
config. Run xyz upgrade, then
xyz proxy setup --machine-name "..." to re-write the token.
NuGet proxy ignored on macOS or Linux
dotnet reads ~/.nuget/NuGet/NuGet.Config on macOS and Linux, not
~/.config/NuGet/NuGet.Config. CLI 1.4.25 and newer write the correct
path; older versions miss it. Run xyz upgrade.
Daemon not responding to Scan now
xyz status reports whether the LaunchAgent or systemd service is
running. If it is stopped, re-run xyz proxy setup to re-register the
OS service. On Windows, check Task Scheduler for the
cyberxyz-xyz-daemon task.
Resources
- Package on PyPI: cyberxyz-scanner
- Dashboard: app.cyberxyz.io
- Support: support@cyberxyz.io