LLMScout

Install β’ Quickstart β’ CLI reference β’ Comparison β’ FAQ β’ Contributing

Runs 21 technical-SEO and GEO (generative-engine-optimization) checks against your site, in pure TypeScript or pure Python, with zero Python interpreter, zero headless browser, and zero external toolchain either way.

Install
LLMScout ships as two independent, complementary distributions. Both run the same 21 checks with the same PASS/WARN/FAIL verdicts, so pick whichever fits your toolchain.
Node/TypeScript (npm):
npm install -g llmscout-cli
llmscout init ./my-site --site-url https://example.com
llmscout check ./my-site
The CLI targets Node 18+ (declared in package.json engines). The two runtime dependencies are cheerio (HTML parsing) and commander (argument parsing): there is no Python interpreter, no pip install, and no Playwright/Chromium download anywhere in the npm install.
[!NOTE]
The npm install pulls in undici as a transitive dependency of cheerio. npm audit has flagged a high-severity advisory against it in the past; package.json's overrides block pins undici (and js-yaml/nanoid) to patched ranges to close it. Run npm audit after install to confirm your resolved tree is clean.
Python (PyPI):
pip install llmscout-cli
llmscout init ./my-site --site-url https://example.com
llmscout check ./my-site
Zero runtime dependencies -- HTML parsing and HTTP fetching both use only the Python standard library. See python/README.md for the full Python-specific guide.
Then, in any project you want to check:
That scaffolds a llmscout.json config and a small Claude Code skill file into the target directory. Set your site URL and run llmscout check ..
Quickstart
Scaffold a config and run a check against a live site:
llmscout init ./my-site --site-url https://example.com
llmscout check ./my-site
Real output from llmscout check against https://example.com:
LLMScout check -- https://example.com
[PASS] (technical) Title tag
Title "Example Domain" is 14 characters, within the recommended 10-60 range.
[WARN] (technical) Meta description
No meta description found.
Fix: Add <meta name="description" content="..."> with 50-160 characters summarizing the page.
[WARN] (technical) Canonical tag
No <link rel="canonical"> tag found.
Fix: Add a canonical link tag pointing at the preferred URL for this page.
[FAIL] (technical) robots.txt
robots.txt was not reachable at https://example.com/robots.txt (HTTP 404).
Fix: Add a robots.txt file at your site root, even a permissive one, so crawlers and agents have explicit directives.
[WARN] (technical) sitemap.xml
No sitemap was reachable (tried: https://example.com/sitemap.xml).
Fix: Add a sitemap.xml at your site root, or point to one with a Sitemap: directive in robots.txt, to help search engines discover pages.
[PASS] (technical) Heading structure
Exactly one <h1> and no skipped heading levels detected.
[PASS] (technical) Image alt coverage
No <img> tags found on the page.
[WARN] (technical) Open Graph tags
No Open Graph tags found.
Fix: Add Open Graph meta tags (og:title, og:description, og:image, og:url) so shared links render rich previews on social platforms.
[WARN] (technical) Twitter/X Card tags
No twitter:card meta tag found.
Fix: Add <meta name="twitter:card" content="summary_large_image"> (or another valid card type) so links render rich previews on X/Twitter.
[WARN] (technical) Meta robots directives
No meta robots directives found; default Google Search snippet/preview limits will apply.
Fix: Add <meta name="robots" content="max-snippet:-1, max-image-preview:large, max-video-preview:-1"> to control search snippet appearance.
[PASS] (technical) Image weight
No <img> tags with an http(s) src to measure.
[PASS] (technical) Redirect chain
The homepage resolved with no redirects.
[WARN] (geo) Structured data (JSON-LD)
No JSON-LD structured data found.
Fix: Add schema.org JSON-LD markup (e.g. Organization, WebSite, or Article) so generative engines can understand the page's entities.
[WARN] (geo) llms.txt
No llms.txt found at https://example.com/llms.txt.
Fix: Optional: add an llms.txt at your site root summarizing the site for LLM-based agents (see llmstxt.org).
[WARN] (geo) AI crawler directives
robots.txt is unreachable, so AI-crawler directives could not be determined.
Fix: Add a reachable robots.txt if you want to state an explicit policy for AI crawlers (GPTBot, OAI-SearchBot, ClaudeBot, Claude-SearchBot, PerplexityBot, Google-Extended, Applebot-Extended).
[WARN] (geo) FAQ schema
No FAQPage structured data found.
Fix: If this page has an FAQ section, mark it up with FAQPage JSON-LD so generative engines can surface individual answers.
[PASS] (geo) Content extraction friendliness
Found 1 heading(s) and 1 structured text block(s); content appears reasonably extractable. (Heuristic: cannot assess semantic quality or JS-rendered content.)
[WARN] (geo) Speakable schema
No Speakable structured data found.
Fix: If this page has content suited for voice assistants, add a "speakable" SpeakableSpecification to its JSON-LD so voice search can surface it.
[WARN] (geo) Organization schema
No Organization/Corporation/LocalBusiness/Person structured data found.
Fix: Add Organization (or Person) JSON-LD with a sameAs array of your official social/profile URLs to strengthen Knowledge Panel signals.
[WARN] (geo) Markdown content negotiation
Requesting https://example.com/ with "Accept: text/markdown" returned Content-Type "text/html" instead of text/markdown.
Fix: Optional: serve a text/markdown representation of pages when the client sends "Accept: text/markdown" so LLM-based agents can fetch clean Markdown directly instead of parsing HTML.
[WARN] (geo) Link header (RFC 8288)
The homepage does not send a Link response header.
Fix: Optional: add an RFC 8288 Link response header (e.g. <https://example.com/feed>; rel="alternate") to advertise machine-readable service-discovery endpoints to crawlers and AI agents.
Summary: 6 PASS, 14 WARN, 1 FAIL (21 checks)
The same run with --json:
llmscout --json check ./my-site
{
"siteUrl": "https://example.com",
"summary": {
"pass": 6,
"warn": 14,
"fail": 1,
"total": 21
},
"results": [
{
"id": "title",
"name": "Title tag",
"category": "technical",
"status": "PASS",
"message": "Title \"Example Domain\" is 14 characters, within the recommended 10-60 range."
}
]
}

check exits 0 when no check FAILs, 1 when at least one check FAILs (WARN alone does not fail the run), and 2 on a usage error such as a missing or misconfigured llmscout.json.
Features