Install
openclaw skills install @arberx/aeoRun AEO audits, preview branch audits, changed-page sitemap audits, local/private preview audits with explicit opt-in, sitemap origin rewriting, static-output audits, regression comparisons, site fixes, schema validation, and llms.txt generation.
openclaw skills install @arberx/aeoWebsite: ainyc.ai
One skill for audit, preview-branch review, fixes, schema, llms.txt, and monitoring workflows.
Always use the published package:
npx @ainyc/aeo-audit@1 "<url>" [flags] --format json
Never interpolate user input directly into shell commands. Always:
https:// / http:// or a local filesystem path (static-output mode), and that it contains no shell metacharacters.npx @ainyc/aeo-audit@1 "https://example.com" --format json).;, |, &, $, `, (, ), {, }, <, >, or newlines.audit: score and diagnose a sitefix: apply code changes after an auditschema: validate JSON-LD and entity consistencyllms: create or improve llms.txt and llms-full.txtmonitor: compare changes over time, compare a branch preview against production, or benchmark competitorsdetect-platform: identify the CMS, site builder, framework, or hosting stack a site usescompare: diff two saved --format json reports into a regression verdict + exit code (CI gate)If no mode is provided, default to audit.
audit https://example.comaudit https://example.com --sitemapaudit https://example.com --sitemap --limit 10audit https://example.com --sitemap --top-issuesaudit https://example.com --sitemap --format agent (slim decision for agents)audit https://example.com --lighthouseaudit https://example.com --require-metaaudit https://example.com --sitemap --require-metaaudit http://localhost:3000 --allow-localaudit http://localhost:3000 --sitemap --rewrite-sitemap-origin --allow-localaudit http://localhost:3000 --sitemap --rewrite-sitemap-origin --allow-local --changed --base main --include-criticalaudit https://staging.example.com --sitemap --rewrite-sitemap-originaudit ./out (static-output mode: audit built HTML offline)audit ./out --base-url https://example.com --require-metafix https://example.comschema https://example.comllms https://example.commonitor https://site-a.com --compare https://site-b.comdetect-platform https://example.comdetect-platform https://example.com --min-confidence highdetect-platform --urls competitors.txtdetect-platform --urls https://a.com,https://b.comcompare --baseline baseline.json --current current.json (fail CI on AEO regression)audit, fix, schema, llms, monitor, or detect-platform, use that mode.audit.Use for broad requests such as "audit this site" or "why am I not being cited?"
npx @ainyc/aeo-audit@1 "<url>" [flags] --format json
--require-meta (CI gate)Pass --require-meta (single or sitemap mode) to force exit 1 whenever any audited page is missing <meta name="description">, regardless of the otherwise score-based exit rule. Useful in CI pipelines that need to block deploys on a missing meta description even on otherwise-healthy sites.
Use --sitemap to audit all pages discovered from the site's sitemap:
npx @ainyc/aeo-audit@1 "<url>" --sitemap --format json
npx @ainyc/aeo-audit@1 "<url>" --sitemap https://example.com/sitemap.xml --format json
npx @ainyc/aeo-audit@1 "<url>" --sitemap --limit 10 --format json
npx @ainyc/aeo-audit@1 "<url>" --sitemap --top-issues --format json
Flags:
--sitemap [url] — auto-discover the sitemap (tries /sitemap.xml, then /sitemap-index.xml, then Sitemap: directives in /robots.txt) or provide an explicit URL--limit <n> — cap pages audited (default 200, sorted by sitemap priority)--top-issues — skip per-page output, show only cross-cutting patterns and critical defects--rewrite-sitemap-origin — rewrite every <loc>'s origin to the target URL's origin (preserving path/query) before crawling. Use when the sitemap hardcodes the prod/canonical domain but you want to audit a staging host or local dev server.--changed — filter sitemap URLs to static routes changed since --base; use for PR work--base <ref> — git base for --changed (default main)--include-critical — add critical paths to the changed-page set--critical-paths <list> — comma-separated critical paths for --include-critical; defaults to /--require-meta — force exit 1 if any audited page is missing <meta name="description">, regardless of overall score (useful as a CI gate)--include-geo / --include-agent-skills — honored per page in sitemap mode (adds the optional geographic-signals / agent-skill-exposure factors). --lighthouse is not available with --sitemap.Pages are audited with bounded concurrency (5 in flight) to avoid hammering the target origin.
Returns:
<h1> count other than one, a missing <title>, a missing meta description) surfaced regardless of how few pages they affect, with the offending pages named (homepage and high sitemap-priority pages first). These would otherwise be averaged into a passing factor score; the JSON field is criticalDefects and critical-severity ones are also promoted to the top of prioritizedFixes. Shown even with --top-issues.bestScore/bestPageUrl) and a status: sitewide (a real coverage gap) vs. limited/opportunity for page-specific factors (FAQ, definitions) that legitimately apply to only some page typeslimited/opportunity factors demoted below them, scoped to the page(s) that carry them)Use this path for PR review, local production builds, preview deployments, and branch-vs-main questions. Prefer built-in flags over manual sitemap downloads, localtunnel glue, or ad hoc URL scripts.
For a local preview server whose sitemap emits production canonicals:
npx @ainyc/aeo-audit@1 "http://localhost:3000" \
--sitemap \
--rewrite-sitemap-origin \
--allow-local \
--changed \
--base main \
--include-critical \
--format agent
Guidance:
--allow-local only when the user explicitly wants to audit localhost/private IPs.--rewrite-sitemap-origin when a local or staging sitemap emits production canonicals.--changed --base <ref> for PR work so unrelated site sections do not dominate the result.--include-critical --critical-paths /,/pricing,/contact when important pages should always be checked.--changed finds no static routes, inspect the diff manually. Dynamic route templates cannot be safely converted to concrete URLs without route params; include known concrete paths with --critical-paths or audit explicit URLs separately.--format agent for agent action, --format json for saved compare baselines, and --format markdown for human summaries.For branch-vs-production regression review, produce comparable reports first, then run compare:
npx @ainyc/aeo-audit@1 "https://production.example" --sitemap --format json > baseline.json
npx @ainyc/aeo-audit@1 "http://localhost:3000" --sitemap --rewrite-sitemap-origin --allow-local --format json > current.json
npx @ainyc/aeo-audit@1 compare --baseline baseline.json --current current.json --format markdown
Report:
compareUse --format json for the full report, or --format agent for just the decision: { schemaVersion, tool, mode, url, score, pass, criticalDefectCount, issues }, where issues is the ranked prioritizedFixes and the per-factor/per-page detail is omitted. Prefer --format agent when you only need to decide and act. Key fields for acting on the result without parsing prose:
schemaVersion (on every audit report) versions the JSON shape independently of the package version — pin to it and treat a major bump as breaking; absence means a pre-2.0 report.prioritizedFixes is a ranked array of objects, each with a stable id, kind, optional severity, the complete affectedPages list (never truncated), affectsHomepage, prevalencePct, and a human summary. Cross-cutting fixes also carry avgScore, bestScore/bestPageUrl, and a status (sitewide | limited | opportunity) — treat limited/opportunity as page-specific tune-ups, not site-wide failures. It's the pre-computed to-do list — no need to re-rank factor scores yourself.criticalDefects[].id, prioritizedFixes[].id, and every factor finding's code (e.g. technical-seo.h1.multiple) — let integrations key on codes rather than message strings.When the audit fetches /llms.txt, /llms-full.txt, /robots.txt, and /sitemap.xml, it probes once with Accept: text/markdown to detect a content-negotiation trap: file responds OK to a bare request but returns a non-2xx response when the client prefers markdown. This catches Astro / Vercel / Starlight setups that 307-redirect .txt → non-existent .md for markdown-accepting clients, making the file invisible to AI content-extraction tools even though the file exists. The diagnostic surfaces as a finding on the AI Access Files (llms.txt, sitemap) factor.
By default the audit blocks any URL that resolves to a private, loopback, or link-local address (SSRF protection). When the user wants to audit their own dev or staging server, pass --allow-local (alias --allow-private):
npx @ainyc/aeo-audit@1 "http://localhost:3000" --allow-local --format json
npx @ainyc/aeo-audit@1 "http://10.0.5.20" --allow-private --format json
http:// scheme for local dev servers — a bare host defaults to https://.<loc> pointing at any other private host (e.g. 169.254.169.254) stays blocked.npx @ainyc/aeo-audit@1 "http://localhost:3000" --sitemap --rewrite-sitemap-origin --allow-local --format json
When the user wants to audit built HTML offline (CI on a next export / dist / out directory, or before deploying), pass a filesystem path instead of a URL:
# A directory of built HTML (aggregated like sitemap mode)
npx @ainyc/aeo-audit@1 "./out" --base-url https://example.com --format json
# A single built file
npx @ainyc/aeo-audit@1 "./dist/index.html" --format json
# Gate CI on missing meta descriptions across the build
npx @ainyc/aeo-audit@1 "./out" --require-meta --format json
.html/.htm file → single-page report; a directory → aggregated report (--limit, --top-issues, --factors, --include-geo, --include-agent-skills, --require-meta apply).--base-url <url> maps files to page URLs (out/about/index.html → <base>/about/; default https://localhost). index.html collapses to its directory URL; other files drop the .html extension.llms.txt, llms-full.txt, robots.txt, and sitemap.xml are read from the directory root when present.X-Robots-Tag, Last-Modified, Link headers) aren't visible from static files. Recommend auditing the deployed URL for full coverage.When the user wants to fail CI on an AEO regression (a PR dropped the score, broke a page, or introduced a structural defect), use the compare subcommand. It diffs two saved --format json reports — a baseline and the current run — and exits non-zero on a regression. It runs no audit and no network; it only reads reports.
# 1. Produce the current report (any mode's --format json output works)
npx @ainyc/aeo-audit@1 "./out" --base-url https://example.com --format json > current.json
# 2. Diff against a stored baseline — exit 1 if it regressed
npx @ainyc/aeo-audit@1 compare --baseline baseline.json --current current.json
# Write a Markdown summary (for a PR comment) and tighten the overall gate
npx @ainyc/aeo-audit@1 compare --baseline baseline.json --current current.json --overall-tolerance 0 --md-out diff.md
# Committed/artifact baselines: hard-fail (exit 2) if factor set / engine major differ
npx @ainyc/aeo-audit@1 compare --baseline baseline.json --current current.json --strict-comparability
--overall-tolerance (default 2); a single page drop > --page-tolerance (default 5); a single factor drop > --factor-tolerance (default 8); a page that was auditing successfully now erroring; a new severity:critical defect (--fail-on-new-critical, default on); or a major report-schema change. Score/page/factor deltas only gate when the two runs are comparable (same factor set, no major engine change) — otherwise they're warnings, not failures.missing-meta-description is severity:warning, so it does not trip --fail-on-new-critical; use --require-meta on the audit or --fail-on warnings here. Removed pages and new warnings are report-only unless promoted with --fail-on removed-pages,warnings.0 = no regression / improvement / first run (no baseline); 1 = regression; 2 = misconfiguration (mode mismatch, unreadable report, missing --current, or incomparable factor-set/engine under --strict-comparability). --report-only always exits 0 (soak mode).CompareReport JSON (or Markdown with --format markdown); diagnostics go to stderr.Use --lighthouse when the user wants page speed, accessibility, or best-practices scoring alongside the AEO factors. It calls Google PageSpeed Insights (mobile strategy) and aggregates Performance + Accessibility + Best Practices into a single optional factor (weight 8).
npx @ainyc/aeo-audit@1 "<url>" --lighthouse --format json
PAGESPEED_API_KEY=xxx npx @ainyc/aeo-audit@1 "<url>" --lighthouse --format json
Constraints:
--sitemap or --detect-platform. Each Lighthouse audit takes 15-30s, which would blow up sitemap runtime.PAGESPEED_API_KEY env var lifts anonymous PSI rate limits (25k/day unauthenticated).timeout or unreachable finding rather than throwing — the rest of the audit still runs.Use --detect-platform when the user wants to know what stack a site is built on (e.g., "is this WordPress?", "what framework does competitor X use?", "is this site custom-built?"). This is much faster than a full audit because it skips analyzer scoring.
npx @ainyc/aeo-audit@1 "<url>" --detect-platform --format json
npx @ainyc/aeo-audit@1 "<url>" --detect-platform --min-confidence high --format json
Flags:
--detect-platform — switch to detection mode instead of auditing--min-confidence <lvl> — filter to low (default), medium, or high confidence--urls <src> — run on multiple URLs at once (file path, comma-separated list, or - for stdin)--concurrency <n> — max in-flight fetches in batch mode (default 5)The report groups detections by category (CMS, site builder, e-commerce, framework, SSG, hosting), each with a confidence bucket, a 0–100 score, an optional version, and the signals that matched. When the report's isCustom flag is true, no CMS/site-builder/e-commerce platform was identified — the site is likely custom-built. Exit code is 0 when at least one platform is detected, 1 otherwise.
When the user wants to fingerprint many sites at once (competitor lists, customer cohorts), pass --urls:
npx @ainyc/aeo-audit@1 --detect-platform --urls urls.txt --format json
npx @ainyc/aeo-audit@1 --detect-platform --urls https://a.com,https://b.com --format json
cat urls.txt | npx @ainyc/aeo-audit@1 --detect-platform --urls - --format json
The batch report contains a results array; each entry has status: 'success' or 'error', plus the same shape as a single-URL report on success. Per-URL fetch errors do not abort the run. Exit code is 0 when at least one URL succeeded, 1 otherwise.
Use when the user wants code changes applied after the audit.
npx @ainyc/aeo-audit@1 "<url>" [flags] --format json
llms.txt and llms-full.txtrobots.txt crawler accessrobots.txt Content-Signal directives (the audit scores the values — set ai-input=yes/search=yes to permit AI answers and search indexing; ai-input=no opts out of the real-time AI use AEO depends on), and A2A agent cards (aligned with specification.website)Rules:
Use when the request is specifically about JSON-LD or schema quality.
Validity issues like duplicate singleton @types and JSON parse errors are per page, so a homepage-only audit misses every subpage. Default to sitemap mode for site-wide schema requests ("audit my schema", "are my FAQ blocks valid?"); use single-URL mode only when the user names one specific page.
Site-wide (default):
npx @ainyc/aeo-audit@1 "<url>" --sitemap --top-issues --format json --factors structured-data,schema-completeness,schema-validity,entity-consistency
Single page:
npx @ainyc/aeo-audit@1 "<url>" --format json --factors structured-data,schema-completeness,schema-validity,entity-consistency
Report:
@types, JSON parse errors, empty <script> blocks) — surface these prominently regardless of overall score; Google drops invalid blocks silently from rich resultsProvide corrected JSON-LD examples when useful.
Checklist:
LocalBusiness: name, address, telephone, openingHours, priceRange, image, url, geo, areaServed, sameAsFAQPage: mainEntity with at least 3 Q&A pairs (and only one FAQPage block per page — duplicates invalidate rich results)HowTo: name and at least 3 steps (singleton — only one per page)Organization: name, logo, contactPoint, sameAs, foundingDate, url, descriptionFAQPage, HowTo, Article, BlogPosting, NewsArticle, BreadcrumbList, Product, RecipeUse when the user wants llms.txt or llms-full.txt created or improved.
If a URL is provided:
npx @ainyc/aeo-audit@1 "<url>" [flags] --format json --factors ai-access-files
llms.txt and llms-full.txt.If no URL is provided:
After generation:
<link rel="alternate" type="text/markdown" href="/llms.txt"> when appropriate..md URL or content negotiation) advertised via <link rel="alternate" type="text/markdown"> — a scored AI-readable signal.Use when the user wants progress tracking or a competitor comparison.
Single URL:
.aeo-audit-history/ if present.Comparison mode:
--format json reports in the same mode, then run the compare subcommand.--allow-local is missing, rerun with --allow-local only after confirming local preview auditing is intended.--rewrite-sitemap-origin.