← Plugin catalog
Developer Tools

AEOTester

Ruslan Saifullin v0.3.0

AI SEO audit and fix

Full description ↓

View on ChatGPT ↗

Save this plugin to Following and return to review observed changes. Follow up to 10 plugins free.

Description

From the marketplace listing

Checks whether AI search engines can find, read and cite your website. Scores a site on 26 checks for AI search visibility (AEO and GEO), from the site's code in your repository or from a live URL. Then fixes what it can in your code: JSON-LD schema markup, llms.txt, robots.txt rules for AI crawlers, and title, description and Open Graph tags. Every change is shown as a diff before it is written, and nothing is committed for you. It runs local Node scripts, so it needs an environment that can run Node 18 or newer, such as Codex. URL mode sends GET requests only to the site you name.

Language: English · Automatically detected from descriptions.

What changed

AEOTester

Oct 27, 2026 · 1 saved observations

Metadata · Oct 27, 2026 · 01:05 UTC · Compared with Oct 24, 2026 · 13:55 UTC

WHAT CHANGED

Package or technical metadata updated

Package or technical metadata updated

Observed in package metadata. These changes alone do not establish a new customer-facing feature.

Open full comparison.

Is v2 template

Before

Oct 24, 2026 · 13:55 UTC

Not present

After

Oct 27, 2026 · 01:05 UTC

false

Metadata: full comparison →

Competitor profile

From the developer’s listing and package; capabilities are not independently tested. Package observed Nov 2, 2026.

Declared capabilities

  • Read
  • Write

Declared limitations

Specific limitations have not been established. Missing information does not mean unrestricted capabilities.

Cost & access

Pricing and account requirements have not been established from the available package declarations. Unknown pricing does not mean free access.

Starter prompt

Audit this site for AI search visibility.

View package source →

Keywords

Files & skills

File archives

Plugin package79 files · 202 KBBrowse files →
Skill instructions
audit8.53 KB

View saved version →

---
name: audit
description: AI SEO audit of a website - the AEOTester checklist for answer engine optimization (AEO) and generative engine optimization (GEO), 26 checks and 133 points - with a scored report in aeotester-report.md. Audits the site code in the current repo, or a live site when given a URL. Use when the user asks to audit a site or URL for AI search visibility, AI SEO, AEO, GEO, llms.txt, schema markup, AI crawler access or agent readiness.
argument-hint: "[site-folder | https://site.com[/page]] [--pages N] [--all]"
allowed-tools: Read, Glob, Grep, Bash(node --version), Bash(node ${CLAUDE_PLUGIN_ROOT}/skills/audit/scripts/audit.mjs:*)
---

# AEOTester audit

Audits a site against the AEOTester rubric and writes `aeotester-report.md` in the current directory (for a folder: in that folder).

Two ways to run it:

- **Repo mode** (no argument, or a folder): reads the site's files in this repo. No network requests.
- **URL mode** (an `http://` or `https://` URL): fetches the live site, the way an AI crawler sees it.
  - A page URL (`https://site.com/blog/post`) audits that one page, plus the site-wide files (robots.txt, llms.txt, sitemap, `/.well-known/`).
  - The homepage (`https://site.com`) audits a sample: the homepage, the pages linked from the header, nav and footer, and a listing page plus one item from each section (blog, docs, products...), about 25 pages at most. One page per template finds nearly every issue without crawling the whole site.
  - `--pages N` changes the sample size. `--all` audits every page found (up to 500, or `--pages N`).
  - Requests go to that site only, are polite (a few at a time, with timeouts) and skip pages that robots.txt disallows. The README lists exactly what is fetched.

## Other hosts (Codex, ChatGPT)

The commands below start with Claude Code's plugin-root variable. A host that does not substitute it (Codex, ChatGPT) leaves it as literal text: replace that prefix with the absolute path of the plugin root, which is the folder two levels above the folder that contains this SKILL.md (it holds `skills/`). Do the same for the skill-folder variable, which is the folder that contains this SKILL.md. Write the resolved path into the command; never run it with the variable unexpanded. Slash commands such as `/aeotester:audit` are Claude Code syntax: elsewhere the user asks for this skill by name or mention, and `$ARGUMENTS` means whatever folder, URL or flags their request names (leave it out if there are none). The scripts need Node 18+ and a shell, so the skill only works in a host that can run them.

## Rules

- Read-only. The only file written is the report, and the script writes it. Never edit site files here; fixes belong to `/aeotester:fix`.
- Repo mode stays inside the current repo and makes no network requests.
- URL mode only fetches the site the user named. Use it only when the user gave a URL or asked for the live site.

## Steps

1. **Check Node.** Run `node --version`. The scripts need Node 18 or newer. If Node is missing, tell the user the audit needs Node 18+ and stop.

2. **Run the audit.** Pass the user's arguments through (`$ARGUMENTS`, default `.`):

   ```bash
   node ${CLAUDE_PLUGIN_ROOT}/skills/audit/scripts/audit.mjs $ARGUMENTS
   ```

   It prints a short summary and writes `aeotester-report.md`.

3. **Handle the mode the summary reports:**
   - **"No build output found"** (Astro, Next.js, Hugo, Eleventy, Vite): the audit reads built HTML because that is what crawlers and agents receive. Ask the user whether to run the build command it names. Only run it if they say yes, then run the audit again. If they say no, offer URL mode on the deployed site instead.
   - **Report-only** (WordPress or another database-backed CMS): page content lives in the database, so the repo cannot be scored. Say so plainly and offer to audit the live site with `/aeotester:audit https://their-site.com`. Do not try to edit anything.
   - **No pages found**: in repo mode, ask where the site's HTML lives; in URL mode, say the site could not be fetched and show the status from the summary (it may block automated requests).

4. **Summarize in chat** in a few lines, not the whole report:
   - the score, percentage and grade, and in URL mode how many pages were audited,
   - the three to five issues that lose the most points (see "Writing each issue" below),
   - pages left out of the score and advice (see "Not scored and advice" below),
   - checks marked "predicted from config" or "inconclusive" that the user should confirm (see "Live checks" below),
   - the next step: in repo mode, `/aeotester:fix` applies the auto-fixable items, always with a diff and a confirmation first; in URL mode, open the site's code and run `/aeotester:fix` there.

   Link the report file. Do not paste it.

   **Writing each issue.** Write for someone who has never seen the rubric:
   - Say what the check looks for and why it matters to AI search or agents, in one plain sentence, before the finding.
   - Show a short concrete example of what is missing or what the fix adds, such as the exact tag or line. For Content Signals, for example: "`robots.txt` sets rules for GPTBot and ClaudeBot, but has no `Content-Signal:` line. That line tells AI companies whether they may use your pages for search results, as answer input, or for training, for example `Content-Signal: search=yes, ai-input=yes, ai-train=no`."
   - Never show bare rubric labels such as "auto-fix", "assisted" or "inconclusive". Say what they mean instead: "`/aeotester:fix` can change this for you" (auto-fix; after a URL audit, add "in the site's code"), "needs your input, such as dates or copy, so the fix will guide you" (assisted), "can't be confirmed from the files, check the live site" (inconclusive or predicted from config in repo mode), "the site blocked or did not answer this request, so it was not scored down" (inconclusive in URL mode).
   - Name the affected pages as Markdown links to the page on the live site: the page's canonical URL if it has one, otherwise the base URL plus the served path. Without a known base URL, link the file path instead. List up to 10 pages inline, then say "and N other pages". Get the full list from `--json`, because the printed report shortens it.

   **Not scored and advice.** Neither of these costs points, so never present them as issues or count them as points lost:
   - `excludedPages` in `--json` lists pages kept out of search on purpose (noindex, not the homepage, not in the sitemap). Say in one line that they were not scored and why, linking them like other pages, for example "[privacy](https://site.com/privacy) and [terms](https://site.com/terms) are kept out of search on purpose, so they were not scored". A noindex page the sitemap lists is a real issue and appears under Indexability instead.
   - Checks with `advice` (and the advisory Content Signals check, status `advice`) go in a short "Worth considering" list after the issues, each with the same plain explanation and example as an issue, and a note that it may be deliberate. For example: Content Signals (no line in robots.txt, which leaves AI use unrestricted), answering `Accept: text/markdown` when a Markdown copy is already linked, or a "last updated" date on a privacy page.

   **Live checks.** In repo mode, checks marked "predicted from config" or "inconclusive" can be measured on the deployed site. First offer a URL audit: `/aeotester:audit https://their-site.com` (or the single page URL). For one quick check, the user can also run a command themselves: give it with the `!` prefix (for example `! curl -sI -H "Accept: text/markdown" https://example.com/`) so the output lands in the conversation, say what a pass looks like (here, `Content-Type: text/markdown` in the response headers), and once they run it, read the output and tell them the result. In URL mode these checks were already measured; only "inconclusive" ones (the site blocked or timed out) are worth retrying later.

## Reference

- `references/rubric.json` holds every check: weight, scoring rules, how it is detected, and where results from source can differ from a live page (`parity`). Look up a single check by `id` when the user asks why something scored the way it did; do not load the whole file into the conversation.
- `audit.mjs ... --json -` prints the full machine-readable result, which is useful for answering detailed questions.
- Repo mode: `--base-url https://site.com` sets the production URL when the repo does not reveal it (used to tell internal from external links and to check canonical URLs).
- URL mode: `--ignore-robots` also audits pages that robots.txt disallows. Only use it when the user owns the site and asks for it.

Referenced files: 41 — file references are metadata, not package contents.

fix7.14 KB

View saved version →

---
name: fix
description: Apply AEOTester AI SEO fixes in the current repo - JSON-LD schema markup, llms.txt, robots.txt AI crawler rules, Content Signals, meta and social tags, heading hierarchy, language and viewport tags. Shows a diff and asks before writing anything, then re-audits to show the score change.
argument-hint: "[check-id ...] [--yes]"
disable-model-invocation: true
allowed-tools: Read, Glob, Grep, AskUserQuestion, Bash(node --version), Bash(node ${CLAUDE_PLUGIN_ROOT}/skills/audit/scripts/audit.mjs:*), Bash(node ${CLAUDE_PLUGIN_ROOT}/skills/fix/scripts/page-facts.mjs:*), Bash(node ${CLAUDE_PLUGIN_ROOT}/skills/fix/scripts/generate-llms-txt.mjs:*)
---

# AEOTester fix

Fixes the problems `/aeotester:audit` found, in the site's source files.

## Other hosts (Codex, ChatGPT)

The commands below start with Claude Code's plugin-root variable. A host that does not substitute it (Codex, ChatGPT) leaves it as literal text: replace that prefix with the absolute path of the plugin root, which is the folder two levels above the folder that contains this SKILL.md (it holds `skills/`). Do the same for the skill-folder variable, which is the folder that contains this SKILL.md. Write the resolved path into the command; never run it with the variable unexpanded. Slash commands such as `/aeotester:audit` are Claude Code syntax: elsewhere the user asks for this skill by name or mention, and `$ARGUMENTS` means whatever folder, URL or flags their request names (leave it out if there are none). The scripts need Node 18+ and a shell, so the skill only works in a host that can run them.

## Non-negotiable rules

1. **Diff first, then ask.** Before the first Edit or Write, print every planned change as a unified diff in your reply and get the user's approval. `--yes` in the arguments means the user approved in advance: you skip the question, never the diffs. Print them first, then apply.
2. **Never commit, push, stash or change git state.** Never delete files.
3. **Only touch files inside the current repo.** Never edit build output (`dist/`, `_site/`, `out/`, `.next/`, Hugo's `public/`). Fix the source that produces it.
4. **Never invent facts.** Names, people, job titles, credentials, prices, ratings, dates, addresses and social profiles come from the repo (`page-facts.mjs`) or from the user. If a fix needs a fact you do not have, ask, or skip that fix and say why.
5. **Policy choices belong to the user:** which AI bots to allow, and the Content-Signal values (search, ai-input, ai-train). Propose a default and ask.
6. **No network calls.**
7. **Reference only assets that exist.** An `og:image`, logo or icon URL must point at a file in the repo (check with Glob) or one the page already uses.
8. **Tools:** read files (recipes included) with Read, find them with Glob and Grep. Use Bash only for the `node` commands below, written exactly as shown (in Claude Code, an unquoted plugin path) so they match the pre-approved commands. Other shell commands may be denied, and a denied command does not mean `node` is unavailable.

## Steps

### 1. Audit

Check `node --version` (Node 18+ needed). Then run:

```bash
node ${CLAUDE_PLUGIN_ROOT}/skills/audit/scripts/audit.mjs . --no-report --json -
```

Note the score as `total / available` (for example 71/127): `available` already leaves out checks that do not apply. Read `site.mode` and `site.stack.id`:

- `report-only` (WordPress and other CMSs): stop. Content lives in the database; point the user to the fix list in `aeotester-report.md` (run `/aeotester:audit` first if it is missing). Do not edit files.
- `needs-build`: ask whether to run the build command from `site.notes`. Only build if they agree, then audit again.
- `nextjs`: every fix is assisted. Show the diffs as proposals and apply only the ones the user explicitly approves. Never use `--yes` shortcuts for Next.js.
- `full`: continue.

### 2. Choose what to fix

- With check ids in the arguments: fix exactly those, auto or assisted.
- Without: every check where `fixable` is `auto` and `lost` > 0, sorted by points lost. Skip `inconclusive` checks unless the finding is concrete.
- List assisted checks that lost points at the end, as "needs your input", with the command to run them (`/aeotester:fix content.author`). Do not attempt them unasked.
- Advice is not a fix list: checks with status `advice` (Content Signals) and `advice` entries cost no points and may be deliberate. Mention them once at the end as optional, with the command to apply one (`/aeotester:fix ai-access.content-signals`). Do not apply them unasked.
- Never touch pages listed in `excludedPages`: they are kept out of search on purpose and were not scored. Do not remove their noindex or add schema, Open Graph or Twitter tags to them.

### 3. Gather facts and recipes

```bash
node ${CLAUDE_PLUGIN_ROOT}/skills/fix/scripts/page-facts.mjs . [--pages file1.html,file2.html]
```

For each chosen check, open its recipe with the Read tool: `${CLAUDE_SKILL_DIR}/references/fix-recipes/<check-id>.md`. Read every recipe for a check you are about to fix and follow it; read only those. For llms.txt, draft with:

```bash
node ${CLAUDE_PLUGIN_ROOT}/skills/fix/scripts/generate-llms-txt.mjs .
```

Review the draft before proposing it: drop weak lines (for example "Click here to learn more"), keep links useful.

### 4. Find the source

For static HTML the flagged file is the source. For generated sites (Astro, Hugo, Eleventy, Vite, Next.js), findings point at built HTML; find the layout, partial, component or content file that produces it (Grep for the flagged text or tag). Prefer one change in a shared layout over the same change in many pages.

### 5. Plan and show the diff

Prepare all changes, then show them in one message, before any Edit or Write:

1. A table: file | check | what changes | expected points.
2. **One fenced `diff` block per file.** A table alone is not a diff. Use unified diff format with a few lines of context, for example:

   ```diff
   --- a/index.html
   +++ b/index.html
   @@ -3,4 +3,6 @@
      <meta charset="utf-8">
   -  <title>Home</title>
   +  <title>Visual bookmarks for research | InsightPins</title>
   +  <meta name="description" content="...">
   ```

3. For new files (llms.txt), the full content in a fenced block.

Then ask with AskUserQuestion (in a host without that tool, a plain question): **Apply all**, **Let me choose** (then ask per file or per check), or **Cancel**. With `--yes`, skip the question and apply, but only after the diffs are printed.

### 6. Apply

Use Edit for existing files (never rewrite a whole existing file with Write) and Write only for new files. Match the file's existing indentation and style. Apply only what the user approved.

### 7. Re-audit and report

Always re-audit; a fix run is not finished without the after score.

For generated sites, ask whether to rebuild before re-auditing (a re-audit without a rebuild reads the old output). Then:

```bash
node ${CLAUDE_PLUGIN_ROOT}/skills/audit/scripts/audit.mjs .
```

This rewrites `aeotester-report.md`. Report in chat:

- score before -> after as `total / available` with the percentage,
- what was fixed, per check,
- what was skipped and why,
- assisted items still open,
- a reminder that nothing was committed: review with `git diff`.

Referenced files: 29 — file references are metadata, not package contents.

Package details

Publisher declarations from the archived package. These are separate from our research and the live service's terms.

Package license
MIT
Package author
Ruslan Saifullin
Keywords
See keywords

Declared capabilities

  • Read
  • Write

Package observed Nov 2, 2026.

Technical details
First seen
Oct 24, 2026 · 12:40 UTC
Last seen
Nov 3, 2026 · 12:00 UTC
Collection status
Collected

plugins_6ac860d3ec748191a09c8ec8f87e8cca

Download plugin data (JSON)