The only SEO skill your agent needs. Audit sites, find search opportunities, research competitors, and verify the work from one local CLI and MCP server.
Get started · Documentation · npm · Questions · Privacy · Security · License · Agent notes
The seo command turns crawl, Search Console, Google Analytics, and optional
research-provider data into work you can inspect and ship. Find technical
blockers, recover existing demand, research new keywords and competitors,
review programmatic page patterns, and catch regressions after a release.
- People running their own sites who want a clear audit and a ranked list of fixes, without learning a heavy dashboard.
- AI agents that need real crawl, Search Console, Google Analytics, keyword, result, domain, competitor, and link evidence through MCP and one packaged SEO skill instead of screenshots or guesses.
- Developers who want to embed the same report engine in a script, a CI job, or a TypeScript app.
Requires Node 22 or newer.
npm i -g seo
seo start
seo reportThe setup walks you through Google sign-in, your Search Console property, an optional Google Analytics property, and a local project profile. Public releases can include the shared Google app. If it is unavailable in your build, setup guides you through adding your own desktop OAuth client.
Research providers are optional and connected separately. Start with the main report, then add DataForSEO, Semrush, or Ahrefs only when external keyword, result, domain, competitor, or link estimates would change the decision.
That is the normal path. The seo command is then available in every terminal,
script, CI job, and local MCP client on the machine.
The main report uses the evidence you have, explains what it could not check, and recommends a short list of follow-up commands. You can start with a local technical report before connecting Google.
Running seo help shows the shape of the tool:
Run SEO audits, find what needs fixing, and ship the changes with your agent.
Start here
seo start Connect Google and save a project profile
seo report Run the main SEO report for the default project
seo report --site sc-domain:example.com Run without a profile
seo report --url https://example.com Start with a local technical report
Projects
seo projects list List saved project profiles
seo projects add Create or update a project profile
seo sites List Search Console properties
seo doctor Check local auth and config
Act on a report
seo refresh-priorities Rank the next best SEO actions
seo quick-wins Find ranking 4-10 low-CTR wins
seo second-page Investigate URLs averaging positions 10-20
seo technical-watch Crawl and index-monitor a site
Agent and power tools
seo report --json Run the main report as structured JSON
seo export diagnose Export report data to CSV
seo mcp install Install SEO tools into MCP clients
seo skill list Show the packaged SEO skill
seo reports list Discover every structured report
Use `seo help <command>` or `seo <command> --help` for command help.
Use `seo help all` for the longer command list.- Find technical blockers across metadata, links, indexability, canonicals, structured data, performance, security, mobile, international SEO, and social previews.
- Rank the work using affected URLs, rule severity, search visibility, and analytics value instead of treating every warning equally.
- See why a finding matters, what evidence supports it, how to fix it, and how to verify the change.
- Save and compare crawl reports without running the same crawl again.
- Measure SEO changes with matched before and after Search Console windows.
- Discover keyword ideas, compare market estimates, inspect current results, and keep useful terms in local saved sets.
- Find recurring search competitors, inspect their ranking pages, and filter possible keyword gaps through first-party evidence and existing provider ranks.
- Detect repeated first-party and competitor page patterns, then return bounded data-source research briefs before proposing a new programmatic template.
- Find location-specific Search Console demand and repeated local page patterns, then add a few exact local result snapshots when the decision needs them.
- Give scripts and agents deterministic JSON, Markdown, stable rule IDs, and a compact local MCP surface.
The point of a report is to be defensible, so the design keeps a few rules:
- Observed evidence stays separate from derived findings and recommended actions. You can always see the crawl row or provider row behind a claim.
- Partial data is never reported as a zero. A capped, filtered, or sampled source says so, and it cannot support a definitive all-clear.
- Heuristics are labeled as heuristics. A convention or threshold is not presented as a search-engine rule.
- Each recommendation comes with a way to check that the fix worked, rather than a promise about rankings or traffic.
seo start can save a project profile, which is a local shortcut for a site,
Search Console property, Google Analytics property, and brand terms. If you have one default
project, most commands need no flags.
seo report
seo refresh-priorities
seo quick-wins
seo second-page
seo technical-watchUse --project when you have more than one:
seo report --project example
seo projects listYou can also work without a saved profile:
seo report --site sc-domain:example.com
seo report --url https://example.com
seo crawl https://example.com
seo audit-page --url https://example.com/pricingseo report --url crawls the site and saves technical evidence. It does not
pretend to know traffic, queries, or rankings until you add a Search Console
property with seo start.
Run seo help for the short path or seo help all for the full command list.
Connect a research provider when you need independent market estimates or competitor evidence. Each connection is local and separate from Google sign-in. DataForSEO has the broadest live coverage:
seo providers dataforseo connect
seo providers dataforseo status --check
seo providers dataforseo limitsCredentials use the system keychain when available, with a private local file fallback. Semrush Version 3 and Ahrefs API v3 use the same local credential boundary:
seo providers semrush connect
seo providers semrush status --check
seo providers ahrefs connect
seo providers ahrefs status --check
seo providers ahrefs limitsRead the Semrush guide and Ahrefs guide before running paid research. Supported reports record the applicable API units or USD cost, cache state, request bounds, and retained row coverage. Cached results avoid repeating paid work during their retention window.
Use the existing report catalog. There are no separate provider-named report commands:
seo reports describe keyword-research --json
seo reports describe competitive-opportunities --json
seo reports describe domain-overview --json
seo reports describe competitor-keyword-gap --json
seo reports describe local-search-demand --json
seo reports describe ai-mention-research --json
seo reports describe ai-prompt-observations --json
seo reports run domain-overview \
--params '{"domain":"example.com","countryCode":"GB","languageCode":"en"}' \
--jsonRanked-keyword exports work without provider API access. Pass one to four local DataForSEO, Semrush or Ahrefs files through the same report pipeline:
seo reports run competitor-keyword-gap \
--params-file ./competitor-gap-run.json \
--jsonThe parameter file uses researchFiles. Each item records
dataset: "ranked-keywords", the local file, its provider, and the real
exportedAt date. CSV, TSV, JSON, JSONL and NDJSON are supported. UTF-8 and
UTF-16 CSV files are detected automatically, including Ahrefs downloads that
use tabs despite a .csv name. The output keeps the detected encoding and
delimiter, a SHA-256 hash, included fields, explicit column mapping, row counts,
filtered historical rows, invalid rows, duplicates and caps under
evidence.imports. Add columns when an export uses unfamiliar headings.
Each entry maps a canonical field such as keyword, url, position or
searchVolume to the source heading. Imported files can feed ranked-keywords,
ranking-pages, serp-competitors and competitor-keyword-gap without
adding another command or MCP tool. The research provider guide
has the exact JSON shape, market guidance and file limits.
The research flow now covers:
competitive-opportunitiesfor turning a small topic set into a bounded keyword and competitor investigation order using current results, free Domain Rating observations, and optional paid link summaries;keyword-research,keyword-metrics, andsaved-keywordsfor discovery, estimates, and local persistence;serp-resultsandrank-trackingfor current or repeated exact market and device-specific observations;domain-overview,ranked-keywords, andranking-pagesfor country-level domain, term, page, and repeated path evidence;serp-competitorsfor finding domains that recur across an explicit keyword set without guessing whether they are a business, publisher, directory, community, or marketplace;competitor-keyword-gapfor comparing up to three relevant domains with retained Search Console themes, the site's provider-observed rankings, and programmatic page patterns;local-search-demandfor matching explicit place names, nearby phrases, and postal codes in retained Search Console rows, reviewing repeated local page patterns, optionally joining Analytics geography by exact landing-page path, and optionally adding up to three exact local result snapshots with bounded competitor and local-pack listing summaries;link-evidencefor a current link summary, one representative backlink per referring domain, and linked-target checks against saved crawl and Search Console evidence;domain-ratingfor one free, attributed Ahrefs observation of backlink profile strength, kept separate from ranking and traffic evidence;ai-mention-researchfor provider-indexed mentions, cited domains, and bounded question samples in one exact AI surface and market, with optional Search Console overlap for a property you own;ai-prompt-observationsfor a small fixed set of prompts across explicit current ChatGPT, Claude, Gemini, or Perplexity models, with answers, citations, compatible history, exact returned costs, and optional Search Console context stored locally.
Provider traffic, volume, difficulty, intent, visibility, and ranking history are estimates. Search Console remains the evidence for measured search performance on a property you own. A live result snapshot remains the evidence for one query, market, device, and observation time. Reports can combine these sources without blending their meanings or turning a missing row into zero. Local query wording does not establish the searcher's physical location, and an observed local pack does not establish that a particular listing appeared. Provider-indexed AI mentions are not live prompt observations. Each live answer is one sample under its exact prompt, requested and effective model, market label, settings, and collection time. Neither source proves referral traffic or technical eligibility. A missing target in one answer does not prove universal absence. The requested model is the model you chose; the effective model is the model the provider reports actually running.
Read the research provider guide for setup, costs, caching, country-level limits, competitor classification, and programmatic data-source checks.
Google Analytics commands sit under their provider namespace. List the properties available to the connected account, then run a report with the property you need:
seo analytics google properties
seo analytics google report --property 123456789 --dimensions landingPage --metrics sessions,totalUsersBing Webmaster is optional. Connect it when you want Bing traffic trends, crawl changes, and query and page opportunities beside your Google evidence:
seo providers bing connect
seo providers bing report --project exampleThe guided connection asks for the API key from Bing Webmaster Tools Settings,
then API Access. It validates the key, lists verified sites, matches one to the
selected project when the hostname is unambiguous, and stores the key in the
system keychain with a private local file fallback. Agents and CI can set
SEO_BING_API_KEY and run the report without saving the key.
The report compares recent traffic periods, highlights material crawl changes,
and returns bounded query and page review lists. Provider responses stay
uncached and byte limited. Invalid, partial, capped, unavailable, and sampled
evidence remain distinct. Bing's inIndex crawl statistic is provider
evidence, not URL-level proof that a page is indexed. A query or page missing
from a weekly top list is unknown, not zero.
Review a bounded set of referring links from Ahrefs, DataForSEO, Bing or a local export:
seo links --provider ahrefs --target example.com --json
seo links --provider dataforseo --target example.com --json
seo links --provider dataforseo --target example.com \
--search-site sc-domain:example.com --json
seo links --project example --json
seo links --file ./links.csv --row-limit 10000 --jsonThe Ahrefs and DataForSEO paths request one summary and a bounded set of live representative backlinks, one per referring domain by default. Ahrefs keeps estimated and actual API units in the evidence. DataForSEO keeps current endpoint prices, estimated and actual USD cost, and task ids. Both retain cache state, provider filters, row coverage, and omitted rows. A cached repeat does not repeat paid work during the retention window.
When a matching saved crawl or Search Console property is available, the same report checks linked target pages for observed error responses, redirects, canonical conflicts and non-indexable states. Search Console metrics add first-party context without turning a missing retained page row into zero. Verify the live target and the referring page before changing anything.
CSV and JSONL imports stream from disk. Regular JSON arrays have a smaller file limit to avoid a memory spike. Every result includes the number of rows read, rejected, deduplicated, omitted, or stopped by a limit. It is evidence from the selected source, not a complete backlink index. Provider rank and spam metrics keep their provider-specific names and scales. They are context, not search-engine ranking factors or universal authority scores.
The built-in renderer creates a standalone report when you need a predictable file without asking an agent to design it:
seo report --project example --format html
seo monthly-report --project example --format html
seo report-narrative --project example --format html --view analystClient view keeps the presentation concise. Analyst view adds evidence coverage
and unavailable sections. Use --output ./report.html to choose the file path.
The file contains its own CSS, works offline, prints cleanly, and is marked
noindex,nofollow.
An agent can instead design its own report from the structured result:
seo report --project example --full --json > seo-report.jsonAsk the agent to turn that evidence into one responsive, print-friendly HTML file for the intended audience. It can choose the layout and visual style, but it must keep provider labels, reporting dates, data status, limitations, and verification steps visible. Missing or partial data must not become zero, and the presentation must not invent forecasts, causes, scores, or conclusions. The installed skill teaches agents this contract automatically.
Stream a local NGINX or Apache-style combined access log without importing or retaining every raw request:
seo server-logs analyze --file ./access.log --json
seo server-logs analyze --file ./access.jsonl --format jsonl --jsonThe report groups observed search and AI crawler user agents by response class and path. Input bytes, rows, line size, unique paths, and returned detail are bounded, and any capped or malformed evidence stays visible. User-agent names can be spoofed, so the result describes observed request strings rather than verified crawler identity.
Generate a key file in the public asset directory for your site, then deploy it before sending notifications:
seo indexnow setup --site https://example.com --output ./public
seo indexnow verify --site https://example.com
seo indexnow submit --site https://example.com --url https://example.com/changed-pageUse --dry-run --json to validate a submission without notifying IndexNow.
The command accepts one URL, a comma-separated list, or a newline-delimited
file. A run is limited to 1,000 unique URLs, every URL must use the configured
host, and the public key file is checked before a live request. The local key
mapping stays in the system keychain with a private file fallback. Agents and
CI can set SEO_INDEXNOW_KEY for the current process instead.
An accepted IndexNow request confirms receipt only. It does not prove that a URL was crawled, indexed, ranked, or shown in search results.
For a large or unfamiliar site, start with the sitemap health pass:
seo crawl --sitemap-url https://example.com/sitemap.xml --health --format prettyThis reads the sitemap, then checks each listed URL for status, redirects, robots decisions, network failures, and access blocks. It does not parse or render page bodies, join Google data, check external links, or write page and robots responses to the local cache. Requests begin one at a time and increase only after clean responses.
Run the full crawl second when the health evidence points to a problem, or when you need metadata, canonicals, indexability, links, structured data, or page content:
seo crawl https://example.com --format prettySave it, export it, or compare it with an earlier crawl:
seo crawl https://example.com --save
seo crawl https://example.com --format html --output report.html
seo crawl-reports
seo crawl-reports --compare latest --against previousUseful crawl controls include --max-pages, --max-depth, --include,
--exclude, --no-sitemap, --no-external, and --fail-on for CI. Every
request uses the stable versioned identity
SEO-Skill/<version> (+https://seoskill.dev).
If a site denies or challenges that identity, the report keeps the HTTP status, provider indicators, request ID when available, and practical access guidance. Do not allow requests based on User-Agent alone because it can be spoofed. Scope any temporary exception to the audit machine source IP, required host or paths, and the exact blocking rule.
JSON mode never prompts. Pass the site or project explicitly in unattended runs.
seo report --project example --json
seo crawl --sitemap-url https://example.com/sitemap.xml --health --format junit --output sitemap-health.xml --fail-on high
seo crawl https://example.com --json --output crawl.jsonReports keep observed data, derived findings, skipped sections, limits, and provider errors separate so automation can make decisions without parsing terminal prose.
seo report --json returns a compact summary, action queue, and bounded crawl
evidence so an agent can choose its next call without loading every raw report.
Use --full only when a script needs the complete report object.
When a CI job needs Search Console or Google Analytics data, give it a Google service account JSON key through its secret store. The service account needs access to the exact properties it will query. This GitHub Actions step runs without a browser or a copied local token:
- name: Run the SEO report
run: |
npm i -g seo
seo report --site sc-domain:example.com --json > seo-report.json
env:
SEO_GOOGLE_SERVICE_ACCOUNT_JSON: ${{ secrets.SEO_GOOGLE_SERVICE_ACCOUNT_JSON }}The Google data guide covers Search Console and Google Analytics permissions, mounted secret files, and how to check the active identity safely.
Agents can discover and run the same report catalog as MCP without starting a server:
seo reports list --category crawl --json
seo reports describe audit-page --json
seo reports run audit-page --params '{"url":"https://example.com"}' --jsonAlways describe a report before constructing its parameters. The CLI and MCP surfaces read from the same registry, so their ids and JSON Schemas cannot drift.
Your agent carries one short SEO skill, and the CLI and MCP server do the heavy lifting. The skill teaches an agent how to discover the full audit and research catalog at runtime, and the agent asks the CLI for the detail on each tool only when it is about to run it. You get the whole toolkit without fifty skill files sitting in the context window on every session.
seo start offers to install the SEO skill during setup. If you skipped that
step or need to reinstall it later, run the packaged installer:
seo skill installIf you also skipped the MCP step, install the local server into a supported client:
seo mcp installThe prompt detects installed clients. Scripts can choose one or more explicitly:
seo mcp install --codex
seo mcp install --claude-code
seo mcp install --cursor
seo mcp install --claude-desktopYour client starts the server when it needs it. Run it directly only for manual configuration or testing:
seo mcp serveThe repository ships one skill under skills/seo. It is a router: it teaches an
agent to discover reports, describe one to load its depth at runtime, inspect
the evidence, and request a smaller follow-up instead of loading a giant result
into context. Per-report guidance lives in the registry and is fetched with
seo reports describe <id> --json, so it never drifts from the skill.
The npm package includes the same file for local inspection:
seo skill list
seo skill path seoAgents can also discover the canonical skill from
https://seoskill.dev/.well-known/agent-skills/index.json. The entry links to
the canonical skill instructions and includes a content digest for verification.
See MCP and agents for setup and tool details.
Install the same unscoped package in any Node 22 or newer project:
npm install seoRun any public report by id with the same definition, input schema, and evidence used by the CLI and MCP server:
import { describeReport, executeReport } from 'seo/mcp'
const description = describeReport('quick-wins')
const result = await executeReport('quick-wins', {
site: 'sc-domain:example.com',
days: 90,
})
console.log(description.inputSchema)
console.log(result)Or call typed analysis functions directly when your app already knows the job it needs to run:
import { auditPage, crawlSite } from 'seo'
const page = await auditPage({
url: 'https://example.com/pricing',
})
const health = await crawlSite({
url: 'https://example.com',
mode: 'sitemap',
strategy: 'health',
sitemapUrl: 'https://example.com/sitemap.xml',
})
const crawl = await crawlSite({
url: 'https://example.com',
maxPages: 100,
maxDepth: 4,
})
console.log(page.issues)
console.log(health.summary, health.access)
console.log(crawl.summary, crawl.issueGroups)The main seo export contains the report, provider, crawler, storage, and
rendering APIs. seo/mcp exposes report discovery, report execution, and the
embeddable MCP server. See the TypeScript library
guide for structured error handling,
local Google access, and more examples.
Google OAuth tokens use your system keychain when it is available. On a
headless machine or a locked keychain, the CLI falls back to a private
0600 file in your user config directory. Project profiles, crawl reports, and
provider caches are also local. Use these commands to inspect or remove them:
seo privacy
seo doctor
seo auth logout
seo resetseo auth status shows the active storage mode. Power users can choose it with
seo auth storage --keychain or seo auth storage --file.
Power users can bring their own Google OAuth client or use a service account in CI. The Google data guide covers both auth paths, including OAuth testing-mode limits.
Yes. Reports, project profiles, Google tokens, crawls, and caches stay in your local config directory. Local first does not mean offline. A command can request a site, connected Google or Bing account, research provider, Chrome UX Report, IndexNow, or the npm registry when the work needs it.
Optional external enrichment can send selected Search Console query or derived seed text to the chosen research provider only when you explicitly enable it. It does not send Google credentials, property IDs, Search Console metrics, or Google Analytics rows. Local provider file imports are not uploaded. Read the privacy policy for every network boundary and the telemetry page for the fixed anonymous usage-event schema and opt-out controls.
No. seo start uses a normal Google sign-in for read-only Search Console and
Google Analytics access. Public releases can include a shared desktop OAuth client, and if
your build does not have one, setup helps you add your own. You can also run a
local technical crawl with no Google connection at all.
The seo package is free and open source under Apache-2.0. It calls Google APIs
you already have access to, so the core crawl and Google workflows need no
separate subscription. Optional research providers can charge for API
requests. Their estimated and actual costs, local spend limits, cache state,
and request bounds stay visible in each supported report.
A hosted SEO tool keeps your data on its servers and shows you a dashboard. This runs on your machine, works from your own crawl and Google data, and returns structured evidence your agent can read and act on. Every finding shows the evidence behind it and a way to verify a fix, so you are not trusting a score you cannot inspect.
Questions, bug reports, and feature requests go through GitHub Issues. Report suspected vulnerabilities privately through the process in SECURITY.md.
- Getting started
- CLI commands
- Crawler
- Reports and data
- Research providers
- MCP and agents
- AI-search evidence
- Privacy policy
- Anonymous telemetry
- Public usage stats
- Terms of use
- Security policy
- Contributing
- Trademark and brand policy
Most users do not need the source checkout. If you want to contribute:
git clone https://github.com/iannuttall/seo.git
cd seo
pnpm install
pnpm build
node dist/cli.js start --dry-runRun the full quality gate before opening a pull request:
pnpm build
pnpm typecheck
pnpm test
pnpm lint
pnpm pack --dry-runContributor architecture and report-quality rules live in AGENTS.md.
The code is available under Apache-2.0. Project names and artwork are covered separately by the trademark and brand policy.