SEO Skill

SEO for developers

Check SEO the way you check types. Crawl the build before it ships, fail CI on real problems, and let your coding agent read your own Search Console data.

Run it in a terminal, then sign in with Google.

Or run it on your machine

Installs the CLI, signs you in and adds the skill to your agents. Site crawls and Bing data run this way, on your own machine. A crawl fetches many pages, and Bing blocks our hosted server.

Most SEO problems a developer causes are visible in the build: a template that lost its canonical, a moved page with no redirect, a staging noindex that reached production. SEO Skill gives you a crawler you can run on localhost, an MCP server for your coding agent, and a TypeScript library, all from the open source seo package. The commands above add the hosted MCP server or install the CLI. The crawl needs no sign-in, so for a one-off run, or in CI, use npx -y seo in place of seo and skip setup.

Crawl a local build before you deploy

Crawl the production build, not the dev server, so you see the HTML that will ship. Build with your local address as the site URL first, or every canonical and Markdown link will point at production and show up as an issue. Then start the build (astro preview, next start or wrangler dev) and crawl it:

seo crawl http://localhost:4321 --max-pages 2000

It follows links from the start page and your sitemap, and lists broken links, redirects, missing or duplicate titles and descriptions, canonical and robots tags, and structured data. It also checks what AI agents get: which AI crawlers your robots.txt allows, whether each page's Markdown copy loads, and whether llms.txt links work. The crawl stops at 500 pages unless you raise --max-pages, and says so when it does.

A noindex or a canonical pointing elsewhere is reported as what the page says. It is only a bug if you did not mean it.

Crawl staging and fail CI on real problems

--fail-on exits with an error when the crawl finds an issue at that severity or above, so a pipeline step can stop a deploy:

npx -y seo crawl https://staging.example.com --fail-on high

The crawler needs to reach staging without a sign-in. If staging sits behind Cloudflare Access or similar, crawl the local build in CI instead. For a large site, a sitemap health pass checks every listed URL's status and redirects without reading page bodies, and writes a JUnit file most CI systems can show as test results:

npx -y seo crawl --sitemap-url https://staging.example.com/sitemap.xml --health --format junit --output seo-health.xml

Add --json --output crawl.json to any crawl to keep the full result as a file, for a diff against the last run or for your agent to read.

Give your coding agent your search data

The crawl tells you what the site says. Search Console tells you what Google did with it. With the MCP server connected, your agent can answer questions like these from your own data while it works in the code:

AskWhat it reads
Did last Tuesday's release change search clicks?Clicks and positions before and after the date, with Google updates in the same window.
Is this page indexed, and which queries find it?Google's URL Inspection result and the page's queries.
Which pages lost their clicks this month?Pages that lost clicks, each checked live and with URL Inspection.
Which queries are we on page two for?The striking distance section of the Search Console report.

The hosted server needs nothing installed. To run the server on your machine instead, with the sign-in from seo start, add it to every MCP client it finds (Claude Code, Codex, Cursor and Claude Desktop):

seo mcp install --all

The crawl and internal links fetch many pages, so they run only in the CLI. When your agent asks the hosted server for a crawl, it is told to run seo crawl instead.

Run the same checks from TypeScript

The package is also a library, for a build script, a test or your own tool. Install it in your project:

npm i seo

Then crawl a site and check a single page. Save this as check.mjs and run node check.mjs:

import { auditPage, crawlSite } from 'seo'

const report = await crawlSite({ url: 'http://localhost:4321', maxPages: 500 })
console.log(report.status)
for (const group of report.issueGroups) {
  console.log(group.severity, group.title, group.count)
}

const page = await auditPage({ url: 'http://localhost:4321/about' })
console.log(page.issues.map((issue) => issue.title))

report.status is completed, partial or failed. A partial crawl stopped early, for example at the page limit, so a missing issue in it is not an all-clear. seo/mcp exports the MCP server, if you want to run it inside your own process.

Set up your framework

The crawler finds problems; the framework guides show how to avoid them in the first place. The Astro SEO guide covers a static site on Cloudflare with build checks that fail, and the Next.js SEO guide covers the Metadata API, sitemaps and real 404s in the App Router.