CrawlPod

CLI reference

npx ai-visibility audit <url> scores a live page or local build directory against the six-category AI Readiness Engine, and --fail-under <n> turns it into a CI gate. Thirteen commands total as of 0.8.2 — the structural ones below, plus discover/measure/citations/compare/report for brand measurement, each with its own dedicated page linked in the section below. Every command and flag was verified directly against the installed binary's --help output — not copied from the README.

Install and invoke

npx ai-visibility <command>          # no install required
# or
npm install -D ai-visibility && npx ai-visibility <command>

Global flags, from ai-visibility --help:

Usage: ai-visibility [options] [command]

Options:
  -V, --version          output the version number
  -q, --quiet            suppress the CrawlPod footer and other non-essential output
  -h, --help              display help for command

audit — the headline command

Fetches a live URL, or scans a local build directory with --dir, and scores every HTML file it finds against the same ContentAnalyzer the package exports programmatically:

Usage: ai-visibility audit [options] [url]

Arguments:
  url               URL to audit (fetches the live page)

Options:
  --dir <path>      Audit a local build directory instead of a live URL
  --json            Output results as JSON
  --fail-under <n>  Exit with a non-zero code if any score is below this
                    threshold (0-100) — for CI
  -h, --help        display help for command

Real output, run against a plain HTML fixture with a thin body and no structured data:

npx ai-visibility audit --dir ./fixture
🤖 ai-visibility audit

❌ fixture/index.html — 35/100
   Answer placement: 20  Fact density: 25  Headings: 100  E-E-A-T: 0  Snippability: 30  Schema: 0  Crawler access: 100
   🔴 No substantive paragraph found after H1
      Fix: Add a clear, direct answer or description in the first paragraph immediately after your H1
   🔴 Very low fact density: 0.0 facts per 100 words (target: 4-6)
      Fix: Add specific numbers, dates, statistics, or measurable claims to support your content
   🔴 No JSON-LD structured data found
      Fix: Add JSON-LD schema markup using SchemaBuilder from ai-visibility
   ... and 4 more issues

──────────────────────────────────────────────────
Scanned: 1
Average score: 35/100
Passing (≥80): 0 / 1

Powered by CrawlPod — https://crawlpod.com

--fail-under is opt-in — there is no implicit default threshold for audit, unlike lint below. Passing it flips the exit code without changing the report:

npx ai-visibility audit --dir ./fixture --fail-under 80
(same report as above, plus:)

❌ Below threshold: at least one score is under 80

exit: 1

For a live URL, audit also best-effort fetches robots.txt and checks for llms.txt at the same origin (local files, for --dir) to feed the crawlerAccessibilitydimension — a failed or missing fetch is treated as "unknown", never a hard error. --json returns the same shape ContentAnalyzer.analyze() returns programmatically, one entry per file/URL scanned:

npx ai-visibility audit https://example.com --json
{
  "file": "https://example.com/",
  "score": 50,
  "result": {
    "overallScore": 50,
    "breakdown": {
      "answerFrontLoading": 95,
      "factDensity": 25,
      "headingStructure": 100,
      "eeatSignals": 0,
      "snippability": 30,
      "schemaCoverage": 0,
      "crawlerAccessibility": 100
    },
    "issues": [ /* { type, severity, message, fix } */ ],
    "recommendations": [ /* string[] */ ]
  }
}

lint — the CI-friendly shorthand

A thin wrapper around the same audit core with defaults tuned for build-time use — this is the build-time GEO linter, not a separate implementation:

Usage: ai-visibility lint [options]

(shorthand for: audit --dir . --fail-under 50)

Options:
  --dir <path>      Directory to lint (default: ".")
  --json            Output results as JSON
  --fail-under <n>  Exit with a non-zero code if any score is below this
                    threshold (0-100) (default: "50")
  -h, --help        display help for command

Unlike audit, lint gates by default — running it with no flags against the same thin fixture above exits 1 because 35 is under the default threshold of 50.

Wiring it into CI

Both audit --fail-under and lint exit non-zero on failure, so either drops into a CI step directly:

.github/workflows/ci.yml
- name: GEO lint
  run: npx ai-visibility lint --dir ./out --fail-under 60

Run the build directory your framework actually emits (./out for a Next.js static export, ./dist for Vite, etc.) — pointing it at source files instead of build output audits pre-render markup, not what a crawler will actually receive.

robots and llms — top-level aliases

New in 0.5.0: flatter top-level aliases for the two most common generate subcommands. generate robots/generate llms/generate schema still work unchanged — see generate below.

Usage: ai-visibility robots [options]

Options:
  --out <path>       Output path (default: "./public/robots.txt")
  --preset <preset>  allow-all | block-training | block-all
  --block-training   Shorthand for --preset block-training (deprecated, kept for back-compat)
  --sitemap <url>    Sitemap URL to include
  -h, --help         display help for command

Usage: ai-visibility llms [options]

Options:
  --out <path>          Output path (default: "./public/llms.txt")
  --site-name <name>    Site name (default: "My Site")
  --description <desc>  Site description (default: "A website")
  --base-url <url>      Base URL (e.g. https://mysite.com)
  -h, --help            display help for command

--preset block-all is new in 0.5.0 too, alongside the existing allow-all/block-training — it maps to RobotsGenerator.blockAll(), a control mechanism for site owners who want every known AI crawler blocked, not a recommendation either way. See the generators API reference for the underlying class.

--quiet

Every command accepts a global -q/--quiet, new in 0.5.0. Without it, non-JSON output ends with a one-line, dimmed "Powered by CrawlPod" footer — no color, no upsell block. With --quiet, the footer (and other non-essential output) is gone entirely; verified by running the same audit both ways and diffing the output.

generate — pre-existing subcommands

generate, init, analyze, and logs predate 0.5.0 and are unchanged by it (except generate robots gaining the same --preset flag as the new top-level robots alias, since they share one implementation):

Usage: ai-visibility generate [options] [command]

Commands:
  robots [options]  Generate robots.txt with AI crawler rules
  llms [options]    Generate llms.txt for AI model indexing
  schema [options]  Generate JSON-LD schema markup

Usage: ai-visibility generate schema [options]

Options:
  --type <type>      Schema type: faq | product | article | org | person (default: "article")
  --out <path>       Output path (optional, prints to stdout if not set)
  --name <name>      Name/headline
  --price <price>    Price (for product schema)
  --author <author>  Author name
Usage: ai-visibility init [options]

Options:
  --dir <path>        Project directory (default: ".")
  --site-name <name>  Your site name
  --site-url <url>    Your site URL (e.g. https://myapp.com)
  --block-training    Block training bots (CCBot, GPTBot) while allowing search bots

Usage: ai-visibility analyze [options]

Options:
  --dir <path>     Directory to scan (default: ".")
  --file <path>    Analyze a single file
  --json           Output results as JSON
  --min-score <n>  Only show files below this score (default: "101")

Usage: ai-visibility logs [options]

Options:
  --crawler <name>   Filter by crawler name (e.g. GPTBot)
  --days <n>         Show logs from last N days (default: "7")
  --url <path>       Filter by URL path
  --summary          Show summary statistics only
  --log-file <path>  Path to log file (default: "./logs/ai-crawler.json")
  --json             Output as JSON

analyze and audit overlap in purpose — both score HTML for AI readability. audit/lint are the ones worth reaching for now: they add the crawlerAccessibility dimension via robots.txt/llms.txt context, a CI-friendly --fail-under exit code, and JSON output shaped for tooling. analyze remains for its --min-score filter across many files at once.

discover, measure, citations, compare, report

Added in v0.7.0 (discover, measure) and v0.8.0 (citations, compare, report) — the brand-measurement suite, each with its own dedicated docs page covering flags, sample output, and the underlying programmatic API in full:

CommandWhat it doesNeeds API keys?
discoverTemplate-based prompt clusters for a brand/categoryNo
measureQuery configured engines, report visibility with confidence intervalsYes (BYOK)
citationsWhere AI engines learned about your brand, by source typeNo — reads a saved report
compareRanked, evidence-backed reasons each competitor outranks youNo — reads a saved report
reportFull pipeline: audit + discover + measure + citations + compareYes, unless --from

citations, compare, and report all accept --from <file> to load a previously saved measure --json report instead of re-querying engines — see the full report pipeline page for why that matters. Full flags and real sample output for each: discover, measure, citations, compare, report.

See the scoring pagefor what the seven breakdown dimensions mean and how they're weighted, and the API reference for the programmatic ContentAnalyzer equivalent of audit.