> ## Documentation Index
> Fetch the complete documentation index at: https://docs.guardway.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# CLI Reference

> Every gw-cli command and flag — discover, approve, serve, scan, vet, report, schedule, mitm, and demo.

## What this is for

The complete command reference for `gw-cli`. The subcommands cover the full endpoint workflow: inventory the machine (`discover`), record a governance baseline (`approve`), look at the results (`serve`, `report`), score something already on disk (`scan`), vet something before installing it (`vet`), keep the inventory fresh (`schedule`), report to a central console (`enroll`), capture live traffic (`mitm`, macOS), and try the whole pipeline on a seeded demo (`demo`).

For the concepts behind the scores, see [Inventory & Risk Scoring](/discovery/guardway-cli/inventory). For the dashboard, see [Local Dashboard](/discovery/guardway-cli/dashboard).

## Global options

<ParamField path="--data-dir <PATH>" default="~/.guardway">
  Directory for the encrypted spool + key. Applies to every subcommand. Defaults to `~/.guardway` (`%USERPROFILE%\.guardway` on Windows).
</ParamField>

<Note>
  Only one `gw-cli` process can hold the store at a time. Don't run `discover` while `serve` is running — use the dashboard's **Rescan** button instead.
</Note>

## discover

Inventory the AI tools, agent projects, skills, MCP servers, and extensions on the machine, then risk-score each artifact and store the result.

```sh theme={null}
gw-cli discover [--deep] [--root <PATH>] [--report]
```

<ParamField path="--deep">
  Deep, machine-wide scan: walk every folder/project (not just known tool directories) for `SKILL.md` skills and MCP configs, then score each skill. Without it, discovery only visits known tool locations.
</ParamField>

<ParamField path="--root <PATH>" default="$HOME">
  Root directory for the deep walk. Defaults to the user's home directory.
</ParamField>

<ParamField path="--report">
  After scanning, push the findings to the Guardway console. Requires an [enrolled](#enroll) endpoint (a saved API key + console URL); a no-op if unconfigured or air-gapped.
</ParamField>

```sh theme={null}
gw-cli discover --deep                 # full machine inventory + scoring
gw-cli discover --deep --root ~/work   # limit the deep walk to one tree
gw-cli discover --deep --report        # scan, then report to the console (if enrolled)
```

<Note>
  Each `discover` run also compares every artifact against its last-stored baseline and flags **post-approval drift** — a new external host, a dropped version pin, or a risk escalation. See [Post-approval drift](/discovery/guardway-cli/inventory#post-approval-drift).
</Note>

Beyond the base scan, `discover` also checks **isolation posture** (agent `settings.json` files with permission prompts bypassed, wildcard shell allowlists, or dangerous auto-run hooks) and, once a baseline exists, flags anything outside it as **[governance](#approve)** — see [OWASP AST coverage](/discovery/guardway-cli/inventory#owasp-agentic-skills-top-10).

## approve

Record the machine's current inventory as the **approved governance baseline** — every skill, command, subagent, and MCP config from the last `discover`, snapshotted by path + content hash into `<data-dir>/approved.json`. From then on, `discover` flags anything that **appears** or **changes** outside that baseline with a `GOV-UNAPPROVED` finding — even if its content scans clean, because nobody approved it. This is the control behind **OWASP AST09 (Governance)**.

```sh theme={null}
gw-cli approve [--clear]
```

<ParamField path="--clear">
  Remove the baseline instead of writing it — turns governance findings off.
</ParamField>

```sh theme={null}
gw-cli discover --deep     # make sure the inventory is current…
gw-cli approve             # …then snapshot it as the approved baseline
gw-cli approve --clear     # stop flagging drift from the baseline
```

<Note>
  Governance is **opt-in and local** — no baseline file, no `GOV-UNAPPROVED` findings, nothing sent anywhere. Run `approve` only after you have reviewed the inventory; approving artifacts you have not looked at defeats the purpose. Review a flagged item, then re-run `approve` to fold it in. See [Governance](/discovery/guardway-cli/inventory#governance-ast09).
</Note>

## serve

Run the local dashboard (and, on macOS, the runtime tap + redaction). Watches your project folders and rescans within seconds of any change, pruning anything you delete.

```sh theme={null}
gw-cli serve [--port <PORT>] [--no-open]
```

<ParamField path="--port <PORT>" default="8788">
  Base port. The tap listens on `<PORT>`; the **dashboard** is served on `<PORT> + 1` — so the default dashboard URL is `http://localhost:8789`.
</ParamField>

<ParamField path="--no-open">
  Do not auto-open the dashboard in a browser.
</ParamField>

```sh theme={null}
gw-cli serve                # dashboard → http://localhost:8789
gw-cli serve --port 9000    # dashboard → http://localhost:9001
```

<Tip>
  Prefer an always-on service? The packaged `install-service.sh` keeps the dashboard live and auto-updating on file changes, without you keeping a terminal open.
</Tip>

## scan

Score a single skill file or directory that is already on disk, and print its risk.

```sh theme={null}
gw-cli scan <PATH> [--air-gap]
```

<ParamField path="<PATH>" required>
  A skill file or a directory to scan.
</ParamField>

<ParamField path="--air-gap">
  Force air-gap mode: the built-in engine only, zero network (no SkillSpector / OSV egress).
</ParamField>

```sh theme={null}
gw-cli scan ~/.claude/skills/my-skill
gw-cli scan ./some-folder --air-gap
```

## vet

Vet a skill/repo from a git URL **before** installing it. Shallow-clones it into an isolated temp dir, scans every skill/script/MCP artifact, prints a verdict, then deletes the clone. **Nothing is ever executed.** The exit code is non-zero at or above `--fail-on`, so it can gate an install in a script or CI. Aliased as `gw-cli check`.

```sh theme={null}
gw-cli vet <URL> [--ref <REF>] [--air-gap] [--keep] [--json] [--summary] [--fail-on <LEVEL>]
```

<ParamField path="<URL>" required>
  A git/GitHub URL or `owner/repo`. Accepts `owner/repo`, `github.com/owner/repo`, `.../releases/latest`, `.../tree/<branch>`, SSH, and generic `.git` URLs.
</ParamField>

<ParamField path="--ref <REF>">
  Clone a specific branch or tag instead of the default branch.
</ParamField>

<ParamField path="--air-gap">
  Scan with the built-in engine only. The clone still uses the network; the *scan* stays offline (no SkillSpector / OSV egress).
</ParamField>

<ParamField path="--keep">
  Keep the cloned repo instead of deleting it (prints where it landed).
</ParamField>

<ParamField path="--json">
  Emit a single machine-readable JSON verdict on stdout (for CI gating) instead of the human report.
</ParamField>

<ParamField path="--summary">
  Condense output to a digest: the verdict plus finding tallies by category, no per-line dump. Combine with `--json` for a compact JSON. A thorough engine can emit hundreds of findings — this makes them glanceable (e.g. `Memory Poisoning ×114`).
</ParamField>

<ParamField path="--fail-on <LEVEL>" default="high">
  Exit non-zero at or above this risk level. One of `low`, `medium`, `high`, `critical`.
</ParamField>

The verdict is one of **DO NOT INSTALL** / **REVIEW FIRST** / **LIKELY OK** / **CLEAN** — see [Vet verdicts](/discovery/guardway-cli/inventory#vet-verdicts).

Every `vet` also reports **provenance** for the cloned source (OWASP supply-chain): the HEAD commit, whether that commit is cryptographically signed, and whether the vetted ref is **pinned** (an immutable commit SHA or tag) or **mutable** (a branch or the default branch — a later install may fetch different code). It appears in the human report and, with `--json`, as a `provenance` object. Provenance is informational — it never changes the verdict or the exit code.

```sh theme={null}
gw-cli vet github.com/owner/repo                     # a repo (default branch)
gw-cli vet github.com/owner/repo/releases/latest     # a release page → its source tree
gw-cli vet owner/repo --ref v1.2.3                   # pin a branch or tag
gw-cli vet owner/repo --air-gap                       # scan fully offline
gw-cli vet owner/repo && echo "clone + install…"      # only proceeds if the vet passed
gw-cli vet owner/repo --json --summary                # compact machine-readable output for CI
```

<Note>
  `vet` needs `git` on your `PATH` and network access to fetch. The scan itself can stay offline with `--air-gap`.
</Note>

## report

Print a plain-text summary of the encrypted store — the current inventory and per-artifact risk — to the terminal, or push the stored snapshot to the console.

```sh theme={null}
gw-cli report [--push]
```

<ParamField path="--push">
  Push the current stored snapshot to the Guardway console instead of printing a summary. Requires an [enrolled](#enroll) endpoint; also flushes any queued reports from the offline outbox.
</ParamField>

## enroll

Enroll this endpoint with the Guardway console so `discover --report` / `report --push` can send findings. Saves the API key + console URL to `<data-dir>/config.toml` (mode `0600`, never logged).

```sh theme={null}
gw-cli enroll [--key <API_KEY>] [--url <CONSOLE_URL>] [--verify] [--remove]
```

<ParamField path="--key <API_KEY>">
  The endpoint API key from the console (e.g. `sk-ep-…`). Stored `0600`; never logged.
</ParamField>

<ParamField path="--url <CONSOLE_URL>">
  The Guardway console base URL. Defaults to keeping the existing one.
</ParamField>

<ParamField path="--verify">
  After saving, immediately push a test report to confirm the key and connectivity.
</ParamField>

<ParamField path="--remove">
  Remove the saved reporting config instead of writing it (stops reporting).
</ParamField>

```sh theme={null}
gw-cli enroll --key sk-ep-… --url <your-console-url> --verify
gw-cli enroll --remove
```

<Note>
  Reporting is opt-in and fail-safe: nothing is sent unless a key + URL are configured, secrets are redacted at source, `--air-gap` disables it, and a failed push is queued to a local outbox and retried — it never breaks a scan. You can also configure it via the `GUARDWAY_CONSOLE_URL` and `GUARDWAY_API_KEY` environment variables instead of `enroll`.
</Note>

## schedule

Auto-refresh: install (or remove) a scheduled `discover --deep` that runs periodically in the background — launchd on macOS, a systemd `--user` timer on Linux, Task Scheduler on Windows. Each run scans once and exits, so nothing stays resident; the dashboard shows the latest scan whenever you open it.

```sh theme={null}
gw-cli schedule [--interval <CADENCE>] [--at <HH:MM>] [--remove]
```

<ParamField path="--interval <CADENCE>" default="daily">
  How often to refresh: `hourly`, `daily`, or `weekly`.
</ParamField>

<ParamField path="--at <HH:MM>" default="09:00">
  Time of day (24-hour, local) for `daily` / `weekly` runs.
</ParamField>

<ParamField path="--remove">
  Remove the scheduled refresh instead of installing it.
</ParamField>

```sh theme={null}
gw-cli schedule --interval daily --at 09:00     # refresh every morning
gw-cli schedule --interval hourly               # refresh every hour
gw-cli schedule --remove                        # undo
```

## mitm

<Warning>
  macOS only. On Linux and Windows the CLI is a static-analysis build and does not include `mitm`.
</Warning>

Capture **all** apps' LLM traffic (including Claude Desktop) via a userspace TLS-inspection proxy. Auto-configures a local CA + the system HTTPS proxy and reverts both on exit. Only LLM hosts are intercepted; everything else passes through untouched. Prompts are shown **redacted**.

```sh theme={null}
gw-cli mitm [--port <PORT>] [--no-open] [--uninstall]
```

<ParamField path="--port <PORT>" default="8080">
  Proxy port. The capture dashboard is served on `<PORT> + 1` (default `http://localhost:8081`).
</ParamField>

<ParamField path="--no-open">
  Do not auto-open the dashboard.
</ParamField>

<ParamField path="--uninstall">
  Remove the Guardway CA trust + system proxy and exit (cleanup).
</ParamField>

```sh theme={null}
gw-cli mitm                 # trust CA + set system proxy (reverts on Ctrl-C)
gw-cli mitm --uninstall     # remove the CA trust + proxy entirely
```

Node-based CLIs (Claude Code, etc.) ignore the system proxy — route them explicitly:

```sh theme={null}
HTTPS_PROXY=http://127.0.0.1:8080 NODE_EXTRA_CA_CERTS=~/.guardway/guardway-ca.crt claude
```

## demo

Seed a deliberately-risky demo skill, scan it, and store it — see the full pipeline end-to-end with no setup.

```sh theme={null}
gw-cli demo
```

## Related

* [Overview](/discovery/guardway-cli/overview) — what the Guardway CLI is and how to install it.
* [Inventory & Risk Scoring](/discovery/guardway-cli/inventory) — risk levels, engines, verdicts.
* [Local Dashboard](/discovery/guardway-cli/dashboard) — the `serve` dashboard.
