AI Search Audit (Lite) skill

Illustration · not a resultFrom the Olexan-art/ai-search-audit README — shows the whole collection, not only this skill.source ↗
Audits 1 public web page for search and AI search (SEO and GEO): robots.txt for Googlebot and AI crawlers (GPTBot, OAI-SearchBot, ClaudeBot, PerplexityBot), noindex, snippets, title, headings, canonical, structured data, hreflang, how an AI retriever reads the page, and what the agent's model knows about the brand.
by Olexan-art·MIT license·★ 2 Stars on the repo·GitHub ↗
npx degit Olexan-art/ai-search-audit/skills/ai-search-audit#main ~/.claude/skills/ai-search-auditChecked ·commit main
Files of AI Search Audit (Lite)
Show the full text128 lines
Version 2.110. The first number changes only on a breaking change.
AI Search Audit (Lite)
Purpose
The skill checks 1 public page against the published rules for crawling, indexing and quoting by Google, Bing and AI assistants, and writes 1 report. You add 4 judgement files; the report marks those findings as your judgement, with your model's name. The report lists problems only, with no explanations and no fixes.
Requirements
- Node 20.18 or later (
node --version). If it is missing or older, tell the user and stop. - No install:
dist/read.mjsanddist/audit.mjs(withdist/chunks/) are bundled. $SKILLis the folder of this SKILL.md:${CLAUDE_SKILL_DIR}in Claude Code; on claude.ai, the sandbox path you read this file from.- Work in a writable directory of your own.
- Network: the page and a capped set of its site's files, links and images; first 1 DNS lookup and 1 RDAP request to
rdap.org(sends the site's IP address only). Nothing is uploaded: no server of ours, no account.
Rules
- R1. Answer the user in the language they wrote in.
- R2. Never re-create the audit by hand. If the scripts cannot run, tell the user what would make them run, and stop. Do not fetch or check the page another way.
- R3. Write every JSON file with the file-writing tool, never a shell heredoc (heredocs break on apostrophes).
- R4. Never write Russian.
- R5. The scripts call no model. Do not add a score of your own.
- R6. Use a saved copy (
--html) only when the user gives you one. Never make one with a browsing or fetch tool. - R7. After a refusal, do not retry another URL unless the user asks.
- R8. Do not volunteer fixes. If the user asks, answer from your own knowledge and say the advice is yours, not the report's. The full version is from GetLoopLoop (https://www.getlooploop.com).
Procedure
- Read the page (script).
node "$SKILL/dist/read.mjs" <url> --out reading.json- Options:
--rendercompares with a JavaScript render in a local Chrome or Chromium (an empty app shell is rendered without it);--save-html page.htmlkeeps the fetched copy. - Saved copy:
--html saved.html --final-url <url>(and--robots saved-robots.txt). Nothing is fetched; network checks are reported as not measured. - Result:
reading.jsonandreviews.template.json; prints every cap hit. - On failure:
REFUSED <code>(exit code 2). See Refusal codes.
- Options:
- Write questions.json and style.json (judgement). Read the
textof every passage inreading.json(vs.passages) in full. Write 8 to 12 spoken questions and judge each against the passages. Mark every passagespecificorgeneric. - Write brand.json (judgement). Name the site's own brand. Answer the 5 fixed questions from your own knowledge only.
- Write reviews.json (judgement). Fill in
reviews.template.jsonand write it asreviews.json. - Check the files (script).
node "$SKILL/dist/audit.mjs" reading.json --questions questions.json --style style.json --brand brand.json --reviews reviews.json --check- Result: validates the 4 files; writes nothing. A
warningline is advice, not a refusal. - On failure:
REFUSED <file>: <reason>. Fix that file as the message says and run step 5 again.
- Result: validates the 4 files; writes nothing. A
- Write the report (script).
node "$SKILL/dist/audit.mjs" reading.json --questions questions.json --style style.json --brand brand.json --reviews reviews.json --html report.html --md report.md --json export.json- Add
--keyword "phrase"when the user gave a target keyword; otherwise the keyword comes from the h1. - Result: the 3 files; prints the problems numbered as on the map, judgement findings marked
(judgement).
- Add
- Show the report. Required; see Show the report.
Judgement files
Read references/judgement-files.md before you write them: schemas, examples, full rules.
- All 4:
agent(for example "Claude Code", "claude.ai", "Codex", "opencode", "Hermes") andmodel, at most 60 characters each. If you do not know one, leave it out. Never guess either. - Letters: the script refuses a letter Russian uses and the page's language does not (on a Ukrainian page, the 4 Russian-only letters; Bulgarian and Belarusian keep their own). Quotes are checked against the passage.
- questions.json: 8 to 12 spoken, first-person questions in the page's language.
axes: 1 to 3 ofurgency,device,object,obstacle; each axis used at least once.- Most without the page's keyword. No wake words. None that is another with words added. At least 1 the page probably does not answer.
- Judge from the passages only, never from what you know.
passage: theindexof a passage invs.passages(0-based), ornull.verdict:complete,partialormissing. quote: verbatim from the passage, at most 400 characters, none formissing.
- style.json: 1 verdict per passage:
generic(fits a competitor's page with the brand name changed) orspecific.evidence: verbatim, at most 200 characters. Judge the passage, not who wrote it: this is not an AI detector. - brand.json:
basis: "own_knowledge"; answerwhat_is,pricing,integrations,weaknesses,alternativesin English or the page's language.- Not sure (for example a price range):
"knows": true, and write "I am not sure" in the answer. - Do not know:
"knows": false,"answer": "". - The script sets
knowsto false when the first 400 characters disclaim knowledge ("I don't have information", "I'm not familiar", "I don't know of"). "I am not sure" does not.
- Not sure (for example a price range):
- reviews.json:
basis: "own_knowledge"; every platform of the template once, none added or removed;"knows": truewith aratingon its scale, or"knows": false. Judge each platform separately, from your own knowledge of the brand on that platform. - Honesty (brand and reviews): answer from what you already knew. No browsing, search, fetch or other tool; not from the page. "I don't know" is a correct answer. Do not present a guess as a fact or copy the page into an answer.
Verification
- Every JSON file was written with the file-writing tool.
- Step 5 printed no
REFUSED. -
report.htmlexists.
Show the report
Required. The HTML report is the result; a chat message alone, or the file name alone, has not shown it.
If the user or caller said not to publish or open anything, stop when the HTML file exists and give its absolute path. This overrides the bullets below.
Present one file: report.html. Keep report.md and export.json beside it; do not present, attach, open or preview them. Never open or preview export.json or report.md as the result, and never end the reply on either: the HTML is the report. If the environment shows the last file you present, it must be the HTML.
- claude.ai or the Claude desktop app: save the 3 files where your instructions say user files go, and present only
report.htmlas a file in your reply, not even followed by the others. A file in a scratch folder the user cannot see is not shown. Do not retype the report into an artifact. - Claude Code: publish only
report.htmlwith an HTML or artifact publishing tool, if the session has one, and give the link. Otherwise open it:start "" "<absolute path>"(Windows),open "<absolute path>"(macOS),xdg-open "<absolute path>"(Linux), and give the path. - Codex, opencode, Hermes Agent or any other agent: give the absolute path of
report.htmland offer to open it with the command above or a preview tool. Preview only the HTML. Name the other 2 files only if the user asks for the data.
The report makes no network requests. It opens in English and in the light theme; add #lang=uk, #lang=pl or #theme=dark (for example report.html#lang=pl&theme=dark). Give the #lang link when the user writes in Ukrainian or Polish.
Chat summary
- First, if present:
ai_search_blocked,search_engine_blocked,robots_unreachable,snippet_blockedornoindex. - The verdict line and the counts by severity.
- Problems 1 to 5, each with its place.
- Every cap the audit printed (links past 30, images past 20, alternates past 10, child sitemaps past 5, merged sections, a render that could not run).
- Once: the checks are deterministic; the questions, brand and reviews are your judgement as 1 model (name it), not what ChatGPT, Gemini or Perplexity say (the web Brandscope and Reviewscope ask 3 assistants).
- 1 line: Pattern score and band, marker words per 1,000, passages you judged generic (derived, derived, your judgement). Never say the page was or was not written by AI.
- Never claim an assistant has indexed, ranks or will cite the page.
Refusal codes
| Code | Tell the user |
|---|---|
invalid_url |
Not a web address. Ask for the full URL. |
blocked_scheme |
Only http and https pages can be read. |
blocked_host, blocked_address |
Not a public page: localhost, a private network or a non-standard port. |
unreachable |
The page could not be reached. Read references/network-and-limits.md. |
http_error |
An error status (in the reading), or more than 5 redirects. |
blocked |
The site turns automated readers away (HTTP 401, 403 or 429). Retrying will not help. |
not_html |
A file such as a PDF or an image, not an HTML page. |
too_large |
Over the 3 MB ceiling. |
empty |
No readable text after navigation and boilerplate were removed. |
refused_ru_domain |
A Russian domain zone (.ru, .su, .рф, .москва, .moscow); not fetched. |
refused_ru_hosting |
Hosted in Russia (RDAP country RU); not fetched. |
refused_ru_audience |
The site declares a Russian-language version (hreflang, og:locale or Content-Language). |
refused_language_ru |
The page is in Russian. |
On a refused_ru_* or refused_language_ru code: skip steps 2 to 5, run step 6 without the judgement files, show the report, tell the user in 1 line that this tool does not analyse such pages (the code's line), and stop. Do not analyse the page another way.
References
| File | Read when |
|---|---|
references/judgement-files.md |
Before steps 2 to 4. |
references/checks.md |
The user asks about a finding code, tile, severity, threshold or check. |
references/network-and-limits.md |
What is sent; a failed fetch; no network; a read-only skill folder. |
references/outputs.md |
The user asks for the data or what a file holds. |
| 1 | |
| 2 | name ai-search-audit |
| 3 | description Audits 1 public web page for search and AI search (SEO and GEO): robots.txt for Googlebot and AI crawlers (GPTBot, OAI-SearchBot, ClaudeBot, PerplexityBot), noindex, snippets, title, headings, canonical, structured data, hreflang, how an AI retriever reads the page, and what the agent's model knows about the brand. Output: an HTML report. Use for an SEO or GEO audit of 1 page, AI search readiness, or why Google, ChatGPT or Perplexity do not show or quote a page, or when the user names ai-search-audit. For at most 50 pages, history and fix directions, use ai-search-audit-full. For passages only, use vectorscope. |
| 4 | |
| 5 | |
| 6 | Version 2.110. The first number changes only on a breaking change. |
| 7 | |
| 8 | # AI Search Audit (Lite) |
| 9 | |
| 10 | ## Purpose |
| 11 | |
| 12 | The skill checks 1 public page against the published rules for crawling, indexing and quoting by Google, Bing and AI assistants, and writes 1 report. You add 4 judgement files; the report marks those findings as your judgement, with your model's name. The report lists problems only, with no explanations and no fixes. |
| 13 | |
| 14 | ## Requirements |
| 15 | |
| 16 | Node 20.18 or later (`node --version`). If it is missing or older, tell the user and stop. |
| 17 | No install: `dist/read.mjs` and `dist/audit.mjs` (with `dist/chunks/`) are bundled. |
| 18 | `$SKILL` is the folder of this SKILL.md: `${CLAUDE_SKILL_DIR}` in Claude Code; on claude.ai, the sandbox path you read this file from. |
| 19 | Work in a writable directory of your own. |
| 20 | Network: the page and a capped set of its site's files, links and images; first 1 DNS lookup and 1 RDAP request to `rdap.org` (sends the site's IP address only). Nothing is uploaded: no server of ours, no account. |
| 21 | |
| 22 | ## Rules |
| 23 | |
| 24 | R1. Answer the user in the language they wrote in. |
| 25 | R2. Never re-create the audit by hand. If the scripts cannot run, tell the user what would make them run, and stop. Do not fetch or check the page another way. |
| 26 | R3. Write every JSON file with the file-writing tool, never a shell heredoc (heredocs break on apostrophes). |
| 27 | R4. Never write Russian. |
| 28 | R5. The scripts call no model. Do not add a score of your own. |
| 29 | R6. Use a saved copy (`--html`) only when the user gives you one. Never make one with a browsing or fetch tool. |
| 30 | R7. After a refusal, do not retry another URL unless the user asks. |
| 31 | R8. Do not volunteer fixes. If the user asks, answer from your own knowledge and say the advice is yours, not the report's. The full version is from GetLoopLoop (https://www.getlooploop.com). |
| 32 | |
| 33 | ## Procedure |
| 34 | |
| 35 | **Read the page (script).** `node "$SKILL/dist/read.mjs" <url> --out reading.json` |
| 36 | Options: `--render` compares with a JavaScript render in a local Chrome or Chromium (an empty app shell is rendered without it); `--save-html page.html` keeps the fetched copy. |
| 37 | Saved copy: `--html saved.html --final-url <url>` (and `--robots saved-robots.txt`). Nothing is fetched; network checks are reported as not measured. |
| 38 | Result: `reading.json` and `reviews.template.json`; prints every cap hit. |
| 39 | On failure: `REFUSED <code>` (exit code 2). See *Refusal codes*. |
| 40 | **Write questions.json and style.json (judgement).** Read the `text` of every passage in `reading.json` (`vs.passages`) in full. Write 8 to 12 spoken questions and judge each against the passages. Mark every passage `specific` or `generic`. |
| 41 | **Write brand.json (judgement).** Name the site's own brand. Answer the 5 fixed questions from your own knowledge only. |
| 42 | **Write reviews.json (judgement).** Fill in `reviews.template.json` and write it as `reviews.json`. |
| 43 | **Check the files (script).** `node "$SKILL/dist/audit.mjs" reading.json --questions questions.json --style style.json --brand brand.json --reviews reviews.json --check` |
| 44 | Result: validates the 4 files; writes nothing. A `warning` line is advice, not a refusal. |
| 45 | On failure: `REFUSED <file>: <reason>`. Fix that file as the message says and run step 5 again. |
| 46 | **Write the report (script).** `node "$SKILL/dist/audit.mjs" reading.json --questions questions.json --style style.json --brand brand.json --reviews reviews.json --html report.html --md report.md --json export.json` |
| 47 | Add `--keyword "phrase"` when the user gave a target keyword; otherwise the keyword comes from the h1. |
| 48 | Result: the 3 files; prints the problems numbered as on the map, judgement findings marked `(judgement)`. |
| 49 | **Show the report.** Required; see *Show the report*. |
| 50 | |
| 51 | ## Judgement files |
| 52 | |
| 53 | Read `references/judgement-files.md` before you write them: schemas, examples, full rules. |
| 54 | |
| 55 | **All 4:** `agent` (for example "Claude Code", "claude.ai", "Codex", "opencode", "Hermes") and `model`, at most 60 characters each. If you do not know one, leave it out. Never guess either. |
| 56 | **Letters:** the script refuses a letter Russian uses and the page's language does not (on a Ukrainian page, the 4 Russian-only letters; Bulgarian and Belarusian keep their own). Quotes are checked against the passage. |
| 57 | **questions.json:** 8 to 12 spoken, first-person questions in the page's language. |
| 58 | `axes`: 1 to 3 of `urgency`, `device`, `object`, `obstacle`; each axis used at least once. |
| 59 | Most without the page's keyword. No wake words. None that is another with words added. At least 1 the page probably does not answer. |
| 60 | Judge from the passages only, never from what you know. `passage`: the `index` of a passage in `vs.passages` (0-based), or `null`. `verdict`: `complete`, `partial` or `missing`. |
| 61 | `quote`: verbatim from the passage, at most 400 characters, none for `missing`. |
| 62 | **style.json:** 1 verdict per passage: `generic` (fits a competitor's page with the brand name changed) or `specific`. `evidence`: verbatim, at most 200 characters. Judge the passage, not who wrote it: this is not an AI detector. |
| 63 | **brand.json:** `basis: "own_knowledge"`; answer `what_is`, `pricing`, `integrations`, `weaknesses`, `alternatives` in English or the page's language. |
| 64 | Not sure (for example a price range): `"knows": true`, and write "I am not sure" in the answer. |
| 65 | Do not know: `"knows": false`, `"answer": ""`. |
| 66 | The script sets `knows` to false when the first 400 characters disclaim knowledge ("I don't have information", "I'm not familiar", "I don't know of"). "I am not sure" does not. |
| 67 | **reviews.json:** `basis: "own_knowledge"`; every platform of the template once, none added or removed; `"knows": true` with a `rating` on its scale, or `"knows": false`. Judge each platform separately, from your own knowledge of the brand on that platform. |
| 68 | **Honesty (brand and reviews):** answer from what you already knew. No browsing, search, fetch or other tool; not from the page. "I don't know" is a correct answer. Do not present a guess as a fact or copy the page into an answer. |
| 69 | |
| 70 | ## Verification |
| 71 | |
| 72 | [ ] Every JSON file was written with the file-writing tool. |
| 73 | [ ] Step 5 printed no `REFUSED`. |
| 74 | [ ] `report.html` exists. |
| 75 | |
| 76 | ## Show the report |
| 77 | |
| 78 | Required. The HTML report is the result; a chat message alone, or the file name alone, has not shown it. |
| 79 | |
| 80 | If the user or caller said not to publish or open anything, stop when the HTML file exists and give its absolute path. This overrides the bullets below. |
| 81 | |
| 82 | **Present one file: `report.html`.** Keep `report.md` and `export.json` beside it; do not present, attach, open or preview them. Never open or preview `export.json` or `report.md` as the result, and never end the reply on either: the HTML is the report. If the environment shows the last file you present, it must be the HTML. |
| 83 | |
| 84 | **claude.ai or the Claude desktop app:** save the 3 files where your instructions say user files go, and present **only `report.html`** as a file in your reply, not even followed by the others. A file in a scratch folder the user cannot see is not shown. Do not retype the report into an artifact. |
| 85 | **Claude Code:** publish only `report.html` with an HTML or artifact publishing tool, if the session has one, and give the link. Otherwise open it: `start "" "<absolute path>"` (Windows), `open "<absolute path>"` (macOS), `xdg-open "<absolute path>"` (Linux), and give the path. |
| 86 | **Codex, opencode, Hermes Agent or any other agent:** give the absolute path of `report.html` and offer to open it with the command above or a preview tool. Preview only the HTML. Name the other 2 files only if the user asks for the data. |
| 87 | |
| 88 | The report makes no network requests. It opens in English and in the light theme; add `#lang=uk`, `#lang=pl` or `#theme=dark` (for example `report.html#lang=pl&theme=dark`). Give the `#lang` link when the user writes in Ukrainian or Polish. |
| 89 | |
| 90 | ## Chat summary |
| 91 | |
| 92 | First, if present: `ai_search_blocked`, `search_engine_blocked`, `robots_unreachable`, `snippet_blocked` or `noindex`. |
| 93 | The verdict line and the counts by severity. |
| 94 | Problems 1 to 5, each with its place. |
| 95 | Every cap the audit printed (links past 30, images past 20, alternates past 10, child sitemaps past 5, merged sections, a render that could not run). |
| 96 | Once: the checks are deterministic; the questions, brand and reviews are your judgement as 1 model (name it), not what ChatGPT, Gemini or Perplexity say (the web Brandscope and Reviewscope ask 3 assistants). |
| 97 | 1 line: Pattern score and band, marker words per 1,000, passages you judged generic (derived, derived, your judgement). Never say the page was or was not written by AI. |
| 98 | Never claim an assistant has indexed, ranks or will cite the page. |
| 99 | |
| 100 | ## Refusal codes |
| 101 | |
| 102 | | Code | Tell the user | |
| 103 | |---|---| |
| 104 | | `invalid_url` | Not a web address. Ask for the full URL. | |
| 105 | | `blocked_scheme` | Only http and https pages can be read. | |
| 106 | | `blocked_host`, `blocked_address` | Not a public page: localhost, a private network or a non-standard port. | |
| 107 | | `unreachable` | The page could not be reached. Read `references/network-and-limits.md`. | |
| 108 | | `http_error` | An error status (in the reading), or more than 5 redirects. | |
| 109 | | `blocked` | The site turns automated readers away (HTTP 401, 403 or 429). Retrying will not help. | |
| 110 | | `not_html` | A file such as a PDF or an image, not an HTML page. | |
| 111 | | `too_large` | Over the 3 MB ceiling. | |
| 112 | | `empty` | No readable text after navigation and boilerplate were removed. | |
| 113 | | `refused_ru_domain` | A Russian domain zone (.ru, .su, .рф, .москва, .moscow); not fetched. | |
| 114 | | `refused_ru_hosting` | Hosted in Russia (RDAP country RU); not fetched. | |
| 115 | | `refused_ru_audience` | The site declares a Russian-language version (hreflang, og:locale or Content-Language). | |
| 116 | | `refused_language_ru` | The page is in Russian. | |
| 117 | |
| 118 | On a `refused_ru_*` or `refused_language_ru` code: skip steps 2 to 5, run step 6 without the judgement files, show the report, tell the user in 1 line that this tool does not analyse such pages (the code's line), and stop. Do not analyse the page another way. |
| 119 | |
| 120 | ## References |
| 121 | |
| 122 | | File | Read when | |
| 123 | |---|---| |
| 124 | | `references/judgement-files.md` | Before steps 2 to 4. | |
| 125 | | `references/checks.md` | The user asks about a finding code, tile, severity, threshold or check. | |
| 126 | | `references/network-and-limits.md` | What is sent; a failed fetch; no network; a read-only skill folder. | |
| 127 | | `references/outputs.md` | The user asks for the data or what a file holds. | |
| 128 |
Discussion
Alternatives
Browse more free Claude skills or everything in Marketing.