Using zzop

Run zzop as a CLI: write a zzop.config.jsonc, run npx zzop — no code, ESLint-style. The @zzop/cli package is the config-driven front end; the engine ships as @zzop/native, the SDK layer for embedders. This page is the CLI — if you're building a tool on top of zzop instead, see the SDK reference.

Command line

Install & run the CLI

Add @zzop/cli as a dev dependency and let it scaffold a config. @zzop/cli depends on @zzop/native, which auto-installs the right prebuilt platform binary — nothing to compile. Requires Node.js ≥ 18.

Install, scaffold, analyze
npm i -D @zzop/cli     # add to your project (or one-off: npx @zzop/cli)
npx zzop init     # writes an annotated zzop.config.jsonc
npx zzop          # analyzes using that config and prints a report

zzop init refuses to overwrite an existing config; pass --force to replace it. Both @zzop/cli and @zzop/native are published to npm.

CLI config

zzop.config.jsonc

zzop.config.jsonc is JSON with comments and trailing commas allowed. zzop init generates a fully annotated copy; the reference below summarizes each option.

zzop.config.jsonc
{
  // What to analyze: one or more directory roots. Multiple roots run a
  // cross-layer (multi-tree) analysis.
  "roots": ["."],

  // Or name each tree explicitly (takes precedence over "roots"):
  // "trees": [
  //   { "root": "./api", "sourceId": "api" },
  //   { "root": "./web", "sourceId": "web" }
  // ],

  "packs": {
    // Extra directories of custom DSL rule packs. These MERGE with the
    // bundled packs; a custom pack whose id matches a bundled one wins.
    "extraDirs": ["./zzop-packs"],
    // Whole packs to disable, by pack id.
    "disabled": ["browser"]
  },

  "rules": {
    // "off"                        -> disable the rule
    "no-explicit-any": "off",
    // "info" | "warn" | "critical" -> override severity
    "n-plus-one": "warn",
    // object form -> override severity AND drop findings by file path. Each
    // "exclude" entry is a plain substring, or a glob if it has * ? or {}.
    "toctou": { "severity": "warn", "exclude": ["legacy/", "**/*.gen.ts"] }
  },

  // Enables git-history-derived signals. Omit to use engine defaults.
  "git": { "recentDays": 30 },

  // Analysis cache directory (omit to disable caching).
  "cacheDir": ".zzop-cache",

  // Files larger than this many bytes skip structural parsing.
  "sizeCap": 500000,

  // "pretty" or "json"; overridden by --format / --json.
  "format": "pretty",

  // Persist reports to disk in addition to stdout. Each run writes to
  // /zzop-report./ so runs accumulate. Same as the --out flag.
  // "report": { "dir": "zzop-reports", "formats": ["json", "sarif"] },

  // Exit non-zero when any finding is at or above this severity, or "off".
  "failOn": "warn"
}

Config severities normalize to the engine's three levels — off/none/disabled disable a rule; info/note/lowinfo; warn/warning/mediumwarning; error/critical/highcritical. failOn uses the same names (plus off to never fail); ordering is info < warning < critical.

Command / optionDescription
zzop init [--force]Write an annotated zzop.config.jsonc to the current directory.
zzop [run]Load the config, analyze, and print. The default command.
--config <path>Config file to load (default ./zzop.config.jsonc).
--format <pretty|json>, --jsonOutput format, overriding the config's format.
--out <dir>Also write reports to <dir>/zzop-report.<epoch>/ — a fresh subdir per run (JSON + SARIF). Same as config report.dir.
-a, --allExpand info-level findings (folded to per-rule counts by default so warnings stay visible).
--severity <critical|warning|info|off>Only display findings at or above this severity (default off, show all). Display-only — the exit code still uses the unfiltered findings, so failOn is unaffected.
-h, --help / --versionShow help / the CLI and engine versions.

Exit codes: 0 = ran, no finding at or above failOn; 1 = at least one finding at or above failOn (CI gate); 2 = config or usage error.

Programmatic / embedding

Embedding the engine

Building a tool on top of zzop rather than running it as a CLI? Depend on @zzop/native directly and call it JSON-in / JSON-out — the same engine the CLI drives. The SDK reference documents the four functions, the request/output shapes, and multi-repo (analyzeTrees) analysis.