seo-check — SEO checker skill for Claude Code

An open-source SEO checker skill and plugin for Claude Code: a pre-commit SEO audit. Run /seo-check before you commit: it reviews your pending git changes for SEO regressions, then crawls the affected routes the way Googlebot does and tells you whether the change is safe to ship.

test license: MIT

Homepage: antidote003.github.io/claude-seo-check

Most SEO disasters ship as innocent-looking diffs: a noindex left over from staging, a Disallow: line meant for one path that matches fifty, a deleted page whose URL has backlinks, a canonical pointing at the wrong host, a trailing comma that silently kills all your rich results. seo-check catches these before they're committed, not weeks later in Search Console.

What a run looks like

❌ Fix before committing — 3 blockers

BLOCKERS
1. about.html:7 — meta robots "noindex" added (replaced the canonical tag).
   Crawler confirms: ✗ NOINDEX_META on /about.html. This deindexes the page.
   Fix: remove the noindex, restore <link rel="canonical" ...>.
2. robots.txt:2 — "Disallow: /guides.html" added; the page is live and still
   in sitemap.xml. Crawler: ✗ ROBOTS_BLOCKED (Disallow: /guides.html).
3. index.html:11 — trailing comma makes the JSON-LD unparseable.
   Crawler: ✗ JSONLD_INVALID (position 70). All rich results lost.

WARNINGS
- index.html: meta description removed · new <img src="/table.png"> has no alt.

VERIFIED CLEAN  canonicals (index), redirects, headings, hreflang, sitemap.
PRE-EXISTING (not from this change)  thin content on /guides.html.

How it works

Two passes:

  1. Static audit — scopes git diff to SEO-relevant files (pages, layouts, metadata code, robots.txt/robots.ts, sitemaps, next.config.*, vercel.json, middleware, redirects), maps changed files to URL routes, and greps the diff against a regression checklist — reading full context before flagging anything, so a noindex behind a staging-env conditional isn't a false alarm.
  2. Live crawlcrawl.mjs, a zero-dependency Node script, fetches every affected route with a Googlebot-smartphone user-agent (mobile-first indexing) and reports what a search engine actually receives:
    • full redirect chains, final status, X-Robots-Tag
    • robots.txt evaluation using Google's longest-match rules
    • title/description presence + lengths, canonical (self-referencing? right host?)
    • meta robots, heading outline, word count of the initial HTML (catches content silently moving behind client-side JS)
    • Open Graph / Twitter cards, hreflang, html lang, viewport
    • JSON-LD extraction + validation with @type inventory
    • images missing alt (empty alt="" counted separately as decorative)
    • internal/external/nofollow link counts, sitemap membership

With a production URL it also fetches each route on both origins and diffs every signal — the most direct evidence of "did my change break anything."

The verdict is honest by design: blockers are limited to things that deindex pages, block crawling, 404 existing URLs, or destroy metadata/structured data; pre-existing issues are reported separately from regressions; skipped checks are named instead of silently omitted.

Install

As a plugin (recommended — inside Claude Code):

/plugin marketplace add AnTIdoTe003/claude-seo-check
/plugin install seo-check@claude-seo-check

Manually (personal skill, available in every project):

git clone https://github.com/AnTIdoTe003/claude-seo-check.git
ln -s "$(pwd)/claude-seo-check/skills/seo-check" ~/.claude/skills/seo-check

(or cp -R instead of ln -s if you prefer a detached copy). Requires Node ≥ 18 on your PATH for the crawler.

Usage

/seo-check                            audit whatever is uncommitted
/seo-check https://your-site.com      …and diff every route against production
/seo-check /pricing /blog/some-post   force specific routes into the audit
/seo-check --staged                   only staged changes
/seo-check --branch main              diff against merge-base with main
/seo-check --full                     also crawl homepage + key sitemap routes

It auto-detects your dev server on common ports (or starts and stops it itself), and understands Next.js (app + pages router), Astro, and plain HTML sites out of the box.

Using the crawler standalone

crawl.mjs is useful on its own, no Claude required:

node skills/seo-check/scripts/crawl.mjs --base http://localhost:3000 / /about /blog/my-post
node skills/seo-check/scripts/crawl.mjs --base http://localhost:3000 --compare https://prod.com /
node skills/seo-check/scripts/crawl.mjs https://example.com/page --json
Flag Meaning
--base <origin> origin that bare route paths resolve against
--compare <origin> fetch each route on a second origin and diff all SEO signals
--ua <name> googlebot-mobile (default), googlebot-desktop, chrome, or a custom string
--timeout <ms> per-request timeout (default 20000)
--no-robots skip robots.txt + sitemap checks
--json machine-readable output

Exit codes: 0 clean, 1 error-severity findings, 2 fetch failures — usable straight from a git pre-commit hook or CI.

Design notes & limitations

  • The crawler reads the initial HTML only — no JavaScript execution. That's deliberate: the initial response is what indexing depends on most, and it's what every non-Google crawler (Bing, AI crawlers) sees. A content page whose initial HTML is an empty shell gets flagged (THIN_INITIAL_HTML) — that's a real finding, not a tooling gap.
  • HTML parsing is tolerant/regex-based, tuned for real-world markup rather than spec completeness.
  • Sitemap checks cap at 12 sitemap fetches / 5000 URLs per sitemap; large sites get sampled, not exhaustively verified.
  • The static audit is performed by Claude reading your diff with a checklist, so it benefits from context (frameworks, conditionals, env guards) that pure grep can't judge.

Testing

node test/run.mjs

Spins up two local fixture servers (good pages, broken pages, redirect chains, robots.txt blocks, a sitemap, and a changed "production" variant) and asserts all 31 checks, including compare-mode diffing and exit codes. CI runs this on Node 18/20/22.

FAQ

What is seo-check?
seo-check is an open-source SEO checker skill for Claude Code, installable as a plugin. Run /seo-check and it audits the files you've changed but not yet committed for SEO regressions, then crawls the affected routes with a Googlebot user agent and returns a commit verdict: safe, caution, or fix first.

How is it different from a normal SEO audit tool?
Most SEO tools audit a live site after the damage is done. seo-check runs on the diff, before the commit, so a stray noindex, a broadened Disallow:, a deleted route or a broken JSON-LD block is caught before it reaches production. With a production URL it also diffs every signal between local and live, so you see exactly what your change altered.

Which frameworks does it support?
Next.js (app and pages router), Astro and plain HTML sites out of the box — it maps changed files to URL routes for those. The crawler itself works on any URL, whatever the stack.

Does it send my code anywhere or need an API key?
No API key. The crawler is a zero-dependency Node script that only fetches your own URLs. The static pass runs inside your existing Claude Code session, so your diff goes only where your Claude Code conversations already go.

Can I use it without Claude Code?
Yes. crawl.mjs runs standalone and exits 0, 1 or 2, so it drops straight into a git pre-commit hook or a CI step.

Is it free?
MIT-licensed, free, no sign-up. Install it from the repository's marketplace in two lines, or star and fork it on GitHub.

Contributing

Issues and PRs welcome — see CONTRIBUTING.md. The likely places to extend:

  • skills/seo-check/references/checklist.md — the regression rules the audit reads
  • skills/seo-check/scripts/crawl.mjs — new signals or flags (add a fixture + assertion in test/)
  • skills/seo-check/SKILL.md — the audit workflow itself

License

MIT © Debmalya Biswas