Skip to main content

Zero-dependency, cross-platform LLM/GEO/AEO checker CLI — 21 checks, pure Python stdlib, no runtime dependencies.

Project description

llmscout-cli (Python)

Zero-config SEO and GEO (generative engine optimization) checker: 21 checks against a live site, plus a multi-site fleet mode for agencies checking several client sites at once, in pure Python with no extra runtime toolchain -- no headless browser, no separate interpreter to provision.

PyPI version License: MIT Python versions CI npm version

Why this exists

LLMScout checks a website for 21 technical-SEO and GEO issues -- title/meta description length, canonical tags, robots.txt/sitemap.xml reachability (with a robots.txt Sitemap: fallback), heading structure, image alt coverage and weight, Open Graph and Twitter Card tags, meta robots directives, redirect-chain health, JSON-LD structured data, llms.txt, AI-crawler directives (training and search crawlers tracked separately -- GPTBot/OAI-SearchBot, ClaudeBot/Claude-SearchBot, PerplexityBot, Google-Extended, Applebot-Extended), FAQ schema, Speakable schema, Organization schema, Markdown content negotiation, an RFC 8288 Link header, and content-extraction friendliness -- and reports PASS/WARN/FAIL with a fix suggestion for anything short of a clean pass. This package is the Python distribution of the tool: a genuine, independent port of the npm CLI's logic, not a wrapper around the Node binary. It ships with zero runtime dependencies -- HTML parsing and HTTP fetching both use only the Python standard library.

Install

pip install llmscout-cli

or with uv:

uv add llmscout-cli

The complementary JS/TS distribution installs from npm: npm install -g llmscout-cli -- see the project README for that package. Both packages read the same 21-check spec and are intended to report the same PASS/WARN/FAIL verdicts for the same site; neither is deprecated in favor of the other.

Quickstart

llmscout init ./my-site --site-url https://example.com
llmscout check ./my-site

init scaffolds a llmscout.json config (and a Claude Code skill file) in the target directory; check runs all 21 checks against the configured siteUrl and prints a PASS/WARN/FAIL line per check plus a summary. Pass --json before the subcommand for structured output an agent can parse:

llmscout --json check ./my-site

Or call the library directly (the agent-native path, no subprocess):

from llmscout import load_site, run_checks, ALL_CHECKS

ctx = load_site("https://example.com")
results = run_checks(ALL_CHECKS, ctx)
for r in results:
    print(f"[{r.status}] ({r.category}) {r.name}: {r.message}")

How it works

llmscout.json -> site URL -> fetch homepage + robots.txt + sitemap.xml + llms.txt (parallel)
   -> 21 checks (12 technical + 9 GEO) run against the shared fetched context
   -> PASS / WARN / FAIL per check -> exit code (0 clean / 1 any FAIL / 2 usage error)

Full data model, the 21 checks explained, and fleet-mode semantics are in docs/concepts.md and docs/getting-started.md. The checks are reimplemented as genuine Python logic against the same check contract the npm package uses (Check.run(ctx) -> CheckResult) -- see those docs for what each check actually verifies.

The 21 checks

Each check reports PASS, WARN, or FAIL, with a fix suggestion for anything that is not a clean PASS. A WARN is a missed optimization, not a broken page, and never fails the run on its own.

Technical SEO (12)

Check (id) What it verifies
Title tag (title) A <title> exists and is within 10-60 characters.
Meta description (meta-description) A <meta name="description"> exists and is within 50-160 characters.
Canonical tag (canonical) A <link rel="canonical"> exists and its href is a valid URL (relative hrefs are resolved, not penalized).
robots.txt (robots-txt) /robots.txt is reachable and contains at least one User-agent directive.
sitemap.xml (sitemap-xml) /sitemap.xml is reachable and valid, with a Sitemap: directive in robots.txt checked as a fallback location.
Heading structure (heading-structure) Exactly one <h1>, and no skipped heading levels.
Image alt coverage (image-alt) <img> tags have an alt attribute (an intentional alt="" for decorative images counts as covered).
Open Graph tags (open-graph) og:title, og:description, og:image, and og:url meta tags are present.
Twitter/X Card tags (twitter-card) A valid twitter:card meta tag and its required companion fields are present.
Meta robots directives (robots-meta-directives) Advanced snippet-control directives (max-snippet, max-image-preview, max-video-preview) are set, and flags an outright noindex.
Image weight (image-weight) Each image's actual byte size (via a HEAD request), flagging oversized images that slow page load.
Redirect chain (redirect-chain) The homepage's full redirect chain, warning on long chains and failing if the chain dead-ends in an error status.

GEO / generative engine optimization (9)

Check (id) What it verifies
Structured data (structured-data) JSON-LD <script type="application/ld+json"> blocks exist and parse as valid JSON.
llms.txt (llms-txt) An /llms.txt is present at the site root (an emerging, non-standardized convention; absence is informational).
AI crawler directives (ai-crawler-directives) Reports the robots.txt allow/disallow state for GPTBot, OAI-SearchBot, ClaudeBot, Claude-SearchBot, PerplexityBot, Google-Extended, and Applebot-Extended. This is a report of what is configured, never a recommendation to allow or block.
FAQ schema (faq-schema) FAQPage JSON-LD is present (informational; only relevant to pages that actually have an FAQ).
Content extraction friendliness (content-extraction) Heuristic: the page has heading/paragraph structure an engine can chunk, rather than one large unstructured block. It cannot see content that only appears after client-side JavaScript, by design.
Speakable schema (speakable-schema) A SpeakableSpecification is present in JSON-LD, for voice-assistant answer eligibility.
Organization schema (organization-schema) Organization/Person JSON-LD with a sameAs array of official profile URLs is present, for Knowledge Panel signals.
Markdown content negotiation (markdown-negotiation) Whether the site serves a text/markdown representation when requested via Accept: text/markdown content negotiation.
Link header (link-header) Whether the homepage response sends an RFC 8288 Link header for machine-readable service discovery.

You can run only one category by editing the checks block in llmscout.json ({ "checks": { "technical": true, "geo": false } }).

CLI reference

Transcribed from the tool's own --help output.

$ llmscout --help
usage: llmscout [-h] [-V] [--json] [--user-agent USER_AGENT]
                {init,check,fleet} ...

Zero-config, cross-platform SEO and GEO checks for local projects, with no
extra runtime toolchain.

positional arguments:
  {init,check,fleet}
    init                Scaffold a LLMScout setup (llmscout.json + a Claude
                        Code skill file) into a target directory
    check               Run SEO/GEO checks against a local project's
                        configured site
    fleet               Run the full check suite against every site listed in
                        a fleet manifest

options:
  -h, --help            show this help message and exit
  -V, --version         show program's version number and exit
  --json                output structured JSON instead of human-readable text
  --user-agent USER_AGENT
                        override the default User-Agent header sent on
                        outbound fetches
Command Argument Options Purpose
init <path> target directory --site-url <url> set siteUrl immediately Scaffold llmscout.json plus a Claude Code skill file. Idempotent: existing files are left untouched.
check <path> project directory containing llmscout.json --out-dir <dir> also write an auto-named report file for this site; (global --json, --user-agent) Run the selected checks against the configured siteUrl.
fleet <config.json> fleet manifest --out-dir <dir> also write one auto-named report file per site, named from the manifest's name field; (global --json, --user-agent) Run the full suite against every site in the manifest.

--json, --user-agent, -V/--version, and -h/--help are the only global options.

Exit codes

Code Meaning
0 init succeeded, or check/fleet completed with no FAIL.
1 check: at least one check FAILed. fleet: at least one site FAILed or errored.
2 Usage error: invalid URL scheme, missing/unreadable/invalid llmscout.json, blank siteUrl, missing manifest, or any other configuration error.

Fleet mode

llmscout fleet ./fleet.json

Runs the full 21-check suite against every site declared in a local JSON manifest ({"sites": [{"name": ..., "path": ...}]}) in one invocation -- local filesystem only, no SSH, no remote execution. Aimed at agencies or teams checking several client repos side by side. Add --out-dir ./reports to also write one auto-named report file per site, named from the manifest's name field.

CI integration

- uses: actions/checkout@v4
- uses: actions/setup-python@v5
  with:
    python-version: '3.12'
- run: pip install llmscout-cli
- run: llmscout check ./my-site --json > results.json

Full walkthrough in docs/integrations/ci.md.

Comparison

Every cell below is drawn from a verifiable source (a repo file, a package manifest, or an open issue), cited under the table. "Checker" means the tool audits an existing live site; "generator" means it emits SEO/GEO asset files for you to publish.

LLMScout (Python) claude-seo (AgriciDaniel) geo-seo-claude (zubair-trabzada) geo-optimizer-skill (Auriti-Labs)
Runtime dependencies Zero (stdlib only) Python 3.10+, Playwright optional Python 3.x, Playwright optional Python 3.9+
Requires Playwright / headless browser No Optional (Chromium auto-installed by install.sh for SPA rendering) Optional, for some checks Not required for core function
Install pip install llmscout-cli or uv add llmscout-cli git clone + install.sh / install.ps1, or Claude Code /plugin git clone + install.sh / install-win.sh pip install or uvx
Cross-platform / Windows out of the box Yes (stdlib only, no shelling out) Ships a Windows install.ps1, but fresh-install/Windows/path failures are a recurring pattern: issues #137, #138, #139 Windows install pain is a recurring pattern here too: issues #69, #21, #3 pip/uv are cross-platform; not verified further
AI-crawler bot coverage 7 bots, training and search crawlers tracked separately (GPTBot/OAI-SearchBot, ClaudeBot/Claude-SearchBot, PerplexityBot, Google-Extended, Applebot-Extended) Not a dedicated check Not a dedicated check Not verified
Markdown content negotiation check Yes (markdown-negotiation) No No No
Role Checker Checker Checker + report generator Checker
Coverage Technical + GEO (21 checks) Technical + GEO (broad) GEO-focused Technical + GEO
License MIT MIT Not verified MIT

Sources: LLMScout, from this package's pyproject.toml (dependencies = []) and src/llmscout/. claude-seo, from its README install section and open issues #137/#138/#139. geo-seo-claude, from its README and issue tracker (#69, #21, #3). geo-optimizer-skill, from its README (Python 3.9+, pip install/uvx, MIT).

The complementary npm/TypeScript distribution of LLMScout has its own comparison table with the same competitors in the main project README.

Security

llmscout's fetch layer only ever dials http(s), follows redirects manually one hop at a time, refuses to follow a redirect whose Location targets a non-http(s) scheme, and bounds the redirect chain at 5 hops so a redirect loop can't hang the process -- see SECURITY.md for the full policy and how to report a vulnerability. Honest note: this project does not currently publish SLSA provenance, Sigstore signatures, or an SBOM, and has no OpenSSF Scorecard badge set up -- none of that infrastructure exists yet for either distribution, so it isn't claimed here.

FAQ

Does this package require Node.js or the npm distribution? No. llmscout-cli on PyPI is a genuine, independent Python port with zero runtime dependencies -- not a wrapper around the npm CLI. It runs the same 21 checks with the same PASS/WARN/FAIL verdicts.

Does it use Playwright or a headless browser? No. HTML parsing and HTTP fetching both use only the Python standard library. There is no Chromium download and no subprocess call anywhere in the checks. The trade-off is that the content-extraction check reads static HTML only and cannot see JavaScript-rendered content -- it says so in its own result message.

How is this different from claude-seo or geo-seo-claude? Both of those are Claude Code skills that shell out to Python scripts (and, for some checks, Playwright-based rendering) from skill instructions. That external-toolchain-plus-path-resolution chain is the root cause behind a recurring pattern of install/Windows/path bugs filed against both projects -- see the Comparison table above for the specific open issues. llmscout-cli runs checks inside the host process instead, so that failure class does not exist here.

Does it need my own API keys? No. There is no LLM call anywhere in the check pipeline -- every check is a deterministic HTML/HTTP inspection (parsing tags, following redirects, checking headers). No account, API key, or external service is required to run it.

Is this safe to run against a production site? Yes. The fetch layer only ever dials http(s), refuses to follow a redirect whose Location targets a non-http(s) scheme, and bounds the redirect chain at 5 hops so a redirect loop can't hang the process. It only ever performs GET/HEAD requests; it never submits forms, follows links beyond the declared entry points, or writes anything to the target site. See Security above for the full policy.

Can I use this from an agent, not just a human running the CLI? Yes, two ways: pass the global --json flag to any command for structured output (id, status, message, fix fields plus a summary), or import the library directly (from llmscout import load_site, run_checks, ALL_CHECKS) with no subprocess call at all -- see Quickstart.

Is this a library or just a CLI? Both. The llmscout console script is the CLI entry point, and the same package is directly importable for programmatic use (load_site, run_checks, select_checks, ALL_CHECKS, TECHNICAL_CHECKS, GEO_CHECKS).

Can I run it against many sites at once? Yes. llmscout fleet manifest.json runs the full suite against every site in a local JSON manifest in one invocation, and --out-dir writes one auto-named report file per site instead of one combined stdout dump -- built for agencies checking many client sites.

What Python versions are supported? 3.9 through 3.13, per this package's classifiers. No third-party runtime dependencies means there's nothing else to version-match.

Can I use this commercially, or in a closed-source project? Yes. MIT licensed (see License below): use, modify, and redistribute in commercial and closed-source work, with no royalty and no obligation to open-source anything it checks.

Contributing

See CONTRIBUTING.md.

cd python
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest

License

MIT, see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

llmscout_cli-0.3.3.tar.gz (54.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

llmscout_cli-0.3.3-py3-none-any.whl (59.1 kB view details)

Uploaded Python 3

File details

Details for the file llmscout_cli-0.3.3.tar.gz.

File metadata

  • Download URL: llmscout_cli-0.3.3.tar.gz
  • Upload date:
  • Size: 54.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.13

File hashes

Hashes for llmscout_cli-0.3.3.tar.gz
Algorithm Hash digest
SHA256 c2516b94511b44edf25caceb404a10a4020ae1052b4feb81ff2f02900bb97a33
MD5 6abd40f0f1440fc5c4149917574250f3
BLAKE2b-256 45e086de520167f706d287a6f2ddaf5d888dd0b1b50409466bc458696a522f30

See more details on using hashes here.

File details

Details for the file llmscout_cli-0.3.3-py3-none-any.whl.

File metadata

  • Download URL: llmscout_cli-0.3.3-py3-none-any.whl
  • Upload date:
  • Size: 59.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.13

File hashes

Hashes for llmscout_cli-0.3.3-py3-none-any.whl
Algorithm Hash digest
SHA256 1d9fd4ebe3ba4d8733801ab5b5698a9e71f0dd6266bcdfce68d11dd152321272
MD5 4bc2ab560199a39ec6891192fead5e35
BLAKE2b-256 9587d5bb34616491a3706e05131f6937be3fe3fa5fdb7ccb22877657c2f5be3c

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page