From 80ace69c3ee299f3c6c50493dba60803129bb559 Mon Sep 17 00:00:00 2001 From: Arber Xhindoli <14798762+arberx@users.noreply.github.com> Date: Wed, 3 Jun 2026 15:44:33 -0400 Subject: [PATCH 1/2] docs: slim README to a Canonry-style overview, split details into docs/ Cut the README from ~386 lines to ~70: a badge row, a bold value prop, capability bullets that link out, an immediate usage example, and a docs table. Moved the full detail into docs/cli.md (every flag, mode, exit code), docs/scoring.md (16 factors, weights, grading scale), docs/api.md (programmatic API), and docs/skill.md (the /aeo skill). Updated the CLAUDE.md doc-sync convention to point the CLI surface at docs/cli.md. Copy is minimal and em-dash free throughout. Co-Authored-By: Claude Opus 4.8 --- CLAUDE.md | 6 +- README.md | 389 +++++------------------------------------------- docs/api.md | 62 ++++++++ docs/cli.md | 207 ++++++++++++++++++++++++++ docs/scoring.md | 58 ++++++++ docs/skill.md | 49 ++++++ 6 files changed, 416 insertions(+), 355 deletions(-) create mode 100644 docs/api.md create mode 100644 docs/cli.md create mode 100644 docs/scoring.md create mode 100644 docs/skill.md diff --git a/CLAUDE.md b/CLAUDE.md index 613550e..c08571e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -67,17 +67,17 @@ test/ # Unit and integration tests Any change to user-visible CLI surface must update **all three** of these in the same change: 1. `printHelp()` in `src/cli.ts` — Options list **and** Examples block -2. `README.md` — the `## CLI Usage` section (flags, examples, and any defaults) +2. `docs/cli.md` — the relevant mode section, the **Flag reference** table, and the **Exit codes** section (flags, examples, and any defaults). The root `README.md` only carries a handful of headline examples; the full CLI surface lives in `docs/cli.md`. 3. `skills/aeo/SKILL.md` — Examples and the relevant mode section (e.g. `### Sitemap Mode`) This applies to: - Adding, renaming, or removing a flag -- Changing a default value (e.g. sitemap `--limit` default of 200) — the default must be stated in the help string, the README, and SKILL.md +- Changing a default value (e.g. sitemap `--limit` default of 200) — the default must be stated in the help string, `docs/cli.md`, and SKILL.md - Adding a new CLI mode (e.g. `--sitemap`) — document flags, defaults, exit-code behavior, and an example invocation in all three places - Changing exit-code semantics or output format options -Before opening a PR that touches `src/cli.ts`, grep the README and SKILL.md for the affected flag name to confirm everything still matches. +Before opening a PR that touches `src/cli.ts`, grep `docs/cli.md` and SKILL.md for the affected flag name to confirm everything still matches. ## Versioning diff --git a/README.md b/README.md index d24c508..72caf90 100644 --- a/README.md +++ b/README.md @@ -1,385 +1,70 @@ # @ainyc/aeo-audit -The most comprehensive open-source technical Answer Engine Optimization (AEO) audit tool. Scores any website across 16 ranking factors that determine whether AI answer engines — ChatGPT, Perplexity, Gemini, Claude — will cite your content. +[![npm version](https://img.shields.io/npm/v/@ainyc/aeo-audit)](https://www.npmjs.com/package/@ainyc/aeo-audit) [![Node.js >= 20](https://img.shields.io/badge/node-%3E%3D20-brightgreen)](https://nodejs.org) [![License: MIT](https://img.shields.io/badge/license-MIT-blue)](./LICENSE) -Website: [canonry.ai](https://canonry.ai) - -## Quick Start - -```bash -npx @ainyc/aeo-audit https://example.com -``` - -## Local Development - -```bash -pnpm install -pnpm run typecheck -pnpm run build -pnpm run test -pnpm run lint - -# Smoke test the compiled CLI from this repo -node bin/aeo-audit.js https://example.com --format json -``` - -The package source lives in `src/*.ts` and publishes compiled ESM plus declarations from `dist/`. - -## Why AEO? - -AI answer engines are replacing traditional search for millions of queries. Getting cited by ChatGPT or Perplexity requires different signals than ranking in Google: +**The most comprehensive open-source technical AEO (Answer Engine Optimization) audit tool.** Scores any website across 16 ranking factors that decide whether AI answer engines (ChatGPT, Perplexity, Gemini, Claude) will cite your content. -- **Structured data** (JSON-LD) with FAQPage schema shows 2.7x higher citation rates -- **llms.txt** files help AI systems understand your site at a glance -- **E-E-A-T signals** (author credentials, trust pages) determine citation trustworthiness -- **Content extractability** — clean, well-structured content gets cited; paywalled content doesn't +- Grade any URL across **16 AEO factors**: structured data, `llms.txt`, E-E-A-T, extractability, snippet eligibility, and more. [Scoring](docs/scoring.md) +- Audit a **whole site** from its sitemap; per-page findings roll up into ranked fixes. [Sitemap mode](docs/cli.md#sitemap-mode) +- Audit **built HTML offline** in CI: a `next export` / `dist` / `out` directory, no network. [Static output](docs/cli.md#static-output-mode) +- Detect the **platform / CMS / framework**: WordPress, Webflow, Shopify, Next.js, Vercel. [Platform detection](docs/cli.md#platform-detection) +- Opt in to **Lighthouse, geographic, and agent-skill** factors. [Optional factors](docs/scoring.md#optional-factors) +- `text`, `json`, and `markdown` output with **CI-friendly exit codes**. [CLI reference](docs/cli.md) +- Use as a **library** ([API](docs/api.md)) or from Claude Code via the **`/aeo` skill** ([skill](docs/skill.md)). -## 16 Scoring Factors - -| Factor | Weight | What It Checks | -|--------|--------|---------------| -| Structured Data (JSON-LD) | 12% | Presence of LocalBusiness, FAQPage, Service, HowTo schemas | -| Content Depth | 10% | Word count, heading hierarchy, paragraph structure, lists | -| AI-Readable Content | 5% | llms.txt, llms-full.txt, robots.txt, sitemap.xml availability, per-page Markdown source endpoints | -| E-E-A-T Signals | 8% | Author meta, Person schema credentials, trust pages, reviews | -| FAQ Content | 8% | FAQPage schema, details/summary blocks, question-style headings | -| Citations & Authority | 8% | External links, authoritative domains, sameAs references | -| Schema Completeness | 8% | Property depth per schema type vs recommended properties | -| Entity Consistency | 7% | Name consistency across schema, title, og:title; contact alignment | -| Content Freshness | 7% | dateModified, Last-Modified header, sitemap lastmod, copyright year | -| Content Extractability | 6% | Content-to-boilerplate ratio, citation-ready blocks, paywall detection | -| Definition Blocks | 6% | "What is", "How to" headings, step lists, HowTo schema, dl elements | -| Named Entities | 6% | Brand mentions, knowsAbout/founder signals, proper noun density | -| Snippet Eligibility | 6% | `noindex`/`nosnippet`/`max-snippet` directives in meta robots and `X-Robots-Tag` — Google ties AI feature eligibility to these ([source][google-aeo]) | -| Technical SEO | 5% | H1 presence, image alt text, meta description length, canonical tag | -| Schema Validity | 5% | Duplicate singleton @types, JSON parse errors, empty JSON-LD blocks | -| AI Crawler Access | 4% | Per-bot robots.txt rules for GPTBot, ClaudeBot, PerplexityBot, etc., plus Content Signals directives | - -**Optional:** Geographic Signals (7%) — LocalBusiness geo data, address, areaServed. Enable with `--include-geo`. Agent Skill Exposure (6%) — Schema.org Action, MCP, A2A agent cards, form affordances. Enable with `--include-agent-skills`. Lighthouse (8%) — Performance, Accessibility, and Best Practices scores via Google PageSpeed Insights (mobile strategy). Enable with `--lighthouse`. Adds ~15-30s per audit; set `PAGESPEED_API_KEY` to lift anonymous rate limits. - -[google-aeo]: https://developers.google.com/search/docs/fundamentals/ai-optimization-guide "Google: AI features and your website" - -> **Note on Google's guidance.** Google's [AI features and your website][google-aeo] guide says `llms.txt` and heavy structured data aren't required for AI Overviews or AI Mode. We still score them — Google is one engine; ChatGPT, Perplexity, and Claude do rely on them. Snippet eligibility is the one hard gate Google enforces: a page must be indexable and snippet-eligible to appear in AI features. +Website: [canonry.ai](https://canonry.ai) -## CLI Usage +## Audit your site ```bash -# Colored terminal output (default) npx @ainyc/aeo-audit https://example.com - -# JSON output (for CI/CD) -npx @ainyc/aeo-audit https://example.com --format json - -# Markdown report -npx @ainyc/aeo-audit https://example.com --format markdown - -# Run specific factors only -npx @ainyc/aeo-audit https://example.com --factors structured-data,faq-content - -# Validate JSON-LD blocks for parse errors and duplicate singleton @types -# (catches issues like duplicate FAQPage that Google flags as invalid) -npx @ainyc/aeo-audit https://example.com --factors schema-validity - -# Include geographic signals -npx @ainyc/aeo-audit https://example.com --include-geo - -# Include optional agent skill exposure factor -npx @ainyc/aeo-audit https://example.com --include-agent-skills - -# Include optional Lighthouse factor (Performance + A11y + Best Practices, mobile) -# Calls Google PageSpeed Insights — adds ~15-30s. Single-URL only (not sitemap mode). -npx @ainyc/aeo-audit https://example.com --lighthouse - -# Provide a PageSpeed Insights API key to lift anonymous rate limits -PAGESPEED_API_KEY=xxx npx @ainyc/aeo-audit https://example.com --lighthouse --format json - -# Force exit 1 when meta description is missing (CI gate) -npx @ainyc/aeo-audit https://example.com --require-meta -npx @ainyc/aeo-audit https://example.com --sitemap --require-meta -``` - -### Auditing a Local or Private Target (`--allow-local`) - -By default the audit refuses any URL that resolves to a private, loopback, or -link-local address — the right default for a tool that also runs as a hosted -service on arbitrary input. To audit your **own** dev or staging server, pass -`--allow-local` (alias `--allow-private`): - -```bash -# Audit a local dev server (pass the explicit scheme — bare hosts default to https) -npx @ainyc/aeo-audit http://localhost:3000 --allow-local - -# A staging box on a private IP / VPN -npx @ainyc/aeo-audit http://10.0.5.20 --allow-private -``` - -The relaxation is **scoped to the single host you named on the CLI, and only that -host**. It is evaluated per request hop, so a redirect or a sitemap `` -pointing at any *other* private address (cloud metadata at `169.254.169.254`, -internal services, …) is still blocked. There is no flag that disables the guard -wholesale, and library/service callers that never set it stay fully protected. - -### Static-Output Mode (audit built HTML offline) - -Point the CLI at a filesystem path instead of a URL to audit built HTML directly — -no network, ideal for CI on a `next export` / `dist` / `out` directory: - -```bash -# Audit a whole built directory (aggregated like sitemap mode) -npx @ainyc/aeo-audit ./out - -# Map files to real URLs so canonical / og:url checks are meaningful -npx @ainyc/aeo-audit ./out --base-url https://example.com - -# A single built file -npx @ainyc/aeo-audit ./dist/index.html - -# Gate CI on a missing meta description across the build -npx @ainyc/aeo-audit ./out --require-meta -``` - -A `.html`/`.htm` file produces a single-page report; a directory is walked for -HTML files and aggregated like sitemap mode (`--limit`, `--top-issues`, -`--factors`, `--include-geo`, `--include-agent-skills`, and `--require-meta` all -apply). `index.html` maps to its directory URL (`out/about/index.html` → -`/about/`); other files drop the extension (`out/blog/post.html` → -`/blog/post`). `llms.txt`, `llms-full.txt`, `robots.txt`, and `sitemap.xml` -are read from the directory root when present. - -Coverage is **partial by design**: server-only signals (redirects, `X-Robots-Tag`, -`Last-Modified`, `Link` headers) aren't visible from static files, so factors that -depend on them score as if the header were absent. Audit the deployed URL for full -coverage. - -### Platform Detection Mode - -Detect what platform, CMS, framework, or static site generator a website is built on. Useful for competitor research, lead qualification, and triage before an audit. - -```bash -# Identify the stack (WordPress, Webflow, Shopify, Next.js, Vercel, etc.) -npx @ainyc/aeo-audit https://example.com --detect-platform - -# JSON for programmatic use -npx @ainyc/aeo-audit https://example.com --detect-platform --format json - -# Only show high-confidence matches -npx @ainyc/aeo-audit https://example.com --detect-platform --min-confidence high -``` - -The detector inspects HTML, response headers, ``, script and link sources, and platform-specific globals to fingerprint: - -- **CMS:** WordPress, Drupal, Joomla, Ghost, HubSpot, Craft CMS, Sanity, Contentful, Notion -- **Site builders:** Wix, Squarespace, Webflow, Framer, Carrd, Bubble -- **E-commerce:** Shopify, WooCommerce, BigCommerce, Magento, PrestaShop -- **Frameworks:** Next.js, Nuxt, Gatsby, Remix, Astro, SvelteKit, Angular, Vue, React, Ember, Qwik -- **Static site generators:** Hugo, Jekyll, Eleventy, Hexo, Docusaurus, MkDocs -- **Hosting / CDN:** Vercel, Netlify, Cloudflare, GitHub Pages, Fastly, AWS CloudFront - -Each detected platform is reported with a confidence bucket (`high`, `medium`, `low`), a numeric score, an optional version, and the list of signals that matched. When no CMS, site builder, or e-commerce platform is found, the report flags the site as `custom-built` (framework and hosting fingerprints are still surfaced for context). Exit code is `0` when at least one platform is detected, `1` otherwise. - -#### Batch detection - -Pass `--urls` to fingerprint many sites in a single run. Pages are fetched with bounded concurrency (5 in flight by default; tune with `--concurrency`). - -```bash -# From a file (one URL per line; # comments and blank lines are skipped) -npx @ainyc/aeo-audit --detect-platform --urls urls.txt - -# Inline comma-separated list -npx @ainyc/aeo-audit --detect-platform --urls https://a.com,https://b.com,https://c.com - -# From stdin -cat urls.txt | npx @ainyc/aeo-audit --detect-platform --urls - - -# JSON for downstream processing -npx @ainyc/aeo-audit --detect-platform --urls urls.txt --format json ``` -Per-URL fetch errors don't abort the batch — each entry is reported with `status: 'success'` or `status: 'error'`. Exit code is `0` when at least one URL succeeded, `1` otherwise. - -### Sitemap Mode - -Audit every page discovered from the site's sitemap with bounded concurrency (5 in flight): +Prints a graded report. Common variations: ```bash -# Auto-discover the sitemap (tries /sitemap.xml, then /sitemap-index.xml, -# then the Sitemap: directive in /robots.txt) -npx @ainyc/aeo-audit https://example.com --sitemap - -# Provide an explicit sitemap URL -npx @ainyc/aeo-audit https://example.com --sitemap https://example.com/sitemap.xml - -# Cap the number of pages (default 200, sorted by sitemap priority) -npx @ainyc/aeo-audit https://example.com --sitemap --limit 50 - -# Skip per-page output and show only cross-cutting issues +# Every page in the sitemap, site-wide issues only npx @ainyc/aeo-audit https://example.com --sitemap --top-issues -# Rewrite each 's origin to the target you named (audit staging with prod's sitemap) -npx @ainyc/aeo-audit https://staging.example.com --sitemap --rewrite-sitemap-origin - -# Audit a whole local dev server: rewrite the sitemap onto localhost and unblock it -npx @ainyc/aeo-audit http://localhost:3000 --sitemap --rewrite-sitemap-origin --allow-local -``` - -Auto-discovery checks `/sitemap.xml` → `/sitemap-index.xml` → `Sitemap:` directives in `/robots.txt`. Astro / Next.js / Vercel sites that only publish `sitemap-index.xml` are now discovered without needing an explicit URL. - -`--rewrite-sitemap-origin` re-homes every `` onto the origin of the target URL you passed (preserving path and query) before crawling. Use it when a sitemap hardcodes the canonical/prod domain but you want to audit a different origin that serves the same paths — a staging host, or a local dev server. Every crawled URL is pinned to the origin you explicitly named, so there's no SSRF cost; combined with `--allow-local` it makes a local dev server's whole sitemap auditable in one command. - -When the sitemap has more URLs than `--limit`, the run audits the highest-priority pages and prints a notice to stderr listing how many were skipped and how to audit them all. - -The optional in-process factors are honored per page in sitemap mode: pass `--include-geo` and/or `--include-agent-skills` to add them to every audited page. `--lighthouse` is the exception — it cannot be combined with `--sitemap` because each PageSpeed Insights call takes 15-30s. - -### Auxiliary File Diagnostics - -When fetching `/llms.txt`, `/llms-full.txt`, `/robots.txt`, and `/sitemap.xml` the audit runs a **content-negotiation probe** that surfaces as a finding on the **AI-Readable Content** factor: if a file returns OK to a bare request but a non-2xx response under `Accept: text/markdown`, the audit reports a content-negotiation trap. This catches Astro / Vercel / Starlight setups that redirect `.txt` → non-existent `.md` for markdown-accepting clients, which makes the file invisible to AI content-extraction tools — even though the file is "present" by every other measure. - -### Flag Reference - -| Flag | Description | -|------|-------------| -| `--format ` | Output format: `text` (default), `json`, `markdown` | -| `--factors ` | Comma-separated factor IDs to run (runs all if omitted) | -| `--include-geo` | Include the optional geographic signals factor | -| `--include-agent-skills` | Include the optional agent skill exposure factor | -| `--lighthouse` | Include the optional Lighthouse factor (Performance + Accessibility + Best Practices, mobile strategy) via Google PageSpeed Insights. Single-URL only; cannot combine with `--sitemap` or `--detect-platform`. Adds ~15-30s. Set `PAGESPEED_API_KEY` env var to lift anonymous rate limits. | -| `--sitemap [url]` | Audit all pages from the sitemap. Auto-discovery tries `/sitemap.xml`, then `/sitemap-index.xml`, then `Sitemap:` directives in `/robots.txt`. Pass an explicit URL to override. | -| `--limit ` | Max pages to audit in sitemap mode (default 200, sorted by sitemap priority) | -| `--top-issues` | In sitemap mode, skip per-page output and show only cross-cutting issues | -| `--detect-platform` | Identify the platform/CMS/framework powering the site instead of running an audit | -| `--urls ` | In `--detect-platform` mode, run on multiple URLs. `` is a file path (one URL per line), a comma-separated list, or `-` for stdin | -| `--concurrency ` | In `--detect-platform` batch mode, max in-flight fetches (default 5) | -| `--min-confidence ` | In platform-detect mode, only report matches at or above this level: `low` (default), `medium`, `high` | -| `--require-meta` | Exit `1` if any audited page is missing ``, regardless of the overall score. Works in single-URL, sitemap, and static-output modes. | -| `--allow-local` (alias `--allow-private`) | Allow the single target host you named on the CLI to resolve to a private/loopback IP (e.g. `http://localhost:3000`). Scoped to that one host only — redirects and sitemap ``s to any other private host stay blocked. | -| `--rewrite-sitemap-origin` | In `--sitemap` mode, rewrite every ``'s origin to the target URL's origin (preserving path/query) before crawling. For auditing a staging host or local dev server with a sitemap that hardcodes the prod domain. | -| `--base-url ` | In static-output mode, the base URL used to map files to page URLs (e.g. `out/about/index.html` → `/about/`). Default `https://localhost`. | -| `-h`, `--help` | Show the help message | - -Pass a **filesystem path** (a `.html` file or a directory of built HTML) instead of a URL to run in static-output mode — built HTML is audited offline (partial coverage; no server-only signals). - -Exit code `0` for score >= 70, `1` for < 70 (CI-friendly). In sitemap and static-directory modes the exit code is based on the aggregate score. When `--require-meta` is passed, exit is forced to `1` if any audited page lacks ``, regardless of the score-based rule. - -## Programmatic Usage - -The library exposes two audit entry points. **Use `runSitemapAudit` for site-wide checks** — `runAeoAudit` only fetches the URL you pass it, so per-page issues like duplicate `FAQPage` blocks, JSON parse errors, or missing schema on individual templates are invisible if you call it on the homepage of a multi-page site. - -### Single page - -```ts -import { runAeoAudit } from '@ainyc/aeo-audit' - -const report = await runAeoAudit('https://example.com/specific-page', { - includeGeo: false, // Include geographic signals (default: false) - includeAgentSkills: false, // Include agent skill exposure (default: false) - includeLighthouse: false, // Include Lighthouse via PageSpeed Insights (default: false; adds ~15-30s) - factors: undefined, // Run all factors (or pass array of factor IDs) - allowPrivateHost: undefined, // Permit ONE named host to resolve to a private/loopback IP (e.g. 'localhost'). - // Scoped to that exact host; redirects/sitemap entries to other private hosts stay blocked. -}) - -console.log(report.overallGrade) // 'A+' -console.log(report.overallScore) // 98 -console.log(report.factors) // Array of factor results with scores, findings, recommendations -``` - -### Site-wide (sitemap) - -```ts -import { runSitemapAudit } from '@ainyc/aeo-audit' - -const report = await runSitemapAudit('https://example.com', { - limit: 200, // Max pages to audit (default 200, sorted by sitemap priority) - factors: ['schema-validity', 'structured-data'], // Optional subset -}) +# JSON for CI/CD (exit 1 when score < 70) +npx @ainyc/aeo-audit https://example.com --format json -console.log(report.aggregateGrade) // 'B+' -console.log(report.pagesAudited) // 22 -console.log(report.crossCuttingIssues) // Per-factor rollup with affectedUrls for every recommendation -console.log(report.prioritizedFixes) // Top 5 fixes ranked by site-wide impact +# A built directory, offline +npx @ainyc/aeo-audit ./out --base-url https://example.com ``` -Each entry in `crossCuttingIssues[].topIssues` carries a `recommendation` plus the exact `affectedUrls` so you can attribute each problem to specific pages — e.g. "FAQPage duplicate" pointing at every blog post that has it. - -### Static output (offline, from disk) +Full flag and mode reference: [docs/cli.md](docs/cli.md). -```ts -import { runStaticAudit } from '@ainyc/aeo-audit' +## From your AI coding agent -const result = await runStaticAudit('./out', { - baseUrl: 'https://example.com', // maps files to page URLs (default https://localhost) - limit: 200, // max HTML files when the path is a directory -}) +The package ships a Claude Code / ClawHub skill. [Install it](docs/skill.md#install), then: -if (result.kind === 'single') { - console.log(result.report.overallGrade) // single .html file → AuditReport -} else { - console.log(result.report.aggregateGrade) // directory → SitemapAuditReport shape - console.log(result.report.crossCuttingIssues) -} +```text +/aeo audit https://example.com ``` -`runStaticAudit` performs no network I/O. Coverage is partial — server-only signals (redirects, `X-Robots-Tag`, `Last-Modified`, `Link` headers) aren't visible from static files. - -TypeScript declaration files are included automatically. - -## Claude Code / ClawHub Skill - -This package now ships one umbrella skill source at `skills/aeo/SKILL.md`. +Modes: audit, fix, schema, `llms.txt`, monitor. See the [skill guide](docs/skill.md). -Command: `/aeo` +## Documentation -Modes: +| Doc | What's in it | +|---|---| +| [CLI reference](docs/cli.md) | Every flag, mode, and exit code | +| [Scoring](docs/scoring.md) | The 16 factors, weights, grading scale | +| [Programmatic API](docs/api.md) | `runAeoAudit`, `runSitemapAudit`, `runStaticAudit` | +| [Skill](docs/skill.md) | `/aeo` modes and install | +| [Changelog](CHANGELOG.md) | Release history | +| [Roadmap](ROADMAP.md) | What's planned | -- `audit` for grading and diagnosis -- `fix` for code changes after an audit -- `schema` for JSON-LD validation -- `llms` for `llms.txt` and `llms-full.txt` -- `monitor` for before/after tracking or competitor comparisons - -Examples: - -- `/aeo audit https://example.com` -- `/aeo fix https://example.com` -- `/aeo schema https://example.com` -- `/aeo llms https://example.com` -- `/aeo monitor https://site-a.com --compare https://site-b.com` - -ClawHub package: [arberx/aeo](https://clawhub.ai/arberx/aeo) - -If you are testing the skill from this repository instead of the published package, build first and use the local CLI: - -```bash -pnpm run build -node bin/aeo-audit.js https://example.com --format json -``` - -### Install Skills +## Contributing ```bash -# Personal install -git clone https://github.com/AINYC/aeo-audit.git /tmp/aeo-audit -cp -r /tmp/aeo-audit/skills/aeo ~/.claude/skills/ - -# Or project-level -cp -r /tmp/aeo-audit/skills/aeo .claude/skills/ +git clone https://github.com/AINYC/aeo-audit.git && cd aeo-audit +pnpm install && pnpm run typecheck && pnpm run build && pnpm test && pnpm lint ``` -## Grading Scale - -| Grade | Score | Meaning | -|-------|-------|---------| -| A+ | 97-100 | Exceptional AEO readiness | -| A / A- | 90-96 | Strong foundation | -| B+/B/B- | 80-89 | Good with clear gaps | -| C+/C/C- | 70-79 | Moderate, needs work | -| D+/D/D- | 60-69 | Weak | -| F | <60 | Critical | - -## Contributing - -See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines. +See [CONTRIBUTING.md](CONTRIBUTING.md). ## License -MIT +[MIT](LICENSE) diff --git a/docs/api.md b/docs/api.md new file mode 100644 index 0000000..8f77b11 --- /dev/null +++ b/docs/api.md @@ -0,0 +1,62 @@ +# Programmatic API + +The library exposes three audit entry points. **Use `runSitemapAudit` for site-wide checks.** `runAeoAudit` only fetches the URL you pass it, so per-page issues like duplicate `FAQPage` blocks, JSON parse errors, or missing schema on individual templates are invisible if you call it on the homepage of a multi-page site. + +TypeScript declaration files are included automatically. + +## Single page + +```ts +import { runAeoAudit } from '@ainyc/aeo-audit' + +const report = await runAeoAudit('https://example.com/specific-page', { + includeGeo: false, // Include geographic signals (default: false) + includeAgentSkills: false, // Include agent skill exposure (default: false) + includeLighthouse: false, // Include Lighthouse via PageSpeed Insights (default: false; adds ~15-30s) + factors: undefined, // Run all factors (or pass array of factor IDs) + allowPrivateHost: undefined, // Permit ONE named host to resolve to a private/loopback IP (e.g. 'localhost'). + // Scoped to that exact host; redirects/sitemap entries to other private hosts stay blocked. +}) + +console.log(report.overallGrade) // 'A+' +console.log(report.overallScore) // 98 +console.log(report.factors) // Array of factor results with scores, findings, recommendations +``` + +## Site-wide (sitemap) + +```ts +import { runSitemapAudit } from '@ainyc/aeo-audit' + +const report = await runSitemapAudit('https://example.com', { + limit: 200, // Max pages to audit (default 200, sorted by sitemap priority) + factors: ['schema-validity', 'structured-data'], // Optional subset +}) + +console.log(report.aggregateGrade) // 'B+' +console.log(report.pagesAudited) // 22 +console.log(report.crossCuttingIssues) // Per-factor rollup with affectedUrls for every recommendation +console.log(report.prioritizedFixes) // Top 5 fixes ranked by site-wide impact +``` + +Each entry in `crossCuttingIssues[].topIssues` carries a `recommendation` plus the exact `affectedUrls` so you can attribute each problem to specific pages, e.g. "FAQPage duplicate" pointing at every blog post that has it. + +## Static output (offline, from disk) + +```ts +import { runStaticAudit } from '@ainyc/aeo-audit' + +const result = await runStaticAudit('./out', { + baseUrl: 'https://example.com', // maps files to page URLs (default https://localhost) + limit: 200, // max HTML files when the path is a directory +}) + +if (result.kind === 'single') { + console.log(result.report.overallGrade) // single .html file → AuditReport +} else { + console.log(result.report.aggregateGrade) // directory → SitemapAuditReport shape + console.log(result.report.crossCuttingIssues) +} +``` + +`runStaticAudit` performs no network I/O. Coverage is partial: server-only signals (redirects, `X-Robots-Tag`, `Last-Modified`, `Link` headers) aren't visible from static files. diff --git a/docs/cli.md b/docs/cli.md new file mode 100644 index 0000000..d700aff --- /dev/null +++ b/docs/cli.md @@ -0,0 +1,207 @@ +# CLI reference + +```bash +npx @ainyc/aeo-audit [options] +``` + +Pass a **URL** to audit a live site, or a **filesystem path** (a `.html` file or a directory of built HTML, e.g. `./out`) to audit static output offline. + +Exit code is `0` when the score is ≥ 70 and `1` when it's below (CI-friendly). See [Exit codes](#exit-codes) for the full rules. + +## Output formats + +```bash +# Colored terminal output (default) +npx @ainyc/aeo-audit https://example.com + +# JSON output (for CI/CD) +npx @ainyc/aeo-audit https://example.com --format json + +# Markdown report +npx @ainyc/aeo-audit https://example.com --format markdown +``` + +## Running a subset of factors + +```bash +# Run specific factors only +npx @ainyc/aeo-audit https://example.com --factors structured-data,faq-content + +# Validate JSON-LD blocks for parse errors and duplicate singleton @types +# (catches issues like duplicate FAQPage that Google flags as invalid) +npx @ainyc/aeo-audit https://example.com --factors schema-validity +``` + +Factor IDs are listed in [scoring.md](scoring.md). + +## Optional factors + +```bash +# Geographic signals (LocalBusiness geo data, address, areaServed) +npx @ainyc/aeo-audit https://example.com --include-geo + +# Agent skill exposure (Schema.org Action, MCP, A2A cards, form affordances) +npx @ainyc/aeo-audit https://example.com --include-agent-skills + +# Lighthouse (Performance + A11y + Best Practices, mobile) via Google PageSpeed +# Insights. Adds ~15-30s. Single-URL only (cannot combine with --sitemap). +npx @ainyc/aeo-audit https://example.com --lighthouse + +# Provide a PageSpeed Insights API key to lift anonymous rate limits +PAGESPEED_API_KEY=xxx npx @ainyc/aeo-audit https://example.com --lighthouse --format json +``` + +See [scoring.md](scoring.md#optional-factors) for what each optional factor measures. + +## CI gating + +```bash +# Force exit 1 when the meta description is missing (on top of the score gate) +npx @ainyc/aeo-audit https://example.com --require-meta +npx @ainyc/aeo-audit https://example.com --sitemap --require-meta +``` + +## Sitemap mode + +Audit every page discovered from the site's sitemap with bounded concurrency (5 in flight): + +```bash +# Auto-discover the sitemap (tries /sitemap.xml, then /sitemap-index.xml, +# then the Sitemap: directive in /robots.txt) +npx @ainyc/aeo-audit https://example.com --sitemap + +# Provide an explicit sitemap URL +npx @ainyc/aeo-audit https://example.com --sitemap https://example.com/sitemap.xml + +# Cap the number of pages (default 200, sorted by sitemap priority) +npx @ainyc/aeo-audit https://example.com --sitemap --limit 50 + +# Skip per-page output and show only cross-cutting issues +npx @ainyc/aeo-audit https://example.com --sitemap --top-issues + +# Rewrite each 's origin to the target you named (audit staging with prod's sitemap) +npx @ainyc/aeo-audit https://staging.example.com --sitemap --rewrite-sitemap-origin + +# Audit a whole local dev server: rewrite the sitemap onto localhost and unblock it +npx @ainyc/aeo-audit http://localhost:3000 --sitemap --rewrite-sitemap-origin --allow-local +``` + +Auto-discovery checks `/sitemap.xml` → `/sitemap-index.xml` → `Sitemap:` directives in `/robots.txt`. Astro / Next.js / Vercel sites that only publish `sitemap-index.xml` are discovered without needing an explicit URL. + +`--rewrite-sitemap-origin` re-homes every `` onto the origin of the target URL you passed (preserving path and query) before crawling. Use it when a sitemap hardcodes the canonical/prod domain but you want to audit a different origin that serves the same paths: a staging host, or a local dev server. Every crawled URL is pinned to the origin you explicitly named, so there's no SSRF cost; combined with `--allow-local` it makes a local dev server's whole sitemap auditable in one command. + +When the sitemap has more URLs than `--limit`, the run audits the highest-priority pages and prints a notice to stderr listing how many were skipped and how to audit them all. + +The optional in-process factors are honored per page: pass `--include-geo` and/or `--include-agent-skills` to add them to every audited page. `--lighthouse` is the exception: it cannot be combined with `--sitemap` because each PageSpeed Insights call takes 15-30s. + +## Static-output mode + +Point the CLI at a filesystem path instead of a URL to audit built HTML directly: no network, ideal for CI on a `next export` / `dist` / `out` directory: + +```bash +# Audit a whole built directory (aggregated like sitemap mode) +npx @ainyc/aeo-audit ./out + +# Map files to real URLs so canonical / og:url checks are meaningful +npx @ainyc/aeo-audit ./out --base-url https://example.com + +# A single built file +npx @ainyc/aeo-audit ./dist/index.html + +# Gate CI on a missing meta description across the build +npx @ainyc/aeo-audit ./out --require-meta +``` + +A `.html`/`.htm` file produces a single-page report; a directory is walked for HTML files and aggregated like sitemap mode (`--limit`, `--top-issues`, `--factors`, `--include-geo`, `--include-agent-skills`, and `--require-meta` all apply). `index.html` maps to its directory URL (`out/about/index.html` → `/about/`); other files drop the extension (`out/blog/post.html` → `/blog/post`). `llms.txt`, `llms-full.txt`, `robots.txt`, and `sitemap.xml` are read from the directory root when present. + +Coverage is **partial by design**: server-only signals (redirects, `X-Robots-Tag`, `Last-Modified`, `Link` headers) aren't visible from static files, so factors that depend on them score as if the header were absent. Audit the deployed URL for full coverage. + +## Platform detection + +Detect what platform, CMS, framework, or static site generator a website is built on. Useful for competitor research, lead qualification, and triage before an audit. + +```bash +# Identify the stack (WordPress, Webflow, Shopify, Next.js, Vercel, etc.) +npx @ainyc/aeo-audit https://example.com --detect-platform + +# JSON for programmatic use +npx @ainyc/aeo-audit https://example.com --detect-platform --format json + +# Only show high-confidence matches +npx @ainyc/aeo-audit https://example.com --detect-platform --min-confidence high +``` + +The detector inspects HTML, response headers, ``, script and link sources, and platform-specific globals to fingerprint: + +- **CMS:** WordPress, Drupal, Joomla, Ghost, HubSpot, Craft CMS, Sanity, Contentful, Notion +- **Site builders:** Wix, Squarespace, Webflow, Framer, Carrd, Bubble +- **E-commerce:** Shopify, WooCommerce, BigCommerce, Magento, PrestaShop +- **Frameworks:** Next.js, Nuxt, Gatsby, Remix, Astro, SvelteKit, Angular, Vue, React, Ember, Qwik +- **Static site generators:** Hugo, Jekyll, Eleventy, Hexo, Docusaurus, MkDocs +- **Hosting / CDN:** Vercel, Netlify, Cloudflare, GitHub Pages, Fastly, AWS CloudFront + +Each detected platform is reported with a confidence bucket (`high`, `medium`, `low`), a numeric score, an optional version, and the list of signals that matched. When no CMS, site builder, or e-commerce platform is found, the report flags the site as `custom-built` (framework and hosting fingerprints are still surfaced for context). Exit code is `0` when at least one platform is detected, `1` otherwise. + +### Batch detection + +Pass `--urls` to fingerprint many sites in a single run. Pages are fetched with bounded concurrency (5 in flight by default; tune with `--concurrency`). + +```bash +# From a file (one URL per line; # comments and blank lines are skipped) +npx @ainyc/aeo-audit --detect-platform --urls urls.txt + +# Inline comma-separated list +npx @ainyc/aeo-audit --detect-platform --urls https://a.com,https://b.com,https://c.com + +# From stdin +cat urls.txt | npx @ainyc/aeo-audit --detect-platform --urls - + +# JSON for downstream processing +npx @ainyc/aeo-audit --detect-platform --urls urls.txt --format json +``` + +Per-URL fetch errors don't abort the batch: each entry is reported with `status: 'success'` or `status: 'error'`. Exit code is `0` when at least one URL succeeded, `1` otherwise. + +## Auditing a local or private target + +By default the audit refuses any URL that resolves to a private, loopback, or link-local address. That is the right default for a tool that also runs as a hosted service on arbitrary input. To audit your **own** dev or staging server, pass `--allow-local` (alias `--allow-private`): + +```bash +# Audit a local dev server (pass the explicit scheme; bare hosts default to https) +npx @ainyc/aeo-audit http://localhost:3000 --allow-local + +# A staging box on a private IP / VPN +npx @ainyc/aeo-audit http://10.0.5.20 --allow-private +``` + +The relaxation is **scoped to the single host you named on the CLI, and only that host**. It is evaluated per request hop, so a redirect or a sitemap `` pointing at any *other* private address (cloud metadata at `169.254.169.254`, internal services, …) is still blocked. There is no flag that disables the guard wholesale, and library/service callers that never set it stay fully protected. + +## Auxiliary file diagnostics + +When fetching `/llms.txt`, `/llms-full.txt`, `/robots.txt`, and `/sitemap.xml` the audit runs a **content-negotiation probe** that surfaces as a finding on the **AI-Readable Content** factor: if a file returns OK to a bare request but a non-2xx response under `Accept: text/markdown`, the audit reports a content-negotiation trap. This catches Astro / Vercel / Starlight setups that redirect `.txt` → non-existent `.md` for markdown-accepting clients, which makes the file invisible to AI content-extraction tools, even though the file is "present" by every other measure. + +## Flag reference + +| Flag | Description | +|------|-------------| +| `--format ` | Output format: `text` (default), `json`, `markdown` | +| `--factors ` | Comma-separated factor IDs to run (runs all if omitted) | +| `--include-geo` | Include the optional geographic signals factor | +| `--include-agent-skills` | Include the optional agent skill exposure factor | +| `--lighthouse` | Include the optional Lighthouse factor (Performance + Accessibility + Best Practices, mobile strategy) via Google PageSpeed Insights. Single-URL only; cannot combine with `--sitemap` or `--detect-platform`. Adds ~15-30s. Set `PAGESPEED_API_KEY` env var to lift anonymous rate limits. | +| `--sitemap [url]` | Audit all pages from the sitemap. Auto-discovery tries `/sitemap.xml`, then `/sitemap-index.xml`, then `Sitemap:` directives in `/robots.txt`. Pass an explicit URL to override. | +| `--limit ` | Max pages to audit in sitemap mode (default 200, sorted by sitemap priority) | +| `--top-issues` | In sitemap mode, skip per-page output and show only cross-cutting issues | +| `--detect-platform` | Identify the platform/CMS/framework powering the site instead of running an audit | +| `--urls ` | In `--detect-platform` mode, run on multiple URLs. `` is a file path (one URL per line), a comma-separated list, or `-` for stdin | +| `--concurrency ` | In `--detect-platform` batch mode, max in-flight fetches (default 5) | +| `--min-confidence ` | In platform-detect mode, only report matches at or above this level: `low` (default), `medium`, `high` | +| `--require-meta` | Exit `1` if any audited page is missing ``, regardless of the overall score. Works in single-URL, sitemap, and static-output modes. | +| `--allow-local` (alias `--allow-private`) | Allow the single target host you named on the CLI to resolve to a private/loopback IP (e.g. `http://localhost:3000`). Scoped to that one host only; redirects and sitemap ``s to any other private host stay blocked. | +| `--rewrite-sitemap-origin` | In `--sitemap` mode, rewrite every ``'s origin to the target URL's origin (preserving path/query) before crawling. For auditing a staging host or local dev server with a sitemap that hardcodes the prod domain. | +| `--base-url ` | In static-output mode, the base URL used to map files to page URLs (e.g. `out/about/index.html` → `/about/`). Default `https://localhost`. | +| `-h`, `--help` | Show the help message | + +## Exit codes + +Exit code `0` for score ≥ 70, `1` for < 70 (CI-friendly). In sitemap and static-directory modes the exit code is based on the aggregate score. In `--detect-platform` mode the exit code is `0` if any platform is detected (or, in batch mode, if any URL succeeded), `1` otherwise. When `--require-meta` is passed, exit is forced to `1` if any audited page lacks ``, regardless of the score-based rule. diff --git a/docs/scoring.md b/docs/scoring.md new file mode 100644 index 0000000..d6b66f2 --- /dev/null +++ b/docs/scoring.md @@ -0,0 +1,58 @@ +# Scoring + +## Why AEO? + +AI answer engines are replacing traditional search for millions of queries. Getting cited by ChatGPT or Perplexity requires different signals than ranking in Google: + +- **Structured data** (JSON-LD) with FAQPage schema shows 2.7x higher citation rates +- **llms.txt** files help AI systems understand your site at a glance +- **E-E-A-T signals** (author credentials, trust pages) determine citation trustworthiness +- **Content extractability**: clean, well-structured content gets cited; paywalled content doesn't + +## The 16 scoring factors + +| Factor | Weight | What It Checks | +|--------|--------|---------------| +| Structured Data (JSON-LD) | 12% | Presence of LocalBusiness, FAQPage, Service, HowTo schemas | +| Content Depth | 10% | Word count, heading hierarchy, paragraph structure, lists | +| AI-Readable Content | 5% | llms.txt, llms-full.txt, robots.txt, sitemap.xml availability, per-page Markdown source endpoints | +| E-E-A-T Signals | 8% | Author meta, Person schema credentials, trust pages, reviews | +| FAQ Content | 8% | FAQPage schema, details/summary blocks, question-style headings | +| Citations & Authority | 8% | External links, authoritative domains, sameAs references | +| Schema Completeness | 8% | Property depth per schema type vs recommended properties | +| Entity Consistency | 7% | Name consistency across schema, title, og:title; contact alignment | +| Content Freshness | 7% | dateModified, Last-Modified header, sitemap lastmod, copyright year | +| Content Extractability | 6% | Content-to-boilerplate ratio, citation-ready blocks, paywall detection | +| Definition Blocks | 6% | "What is", "How to" headings, step lists, HowTo schema, dl elements | +| Named Entities | 6% | Brand mentions, knowsAbout/founder signals, proper noun density | +| Snippet Eligibility | 6% | `noindex`/`nosnippet`/`max-snippet` directives in meta robots and `X-Robots-Tag`. Google ties AI feature eligibility to these ([source][google-aeo]) | +| Technical SEO | 5% | H1 presence, image alt text, meta description length, canonical tag | +| Schema Validity | 5% | Duplicate singleton @types, JSON parse errors, empty JSON-LD blocks | +| AI Crawler Access | 4% | Per-bot robots.txt rules for GPTBot, ClaudeBot, PerplexityBot, etc., plus Content Signals directives | + +Weights sum to 100% for the active factors. Pass `--factors ` to run a subset (see the [CLI reference](cli.md#running-a-subset-of-factors)). + +## Optional factors + +These are excluded by default; when included, the weights renormalize. + +- **Geographic Signals (7%)**: LocalBusiness geo data, address, areaServed. Enable with `--include-geo`. +- **Agent Skill Exposure (6%)**: Schema.org Action, MCP, A2A agent cards, form affordances. Enable with `--include-agent-skills`. +- **Lighthouse (8%)**: Performance, Accessibility, and Best Practices scores via Google PageSpeed Insights (mobile strategy). Enable with `--lighthouse`. Adds ~15-30s per audit; set `PAGESPEED_API_KEY` to lift anonymous rate limits. + +[google-aeo]: https://developers.google.com/search/docs/fundamentals/ai-optimization-guide "Google: AI features and your website" + +> **Note on Google's guidance.** Google's [AI features and your website][google-aeo] guide says `llms.txt` and heavy structured data aren't required for AI Overviews or AI Mode. We still score them: Google is one engine; ChatGPT, Perplexity, and Claude do rely on them. Snippet eligibility is the one hard gate Google enforces: a page must be indexable and snippet-eligible to appear in AI features. + +## Grading scale + +| Grade | Score | Meaning | +|-------|-------|---------| +| A+ | 97-100 | Exceptional AEO readiness | +| A / A- | 90-96 | Strong foundation | +| B+/B/B- | 80-89 | Good with clear gaps | +| C+/C/C- | 70-79 | Moderate, needs work | +| D+/D/D- | 60-69 | Weak | +| F | <60 | Critical | + +The CLI exits `0` for a score ≥ 70 and `1` below; see [Exit codes](cli.md#exit-codes). diff --git a/docs/skill.md b/docs/skill.md new file mode 100644 index 0000000..a51ffde --- /dev/null +++ b/docs/skill.md @@ -0,0 +1,49 @@ +# Claude Code / ClawHub skill + +This package ships one umbrella skill source at [`skills/aeo/SKILL.md`](../skills/aeo/SKILL.md). + +ClawHub package: [arberx/aeo](https://clawhub.ai/arberx/aeo) + +## Command + +```text +/aeo [flags] +``` + +## Modes + +- `audit`: grading and diagnosis +- `fix`: code changes after an audit +- `schema`: JSON-LD validation +- `llms`: generate `llms.txt` and `llms-full.txt` +- `monitor`: before/after tracking or competitor comparisons + +## Examples + +```text +/aeo audit https://example.com +/aeo fix https://example.com +/aeo schema https://example.com +/aeo llms https://example.com +/aeo monitor https://site-a.com --compare https://site-b.com +``` + +## Install + +```bash +# Personal install +git clone https://github.com/AINYC/aeo-audit.git /tmp/aeo-audit +cp -r /tmp/aeo-audit/skills/aeo ~/.claude/skills/ + +# Or project-level +cp -r /tmp/aeo-audit/skills/aeo .claude/skills/ +``` + +## Testing the skill from this repo + +If you're testing the skill from a local checkout instead of the published package, build first and use the local CLI: + +```bash +pnpm run build +node bin/aeo-audit.js https://example.com --format json +``` From d7e934a6e484849b15acaeba2a585b631441a0fc Mon Sep 17 00:00:00 2001 From: Arber Xhindoli <14798762+arberx@users.noreply.github.com> Date: Wed, 3 Jun 2026 15:47:56 -0400 Subject: [PATCH 2/2] chore: point GitHub repo URLs at Canonry/aeo-audit after repo move The GitHub repository moved from the AINYC org to Canonry. Update every github.com/AINYC/aeo-audit reference (README, CONTRIBUTING, docs/skill.md, package.json repository + bugs URLs, skills/aeo/SKILL.md) and the local origin remote. Deliberately left unchanged: the @ainyc/aeo-audit npm scope (package identity, not moved), the ainyc.ai homepage, the LICENSE copyright entity, the AINYC-AEO-Audit User-Agent strings, and the historical CHANGELOG note. Co-Authored-By: Claude Opus 4.8 --- CONTRIBUTING.md | 2 +- README.md | 2 +- docs/skill.md | 2 +- package.json | 4 ++-- skills/aeo/SKILL.md | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dee452b..36934fd 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,7 +3,7 @@ ## Getting Started ```bash -git clone https://github.com/AINYC/aeo-audit.git +git clone https://github.com/Canonry/aeo-audit.git cd aeo-audit pnpm install pnpm run typecheck diff --git a/README.md b/README.md index 72caf90..c622757 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ Modes: audit, fix, schema, `llms.txt`, monitor. See the [skill guide](docs/skill ## Contributing ```bash -git clone https://github.com/AINYC/aeo-audit.git && cd aeo-audit +git clone https://github.com/Canonry/aeo-audit.git && cd aeo-audit pnpm install && pnpm run typecheck && pnpm run build && pnpm test && pnpm lint ``` diff --git a/docs/skill.md b/docs/skill.md index a51ffde..234725e 100644 --- a/docs/skill.md +++ b/docs/skill.md @@ -32,7 +32,7 @@ ClawHub package: [arberx/aeo](https://clawhub.ai/arberx/aeo) ```bash # Personal install -git clone https://github.com/AINYC/aeo-audit.git /tmp/aeo-audit +git clone https://github.com/Canonry/aeo-audit.git /tmp/aeo-audit cp -r /tmp/aeo-audit/skills/aeo ~/.claude/skills/ # Or project-level diff --git a/package.json b/package.json index 845fede..454d56a 100644 --- a/package.json +++ b/package.json @@ -76,10 +76,10 @@ "license": "MIT", "repository": { "type": "git", - "url": "https://github.com/AINYC/aeo-audit.git" + "url": "https://github.com/Canonry/aeo-audit.git" }, "homepage": "https://ainyc.ai", "bugs": { - "url": "https://github.com/AINYC/aeo-audit/issues" + "url": "https://github.com/Canonry/aeo-audit/issues" } } diff --git a/skills/aeo/SKILL.md b/skills/aeo/SKILL.md index f11a825..295f749 100644 --- a/skills/aeo/SKILL.md +++ b/skills/aeo/SKILL.md @@ -2,7 +2,7 @@ name: aeo description: Run AEO audits, fix site issues, validate schema, generate llms.txt, and compare sites. homepage: https://ainyc.ai -repository: https://github.com/AINYC/aeo-audit +repository: https://github.com/Canonry/aeo-audit allowed-tools: - Bash(npx @ainyc/aeo-audit@1 *) - Read