llm-citeops
v1.0.4
Published
A CLI tool that audits web content for AEO and GEO scores
Maintainers
Readme
llm-citeops
llm-citeops is a CLI for auditing whether web content is ready for answer engines and generative search.
It helps teams answer a simple question:
If this page is crawled, summarized, or cited by AI systems, is it actually ready?
The package reads a page, runs a deterministic AEO and GEO rubric, computes weighted scores, and produces reports with evidence and suggested fixes.

Why people use it
Good SEO does not automatically mean good AI visibility.
A page can rank, but still be weak when a model looks for:
- direct answers
- clear structure
- trust and authorship signals
- fresh metadata
- supporting citations
- comparison-friendly content
llm-citeops gives you one report that is useful to both sides of the team:
- business users get a simple score and a readable summary
- operators get evidence, failed checks, and concrete fixes
What you get
The CLI currently provides:
llm-citeops overviewllm-citeops infollm-citeops audit
Inputs:
- URL
- local Markdown or HTML file
- local folder of content files
- sitemap or sitemap index
Outputs:
- HTML for human review
- JSON for automation
- CSV for batches
What it checks
The current audit rubric contains 12 checks.
AEO
- FAQ or HowTo schema
- direct answer in the first paragraph
- Q&A density
- readability
- named entities
- author byline
GEO
- topical depth
- trust signals
- content freshness
- external citations
- comparison content
- citation likelihood
These checks are deterministic heuristics over parsed HTML and extracted text. The package does not use an LLM to decide whether a page passes.
Try it quickly
Fastest way to understand the product:
- website and playground: llm-citeops.vercel.app
- npm package: llm-citeops on npm
- source code: GitHub repo
Run without installing globally:
npx llm-citeops overviewInstall globally:
npm install -g llm-citeopsAudit one live page:
llm-citeops audit --url "https://example.com/docs/article" --output html --output-path ./report.htmlAudit one local file:
llm-citeops audit --file ./examples/sample.html --output json --output-path ./report.jsonAudit a folder:
llm-citeops audit --dir ./examples --output csv --output-path ./batch.csvAudit a sitemap:
llm-citeops audit --sitemap "https://example.com/sitemap.xml" --output csv --output-path ./site.csvHow it works
The workflow is intentionally simple:
- Read content from a URL, file, folder, or sitemap
- Normalize and parse the content
- Run the AEO and GEO checks
- Compute
aeo,geo, andcompositescores - Attach recommendations for failed or warning checks
- Write a report in HTML, JSON, or CSV
The score bands are:
poorneeds-improvementgoodexcellent
By default, AEO contributes 50% and GEO contributes 50% to the composite score.
Best practices
Start with one page before running a folder or sitemap audit. It is much easier to validate the rubric and review the recommendations on a known page.
Use html when a person will read the report. Use json or csv when another tool will consume it.
Use csv for real batch runs. It is the only format that currently emits every page in a folder or sitemap audit.
Treat the score as a prioritization signal, not a guarantee. This package is designed to help you improve content quality systematically, not to promise ranking or citation outcomes.
If your site is heavily client-rendered, audit the rendered HTML output or local exports when possible. The current implementation does not run a browser.
Respect robots.txt, rate limits, and site terms when auditing third-party URLs.
Command reference
llm-citeops overview
llm-citeops info
llm-citeops audit [options]
--url <url>
--file <path>
--dir <path>
--sitemap <url>
--output <format> html | json | csv
--output-path <path>
--threshold <n>
--ci
--ignore-robots
--depth <n>
--rate <n>
--config <path>
--probe
--models <list>
--compare <url>Current implementation notes:
--probeexists, but probe mode is not implemented yet--compareexists, but compare mode is not implemented yet--depthis accepted, but the current crawler does not use it yethtmlandjsoncurrently write only the first report for folder and sitemap runs
CI and configuration
Fail a run when the score drops below a threshold:
llm-citeops audit --url "$DEPLOY_URL" --ci --threshold 70 --output json --output-path ./citeops-report.jsonExit codes:
| Exit code | Meaning | |-----------|---------| | 0 | Success | | 1 | CI failure | | 2 | Crawl or runtime error | | 3 | Invalid input or config |
Optional config loading order:
--config <path>.citeops.jsonin the current project.citeops.jsonin the home directory
Example:
{
"audit": {
"aeo_weight": 0.5,
"geo_weight": 0.5,
"custom_weights": {
"faq_schema": 1.5,
"direct_answer": 1.5,
"citation_likelihood": 1.3
}
},
"ci": {
"threshold": 70,
"fail_on_drop": true
}
}Test it locally
git clone https://github.com/rakeshcheekatimala/llm-citeops.git
cd llm-citeops
npm install
npm run lint
npm run build
npm test
npm run test:coverageUseful smoke tests:
node dist/index.js audit --file ./examples/sample.html --output html --output-path ./sample-report.html
node dist/index.js audit --file ./examples/sample.md --output json --output-path ./sample-report.json
node dist/index.js audit --dir ./examples --output csv --output-path ./examples-report.csvCoverage artifacts are written to:
Releases
Releases are automated with semantic-release from main.
Version bumps follow conventional commits:
fix:for patch releasesfeat:for minor releasesfeat!:orBREAKING CHANGE:for major releases
Preview the next version locally:
npm run release:dry-runsemantic-release itself requires Node 24 for the release step, so the local dry run uses an ephemeral Node 24 runtime even if day-to-day development stays on Node 18 or 20.
The release workflow runs typecheck, build, and tests, then publishes to npm and creates a GitHub release when the commit history since the last tag contains a releasable change.
Project health
Latest verified local snapshot on 2026-04-10:
| Metric | Status |
|---|---|
| Typecheck | npm run lint |
| Build | npm run build |
| Tests | 32/32 passing |
| Coverage | 95.06% lines, 82.33% branches, 89.07% functions |
| Bundle size | 61,331 bytes for dist/index.js |
Docs
Limitations
Current known limits:
- no browser rendering for JavaScript-heavy pages
- no implemented probe workflow yet
- no implemented compare workflow yet
- no recursive local directory traversal
- no aggregated HTML or JSON output for multi-page batch runs
License
MIT
