@vigilbase/cli
Version:
Vigilbase CLI — security scanners, agent tools, and Vigilbase One from the terminal.
607 lines (501 loc) • 32 kB
Markdown
# @vigilbase/cli
Vigilbase public security scanners, the Cloudflare Checkup, and Vigilbase One
customer, security, Cloudflare, monitoring, organization and support operations
from the terminal.
## Install
Node.js 20 or newer is required. `cloudflare-checkup` needs Node.js 22.18 or
newer, because it runs Cloudflare's `cf` under the same Node. Node 22.19+ and
24.5+ also trust your operating system's certificates automatically (see
[Troubleshooting](#troubleshooting)).
```bash
npm install -g @vigilbase/cli # or: pnpm add -g @vigilbase/cli
vigilbase help
```
Without installing: `npx @vigilbase/cli help`. If you see
`Unknown command "cloudflare-checkup"`, an older global install is answering
instead (see [Troubleshooting](#troubleshooting)).
Public tools and the Cloudflare Checkup work without signing in. Vigilbase One
commands need `vigilbase login` (see [Sign-in](#sign-in)). Signing in isn't
supported on Windows yet; public tools and `cloudflare-checkup` still work there.
## Documentation
| Reference | Covers |
| --- | --- |
| [COMMANDS.md](https://app.unpkg.com/@vigilbase/cli@0.2.10/files/COMMANDS.md) | Core commands, aliases, global options, API mapping, sign-in, output |
| [CLOUDFLARE.md](https://app.unpkg.com/@vigilbase/cli@0.2.10/files/CLOUDFLARE.md) | Accounts, zones, DNS, WAF, analytics, Zero Trust, Workers/Pages, audit, checkups |
| [SECURITY.md](https://app.unpkg.com/@vigilbase/cli@0.2.10/files/SECURITY.md) | Incidents, logs, intelligence, analytics, assets, connections, policies, notifications, reports |
| [ONE.md](https://app.unpkg.com/@vigilbase/cli@0.2.10/files/ONE.md) | Customer records, billing, reports, investigations, organizations, monitoring, support |
| [LOCAL.md](https://app.unpkg.com/@vigilbase/cli@0.2.10/files/LOCAL.md) | `cloudflare-checkup`: verifies your work email, collects your Cloudflare configuration on your machine with Cloudflare's `cf` and uploads it automatically once saved |
These files ship with the package. Built-in help: `vigilbase <command> --help`
or `vigilbase help <command>`; `vigilbase help <command> <subcommand>` (for
example `vigilbase help cf zones`) shows the same help as
`vigilbase cf zones --help`, and `vigilbase help <tool>` shows how to run a
tool. The library is ESM-only: use `import()`, not `require()`.
## Examples
Public tools, no sign-in:
```bash
vigilbase list
vigilbase headers https://vigilbase.com
vigilbase email vigilbase.com --json
vigilbase describe security-headers
vigilbase badge vigilbase.com --style compact
```
The public scanners are `security-headers` and `email-security`.
`website-security`, `react2shell` and `fortibleed-check` run through Vigilbase
One and need a sign-in:
```bash
vigilbase login
vigilbase run website-security example.com --json
vigilbase account
vigilbase customers list --json
vigilbase customers summary <customer-uuid>
vigilbase orgs list
vigilbase monitoring health
vigilbase support tickets
vigilbase runs list
```
Cloudflare IDs come from the inventory you can access:
```bash
vigilbase cf accounts
vigilbase cf zones
vigilbase cf dns <zone-id> --customer-id <customer-uuid>
vigilbase cf waf <zone-id> --customer-id <customer-uuid> --json
vigilbase cf zero-trust <account-id>
vigilbase cf developer-platform <account-id>
vigilbase cf analytics --customer-id <customer-uuid> --zone-id <zone-id> --days 7
vigilbase cf checkup progress <run-uuid>
```
Security uses the same tenant and permission boundary as One's dashboard:
```bash
vigilbase security
vigilbase security incidents --severity high --json
vigilbase security incidents show <incident-uuid>
vigilbase security logs --search 'failed login' --limit 50
vigilbase security assets
vigilbase security intel ip 203.0.113.8
vigilbase security analytics security-analysis --hours 24
vigilbase security zero-trust device-health --hours 24
vigilbase security notifications
vigilbase security audit --limit 50
```
Customer users inherit their organization's scope. Internal operators add
`--customer-id <customer-uuid>` for security views and support tickets.
Everyone adds it to `cf analytics`, `cf dns`, `cf waf` and `cf speed-settings`.
Other customer-specific commands take the customer UUID as an argument.
Flags select records; One still decides whether your session can see them.
After reviewing an incident, you can update its status explicitly:
```bash
vigilbase security incidents update <incident-uuid> acknowledged \
--note 'Investigating with the customer' --confirm
```
Other statuses are `mitigating`, `resolved` and `false_positive`. `--confirm`
states your intent; it does not grant permission or approve provider
remediation. API changes are never retried automatically. The references list
the other explicit actions (sending invitations, opening a billing portal
session, running scans and starting checkups).
## Cloudflare Checkup on your machine
```bash
npx @vigilbase/cli cloudflare-checkup
```
This one command (also `vigilbase cloudflare-checkup` or
`vigilbase local cloudflare-checkup`) runs the Vigilbase Cloudflare Checkup
on your machine with Cloudflare's own `cf` CLI. It needs no Vigilbase sign-in.
If you are signed in with `vigilbase login`, it uses your verified account
identity without asking for an email or code. Otherwise it asks for your work
email and vigilbase.com emails you a 6-digit code to enter. It then installs cf if needed (it asks first), signs in to Cloudflare
read-only, lets you choose the account, collects, shows what the snapshot
contains and uploads it (`cloudflare-checkup collect` collects without
uploading). It prints the results link and opens it in your browser on
macOS and Linux; the results also go to your verified email.
cf owns your Cloudflare login: this CLI never reads, prints, stores or uploads
it. Your account token is sent only to One; vigilbase.com receives a short-lived
proof tied to this checkup. Checkup output shows only the masked
`j***@acme.com` address. `--email` can select a different recipient, which
requires email verification.
In a terminal the steps show as an interactive timeline; pipes, CI,
`TERM=dumb` and `--json` get plain lines.
Local checkups work while vigilbase.com has them switched on. The CLI checks
before it asks for your email. When they are off, it stops with
`Local checkups aren't available right now.` and points you to the checkup in
your browser, <https://vigilbase.com/tools/cloudflare-checkup>, which uses a
read-only Cloudflare API token instead. When you are done:
```bash
npx @vigilbase/cli cloudflare-checkup logout # removes the read-only cf login and the cf it installed
```
See [LOCAL.md](https://app.unpkg.com/@vigilbase/cli@0.2.10/files/LOCAL.md) for
every step, what is uploaded and the error codes.
## Public tools and sign-in
- **Public scans never depend on your sign-in.** `headers`, `email` and
`run security-headers|email-security` call the public API anonymously and
never read your saved sign-in, so an expired, broken or unreachable sign-in
cannot make them fail. `--public` and `--via public` force the public API for
the public tools (`security-headers`, `email-security`).
- **One-only scans need a sign-in.** `website-security`, `react2shell`,
`fortibleed-check` and any run with `--via one` go through Vigilbase One.
Without a usable sign-in they stop with
``This command needs a Vigilbase One sign-in: run `vigilbase login`.``
(code `NOT_SIGNED_IN`), as every One command does. With `--public` or
`--via public` a One-only tool stops before any request:
``website-security runs only through Vigilbase One: drop --public and run `vigilbase login`.``
`run` with a tool name it doesn't know fails locally with
``Unknown tool "<name>". Run `vigilbase list` for the allowlist.``
(code `INVALID_ARGUMENT`).
- **Scan quota.** Public scans share an hourly quota of 20 scans per client IP
address and 20 per target (1,000 an hour overall). When it is used up,
vigilbase.com answers HTTP 429 (`rate_limit_exceeded`) and the CLI exits 2
with the delay until the quota resets (up to an hour; `retryAfterSec` in
JSON). The CLI never retries on its own.
- **`list`** reads your saved sign-in from disk only (no refresh, no network,
no waiting for another command) to show which tools you can run. If it can't
use it, it lists the tools as signed out and prints one line on stderr:
``Couldn't use your saved sign-in (<reason>); running anonymously. Run `vigilbase login` to fix.``
When the reason is an unsafe config path or credentials file, the line ends
with its fix instead (see [Directory checks](#directory-checks)).
- **`doctor`** reports a sign-in problem as its own failed `signIn` check,
including a sign-in saved for another One origin, Identity issuer or client
ID: ``Saved for a different One origin, Identity issuer or client ID. Pass the matching --one-url, --auth-url and --client-id, or run `vigilbase login`.``
## Automation and output
Every command supports `-j` / `--json`. JSON goes to stdout; progress and
browser instructions go to stderr. Errors are JSON on stdout whenever `--json`
or `-j` is given, also inside a cluster of short flags (`-hj`) and as
`--json=…`; a `--json` after `--` is an argument, not the flag. Commands are
matched in any case (`vigilbase LIST` is `vigilbase list`).
Progress animations are off for `--json`, for output that isn't a terminal, in
CI (`CI` set to anything but `0` or `false`, in any case), with `TERM=dumb` and
with `VIGILBASE_CLI_NO_PROGRESS=1`. `NO_COLOR` doesn't turn them off, because
the spinner has no colour. The spinner fits the terminal width, and Ctrl-C
during a scan clears its line and exits 130. The same CI rule decides the
checkup's terminal UI and its colours and opening a browser (login, billing),
so `CI=yes` neither animates nor opens a browser.
List commands never fetch every page on their own: keep the JSON pagination
fields to fetch the next page. Text output shows complete identifiers: the
first column of `runs list` works with `runs get`, and `watchdog list` starts
with the target ID that `watchdog scans --target-id` takes.
Human-readable output removes terminal control sequences, bidirectional
overrides and invisible characters (zero-width characters, word joiners, the
byte order mark, U+2028/U+2029 line separators and Unicode tag characters) from
everything it prints, including names, tool results, skills and errors. Server
text in scan results never starts a line of its own: every line of a message is
indented. JSON keeps successful response data, with the same characters escaped
as `\uXXXX`, so values stay lossless.
`vigilbase --version` and `vigilbase help` print the banner only in a terminal.
When stdout is a pipe or a file, `--version` prints only the version number and
help starts at `Usage:`, so `v=$(vigilbase --version)` works in scripts. With
`--json`, `--version` prints `{"name":"@vigilbase/cli","version":"…"}`. The
banner is plain text.
| Exit code | Meaning |
| --- | --- |
| `0` | Success (including a signed-out `whoami`, and a graded scan whatever its grade) |
| `1` | Validation, API, network or sign-in error, or a scan that failed or couldn't be assessed |
| `2` | Rate limited (`HTTP 429`) |
| `130`, `143`, `129` | `cloudflare-checkup` cancelled by Ctrl-C (SIGINT), SIGTERM or SIGHUP (128 + the signal number) |
A graded scan exits 0 even with an F. Its first line starts with `✓` only when
the result's `status` is `secure` and the grade isn't F; otherwise it starts
with `•`. Scripts should gate on `.grade` or `.result.status` in the JSON.
Errors keep a safe status, error code and retry delay. These codes come from
the CLI itself:
| Code | Meaning |
| --- | --- |
| `NOT_SIGNED_IN` | A command that needs Vigilbase One has no usable sign-in |
| `SIGN_IN_ENDED` | Vigilbase Identity ended the saved sign-in, and `identity-credentials.json` was removed |
| `SIGN_IN_UNSUPPORTED` | Signing in isn't supported on Windows yet |
| `UNKNOWN_OPTION` | An option the CLI doesn't know, with `Did you mean --x?` when one is close |
| `INVALID_ARGUMENT` | A missing or unexpected option value (`--timeout needs a value.`, `--json does not take a value.`), an invalid value, an unknown subcommand or a token that isn't valid |
| `UNEXPECTED_REDIRECT` | An origin answered with a redirect, which the CLI never follows |
| `BLOCKED_PORT` | Node's fetch refuses the port (see [Troubleshooting](#troubleshooting)) |
| `TIMEOUT` | A request took longer than `--timeout` |
Network failures otherwise carry Node's code (for example `ENOTFOUND` or
`ECONNREFUSED`), and `cloudflare-checkup` has codes of its own (LOCAL.md).
When a public scan fails and vigilbase.com explains why, the CLI shows that
reason: `Error: <message> (<code>)` in text, and `error` plus `code` in JSON.
The reason is shown only when vigilbase.com sends it as a known error code, and
it is cleaned to one line of at most 300 characters. Anything else, and every
Vigilbase One error, prints a message the CLI wrote (for example
`You don't have access to this.` or `Request failed (HTTP <status>).`), never
the server's text. The exception is a scan the scanner couldn't assess (for
example a bot verification challenge), on the public API or through One: the
CLI prints `✗ <tool> · <target> · n/a` and the scanner's reason, cleaned the
same way (code `scan_unassessed`). Hints (`Hint: …`, `hint` in JSON) are always
written by the CLI; COMMANDS.md lists the One errors that get one.
Commands use named One APIs and One's own authorization. They never take
Cloudflare or other provider secrets, delegated identity claims or an arbitrary
upstream URL. Billing records are fetched on demand and never stored by the
CLI.
## Sign-in
### Logging in
`vigilbase login` opens a browser and waits for you to approve the device code.
On a remote terminal, run `vigilbase login --no-open` and open the printed URL
in a signed-in browser.
The CLI reads One's protected-resource metadata to choose the sign-in:
- **Vigilbase Identity** (one.vigilbase.com uses it). You approve at
<https://auth.vigilbase.com/device> and choose the organization the sign-in
is for. `whoami` and `doctor` check the session at Identity.
- **Legacy One sign-in**, for a One that doesn't advertise Identity. You
approve at that One's `/device` page.
The CLI builds the approval URL itself from the issuer (or One) origin; it
never opens a URL the server sends.
To save an existing One session token instead, pipe it from your secret
manager into `vigilbase login --token-stdin`. The input must hold one token and
is never echoed. `--token <bearer>` and `VIGILBASE_ONE_TOKEN` also work, but
command arguments can show up in process listings and shell history; neither
combines with `--token-stdin`. Login checks the token with One before saving
it.
A token must be one value of printable ASCII (no spaces or control
characters), at most 16 KiB, whether it comes from `--token-stdin`, `--token`
or `VIGILBASE_ONE_TOKEN`. Otherwise login stops before any request with
`The token must be a single value of printable ASCII characters.`,
`The token exceeds 16 KiB.` or `The token must not be empty.` (code
`INVALID_ARGUMENT`); an empty `VIGILBASE_ONE_TOKEN` counts as unset. If an Identity
sign-in saved with other `--auth-url`, `--one-url` or `--client-id` values
exists, a token login or a legacy device login stops before it sends the token
or asks for a device code:
`A saved Identity sign-in belongs to <issuer> for <One origin> (client ID <id>). Pass the matching --auth-url, --one-url and --client-id, or log out with them first.`
### Where credentials are stored
Credentials live in the config directory: `VIGILBASE_CONFIG_DIR` if set,
otherwise `$XDG_CONFIG_HOME/vigilbase`, otherwise `~/.config/vigilbase`.
`VIGILBASE_CONFIG_DIR` must be an absolute path; a relative `XDG_CONFIG_HOME`
is ignored. A set but empty `VIGILBASE_CONFIG_DIR` doesn't fall back: when the
credentials are needed it is an error
(`VIGILBASE_CONFIG_DIR is empty. Set it to an absolute path or unset it.`). If
`HOME` is relative and nothing else is set, the error names `HOME`.
| File | Holds |
| --- | --- |
| `identity-credentials.json` | Your Vigilbase Identity sign-in: issuer, client, One origin, organization and the rotating refresh token. CLI 0.1.x never reads it. |
| `credentials.json` | A legacy One session (version 1), shared with CLI 0.1.x: written by `--token`, `--token-stdin`, `VIGILBASE_ONE_TOKEN` and legacy device sign-in. |
| `credentials.json.lock` | One lock for both files, also used by CLI 0.2.0. |
Files are written atomically with mode `0600`. A saved session is only sent to
the One origin it was issued for (a legacy file without an origin counts as
production). With both files present, the Identity sign-in is used, and a
`credentials.json` that can't be parsed is ignored. Logging in replaces a file
that passes the [directory checks](#directory-checks) but can't be parsed.
### Using CLI 0.1.x or 0.2.0 too
- CLI 0.2.0 kept its Identity sign-in in `credentials.json`, which CLI 0.1.x
cannot read. The first command of 0.2.1 or later that reads your sign-in
moves it to `identity-credentials.json` (under the lock), unless that file
already exists. From then on `credentials.json` is either absent or a legacy
session that 0.1.x can use.
- If 0.2.0 later saves a new `credentials.json` while
`identity-credentials.json` exists, 0.2.1 and later ignore it. `whoami`
notes it (`legacyIdentityFileIgnored` in JSON), and `vigilbase logout`
revokes and removes it.
- An Identity login leaves a legacy `credentials.json` alone. A token login or
a legacy device login first revokes and removes any Identity sign-in, so the
new session is the one in use; if that revocation fails, login stops and
nothing changes.
- Logging in again with Identity first revokes and removes the sign-in it
replaces, before asking for a new device code, so cancelling that login
leaves you signed out. If the revocation fails, the CLI warns that the old
sign-in will expire on its own and carries on. A sign-in whose last refresh
had an uncertain result isn't revoked: Identity may have replaced its token
already, and presenting that token again can end every CLI sign-in of yours.
It expires on its own.
- Sign out with 0.2.1 or later: CLI 0.1.x's `logout` only deletes
`credentials.json` and does not touch your Identity sign-in.
### Logging out
`vigilbase logout`:
1. Revokes every saved Identity refresh token, in `identity-credentials.json`
and in a `credentials.json` left by CLI 0.2.0. A sign-in Identity has
already ended (after a browser sign-out, for example) counts as revoked. If
revocation fails otherwise, it keeps every file and stops with
`Identity revocation failed, so your saved sign-in was kept. Try again later.`
2. Signs a legacy session out at the One that issued it. If that fails, it
warns and goes on; the session expires on its own.
3. Deletes the credential files. A file that passes the
[directory checks](#directory-checks) but can't be parsed is removed with a
warning, without being revoked; an unsafe file stops logout and stays in
place.
With nothing saved, logout creates no directories. `logout --json` prints
`{success, cleared, warnings}`: `warnings` lists the warnings text mode prints
on stderr (an unparseable file removed without revoking, a failed legacy
sign-out) and is `[]` when there are none.
Saved Identity credentials belong to one issuer, client and One. If you signed
in with `--auth-url`, `--one-url` or `--client-id`, log out with the same
options; otherwise logout stops, before revoking anything, with
`Saved credentials belong to a different issuer, resource, or client. Use the matching configuration to log out.`
### Refresh and the credentials lock
Identity access tokens last five minutes. The CLI refreshes within 60 seconds
of expiry, or once after a 401. The lock coordinates CLI processes, and each
holder rereads the file before rotating the refresh token.
- A command waits up to 15 seconds (or `--timeout`, if shorter) for a lock
held by a running command, then stops with
``Credentials are locked by another vigilbase command (process <pid>). If none is running, delete <path> and run `vigilbase login`.``
- If the command holding the lock has exited (an interrupted refresh, for
example after Ctrl-C), other commands stop at once with
``A previous vigilbase command was interrupted while it held <path>. Run `vigilbase login` to recover.``
`login` and `logout` replace such a lock, but never one held by a running
command.
- An empty or unreadable lock stops with
``<path> is damaged. Stop every vigilbase command, delete it, and run `vigilbase login`.``
`login` and `logout` replace one older than 30 seconds.
- If a refresh request gets no answer (a timeout or a dropped connection),
Identity may have rotated the token already, so the first error says so:
``The Identity refresh may not have completed (…). Run `vigilbase login` again; its token cannot be retried safely.``
A definite refusal (a 4xx other than `invalid_grant`) leaves the refresh
retryable; a 5xx counts as uncertain.
- An `invalid_grant` answer (for example after a browser sign-out ended the
session) removes `identity-credentials.json`. The command then fails with
``Your saved sign-in was ended by Vigilbase Identity and has been removed. Run `vigilbase login` again.``
(code `SIGN_IN_ENDED`), while `whoami` reports you as signed out (exit 0).
Never reuse a refresh token by hand.
### Directory checks
Commands that read or write credentials (`login`, `logout`, every One command,
`--via one` and the One-only scans, and `whoami` when credentials may be there)
check the whole config path first:
- no component of the path may be a symbolic link;
- every parent directory must be owned by you or root, and not writable by its
group or by others unless it has the sticky bit;
- the config directory must be owned by you with mode `0700`;
- credential files must be regular files owned by you, with one hard link and
mode `0600`;
- on macOS, the config directory and credential files must have no access
control list (the CLI removes inherited entries from what it creates), and no
parent may have an ACL entry that lets another user add, remove or replace
its entries.
Each error names the path that failed and how to fix it, for example:
```
Error: /tmp is a symbolic link. Set VIGILBASE_CONFIG_DIR to a private directory without symbolic links in its path.
Error: /Users/jane/.config/vigilbase must have mode 0700. Run chmod 700 /Users/jane/.config/vigilbase, or set VIGILBASE_CONFIG_DIR to another directory.
Error: /Users/jane/.config/vigilbase has an access control list. Run chmod -N /Users/jane/.config/vigilbase, or set VIGILBASE_CONFIG_DIR to another directory.
Error: /Users/jane/Shared is writable by other users through its access control list. Set VIGILBASE_CONFIG_DIR to a private directory without symbolic links in its path.
```
Paths with spaces, quotes or other special characters are shell-quoted in the
suggested commands.
On macOS `/tmp` and `/var` are symbolic links, and dotfiles managers often make
`~/.config` one. Fix the mode with the `chmod` the error names, or point
`VIGILBASE_CONFIG_DIR` at a private directory of its own, for example:
```bash
export VIGILBASE_CONFIG_DIR="$(cd ~ && pwd -P)/.vigilbase"
```
Don't use a directory inside a dotfiles repository or a synced folder (resolving
a symlinked `~/.config` with `pwd -P` usually leads there): the credential
files hold your refresh token.
Public commands don't need these checks: public scans, `describe`, `skill` and
`badge` never open the config directory, and work even when
`VIGILBASE_CONFIG_DIR` isn't absolute. `list`, `doctor` and `whoami` never
create or open anything in a directory that fails them, and only treat it as a
problem when a credentials file may be there: `list` then shows you as signed
out with one warning, `doctor` reports it in its `signIn` check, and `whoami`
fails with the error. With no saved sign-in, `list` and `doctor` carry on as
usual and `whoami` reports you as signed out (exit 0).
### Windows
Signing in isn't supported on Windows yet, because the CLI can't yet protect
credential files there. `login`, `logout`, `whoami`, the One commands,
`--via one` and the One-only scans stop with
`Signing in isn't supported on Windows yet; public tools and cloudflare-checkup still work.`
(code `SIGN_IN_UNSUPPORTED`) before touching the disk or the network. Public
tools, `list`, `doctor`, `describe`, `skill`, `badge` and `cloudflare-checkup`
work and ignore any saved credentials.
## Configuration
| Option | Environment variable | Default |
| --- | --- | --- |
| `--base-url <origin>` | `VIGILBASE_BASE_URL` | `https://vigilbase.com` |
| `--one-url <origin>` | `VIGILBASE_ONE_URL` | `https://one.vigilbase.com` |
| `--auth-url <origin>` | `VIGILBASE_AUTH_URL` | `https://auth.vigilbase.com` |
| `--client-id <id>` | `VIGILBASE_CLIENT_ID` | `vigilbase-cli` |
| `--timeout <ms>` | — | `60000` per request |
Origins are HTTP(S) URLs without credentials, paths, queries or fragments, and
need HTTPS; HTTP is allowed only for loopback development (`localhost`,
`127.0.0.0/8` or `[::1]`). This applies to `--base-url`, `--one-url` and
`--auth-url`. An empty flag value (`--base-url ""`) is an error; an empty
environment variable counts as unset. `VIGILBASE_API_URL` and
`VIGILBASE_PUBLIC_URL` are older names for the public origin, used after
`VIGILBASE_BASE_URL` when no flag is given; errors about the public origin name
the variable that held the bad value.
Commands check only the origins they use. Public scans, `list`, `describe`,
`skill` and `badge` ignore `--one-url`, `--auth-url` and their variables, and
One-only commands such as `whoami` ignore the public origin. `doctor` checks
both.
| Environment variable | Effect |
| --- | --- |
| `VIGILBASE_CLI_NO_OPEN=1` | Never open a browser |
| `VIGILBASE_CLI_NO_BANNER=1` | Hide the banner |
| `VIGILBASE_CLI_NO_PROGRESS=1` | Turn off progress animations |
**Identity issuer.** The CLI trusts one Identity issuer: `--auth-url` /
`VIGILBASE_AUTH_URL` when set, otherwise `https://auth.vigilbase.com`. The
issuer One names must be exactly that origin, or sign-in stops before any
request to it. `--auth-url` accepts `https://auth.vigilbase.com`, or a loopback
origin (`localhost`, `127.0.0.0/8` or `[::1]`) when `--one-url` is loopback
too. Saved Identity credentials from another issuer count as signed out.
Billing portal URLs must use HTTPS on `billing.stripe.com`. Skill downloads are
limited to HTTPS `vigilbase.com/agent-skills/<name>.md` (or
`www.vigilbase.com`), whatever origin you configure. Every DNS answer must be a
public address, the TLS connection is pinned to a checked address, and
redirects are refused. Skill documents are limited to 256 KiB and API responses
to 8 MiB; timeouts cover reading the body.
## Troubleshooting
**Check connectivity.** `vigilbase doctor` (add `--json` for details) runs
three checks on their own and exits 1 if any fails:
- `publicApi`: `GET https://vigilbase.com/api/v1/agent/tools`.
- `one`: your session. Signed out or with a legacy session,
`GET https://one.vigilbase.com/api/auth/get-session`; a signed-out answer
counts as reachable. With an Identity sign-in, the issuer's
`/.well-known/openid-configuration` and then the userinfo endpoint it names
(`https://auth.vigilbase.com/api/auth/oauth2/userinfo`).
- `signIn`: whether your saved sign-in works, including a refresh if one is
due.
DNS, TLS, connection and timeout failures name the endpoint and the cause. A
connection failure ends with the hint ``Run `vigilbase doctor` for connectivity checks.``,
which `doctor` itself doesn't print. Doctor's `--json` top level includes the
first failing check's `code`. Use `--base-url`, `--one-url`, `--auth-url` and
`--timeout` to check other environments.
**Redirects and blocked ports.** The CLI never follows redirects. An origin
that redirects fails with code `UNEXPECTED_REDIRECT`, naming the origin it
redirects to and the option to set (for example
`… redirected (HTTP 301) to https://www.example.com. Set --base-url to that origin.`).
Node's fetch refuses some ports (the Fetch standard's blocked ports, such as
6000 and 10080); they fail with code `BLOCKED_PORT`. Use another port.
**Proxies.** The CLI uses Node's built-in fetch, which ignores `HTTP_PROXY` and
`HTTPS_PROXY` unless `NODE_USE_ENV_PROXY=1` is set (Node 22.21+ or 24.5+; Node
prints an experimental warning). Skill documents (`skill`, `describe`) are
fetched directly, with DNS pinned to a checked public address, and never go
through a proxy: on a network that allows only proxied connections, `skill`
fails and `describe` shows no docs.
**`Unknown command "cloudflare-checkup"`.** An older global install (0.1.x)
takes priority over a bare `npx @vigilbase/cli`. Update it with
`npm install -g @vigilbase/cli@latest`, or run the latest release once with
`npx @vigilbase/cli@latest cloudflare-checkup`. `vigilbase --version` shows
which version answers.
**`yarn dlx` or `pnpm dlx` runs an older version.** Yarn 4.15 and later and
pnpm 11 and later skip releases published in the last 24 hours by default
(Yarn's `npmMinimalAgeGate`, pnpm's `minimumReleaseAge`). For a day after a
release, `yarn dlx @vigilbase/cli` and `pnpm dlx @vigilbase/cli` run an
older release, and Yarn refuses the new version by number
(`All versions satisfying "…" are quarantined`). pnpm 11 runs a pinned
version (`pnpm dlx @vigilbase/cli@<version>`). pnpm 10.16 and later apply
`minimumReleaseAge` only when you set it, and then refuse a pinned version
released within that time with `ERR_PNPM_NO_MATURE_MATCHING_VERSION`. Use
`npx @vigilbase/cli`, add `--config.minimum-release-age=0` to `pnpm dlx`, or
wait a day.
**`Device sign-in isn't available at <origin> right now.`** Login got a 404
from that origin. If you set `--one-url` or `--auth-url`, check it; otherwise
try again later or email help@vigilbase.com. Public tools work without signing
in.
**`… is a symbolic link`, `… must have mode 0700` and similar.** See
[Directory checks](#directory-checks).
**`A previous refresh has an uncertain result.`** Run `vigilbase login` again.
**`A previous vigilbase command was interrupted while it held …` or
`… credentials.json.lock is damaged.`** Run `vigilbase login`, or delete the
file as the message says (see
[Refresh and the credentials lock](#refresh-and-the-credentials-lock)).
**`Your saved sign-in was ended by Vigilbase Identity and has been removed.`**
You signed out in the browser, or the session ended. Run `vigilbase login`.
**Certificates.** On Node 22.19+ and 24.5+ the CLI adds your operating
system's trusted certificates, keeping Node's bundled roots and
`NODE_EXTRA_CA_CERTS`. This covers private CAs trusted in the macOS Keychain or
the system trust store. See
[Node's TLS documentation](https://nodejs.org/docs/latest-v22.x/api/tls.html#tlssetdefaultcacertificatescerts).
On an older Node 22, `fetch failed` or `SELF_SIGNED_CERT_IN_CHAIN` can be
worked around with:
```bash
NODE_OPTIONS="${NODE_OPTIONS:+$NODE_OPTIONS }--use-system-ca" vigilbase login
```
For a private CA outside the system store, set
`NODE_EXTRA_CA_CERTS=/path/to/trusted-ca.pem` before starting the CLI. The
advice to use Node 22.19+ or 24.5+ appears in TLS errors only when the running
Node couldn't add the operating system's certificates.
The CLI never turns certificate checks off. `NODE_TLS_REJECT_UNAUTHORIZED=0`
does, for every request of the process, including those that carry your One
sign-in; Node then prints a warning. It is not supported: use
`NODE_EXTRA_CA_CERTS` instead.
**Timeouts.** Use `--timeout` for slower queries; some security analytics APIs
take longer than the default.
**Help.** Email help@vigilbase.com or visit <https://vigilbase.com/help>.