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.
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:
- Static audit — scopes
git diffto 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 anoindexbehind a staging-env conditional isn't a false alarm. - Live crawl —
crawl.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
@typeinventory - images missing
alt(emptyalt=""counted separately as decorative) - internal/external/nofollow link counts, sitemap membership
- full redirect chains, final status,
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 readsskills/seo-check/scripts/crawl.mjs— new signals or flags (add a fixture + assertion intest/)skills/seo-check/SKILL.md— the audit workflow itself
License
MIT © Debmalya Biswas
No comments yet
Be the first to share your take.