@nuxtseo/cli runs public Site operations from a terminal, a script, or a coding agent. It sends every request through @nuxtseo/sdk. It never calls MCP or a private route.
Install
Install Node.js 22 or newer.
npm install --global @nuxtseo/cli
nuxtseo --versionYou can also run one command without a global install:
npx @nuxtseo/cli sites listFirst Site read
Set a Team API token through your shell or your CI secret store. Then list the Sites the token can reach:
export NUXTSEO_TOKEN='your-team-api-token'
nuxtseo sites listSelect a default Site and inspect a Page:
nuxtseo sites use site_123
nuxtseo page inspect https://example.com/aboutFor an automated read, keep the Site explicit and request JSON:
nuxtseo page inspect https://example.com/about \
--site site_123 \
--jsonSign in
Run nuxtseo login. It prints a pairing code, opens your browser on the approval page, and waits. Check that the code in the browser matches the code in your terminal. Choose a role, then approve. The CLI receives a Team API token and stores it.
nuxtseo login # pair through the browser
nuxtseo login --no-browser # print the URL instead of opening it
nuxtseo login --with-token # paste an existing token insteadThe token is an ordinary Team API token labelled CLI on <hostname>. It appears under Settings > API tokens and is revoked there like any other.
A pairing request stays open for ten minutes. Denying it creates nothing.
Token resolution order is:
NUXTSEO_TOKEN- The stored credential
Outside an interactive terminal, login reads a token from stdin instead of pairing, so CI keeps working. Tokens are never accepted as positional arguments or options.
The CLI validates the token with GET /api/v1/account/token, which reports the Team, the role, the granted scopes, and the expiry without reading a Site. nuxtseo whoami reads the same operation. It then stores the token in the OS keychain through the optional @napi-rs/keyring package. If keychain support is unavailable, the CLI warns on stderr and writes ~/.nuxtseo/auth.json with mode 0600.
nuxtseo logout removes the local credential. To stop a token working everywhere, revoke it in the dashboard. An environment token always wins, and login and logout never change it.
API host resolution order is:
--api-urlNUXTSEO_API_URL- The host stored by
nuxtseo config https://nuxtseo.com
Site selection
Site scoped commands resolve a Site in this order:
--site <site-id>NUXTSEO_SITE_ID- The Site saved by
nuxtseo sites use <site-id> - The only accessible Site
- A selection prompt when several Sites are available in a TTY
Scripts and agents should pass --site. Several Sites outside a TTY produce exit 5. The CLI never guesses.
An explicit argument, environment value, or stored Site ID goes straight to the requested operation. It adds no sites.list request and needs no sites:read scope.
JSON output
For a public API success, --json writes the complete protocol response envelope to stdout, followed by one newline. The CLI does not unwrap data, rename fields, rank results, or add local fields. Warnings and diagnostics go to stderr.
The OpenAPI 3.1 document holds the exact paths, request schemas, responses, scopes, and errors. Read it to predict an envelope before you call for it.
The SDK validates and parses the HTTP body before the CLI serializes it. The JSON value and the protocol structure are preserved. Whitespace and object key order from the wire are not a byte level guarantee.
If the server returns a valid protocol error body, --json writes that body to stdout and writes the readable recovery message to stderr.
Local outcomes have no server protocol body. With --json, commands such as bare nuxtseo, config, logout, and sites use emit a tagged CLI-owned JSON value with schemaVersion: 1. Local failures emit CliError with a stable code and exit code. These tags are separate from protocol envelopes.
--help --json returns the selected command, global options, arguments, and subcommands as CliHelp with schemaVersion: 2. Option names are strict. An unknown option exits 2 before authentication or network work.
Automation controls
The CLI never prompts outside a TTY. CI=1 or --no-input suppresses interactive mode inside a terminal session. --json also implies --no-input.
Mutations need confirmation. Pass --yes or -y in automation:
nuxtseo page scan https://example.com/about --site site_123 --yes --json| Option | Behaviour |
|---|---|
--no-input | Disable every prompt even when stdin and stdout are TTYs |
--timeout-ms <milliseconds> | Apply one deadline to Site resolution, SDK retries, and the operation. Default 30000, maximum 300000 |
A request timeout returns CliError code request_timeout and exits 6. The error prints an exact retry command with a longer deadline. SIGINT and SIGTERM abort the active request and return exit 130.
Commands
nuxtseo login
nuxtseo logout
nuxtseo whoami
nuxtseo config
nuxtseo sites list
nuxtseo sites use <site-id>
nuxtseo usage
nuxtseo status
nuxtseo pull --json
nuxtseo actions list
nuxtseo actions show <action-id>
nuxtseo actions resolve <action-id>
nuxtseo actions dismiss <action-id>
nuxtseo backlinks recoverable
nuxtseo mentions list
nuxtseo page inspect <url>
nuxtseo page scan <url>
nuxtseo page issues
nuxtseo performance
nuxtseo vitals summary
nuxtseo vitals trend
nuxtseo vitals findings
nuxtseo scans list
nuxtseo scans show <scan-id>
nuxtseo scans pages
nuxtseo annotations list
nuxtseo annotations create
nuxtseo annotations update <annotation-id>
nuxtseo annotations delete <annotation-id>
nuxtseo analytics <view>
nuxtseo search status
nuxtseo search cohorts
nuxtseo search analytics <view>
nuxtseo search indexing <summary|urls>
nuxtseo search index-history
nuxtseo search inspect <url>
nuxtseo sitemaps list
nuxtseo sitemaps urls
nuxtseo sitemaps submit <sitemap-url>
nuxtseo sitemaps delete <sitemap-url>
nuxtseo research overview
nuxtseo research keywords <topic>
nuxtseo research serp <keyword>
nuxtseo research rankings <domain>
nuxtseo audit changes
nuxtseo audit link-opportunities
nuxtseo audit link-structure
nuxtseo audit content-decay
nuxtseo audit duplicates
nuxtseo skill installUse nuxtseo <command> --help --json for required inputs and the complete command list. This overview does not replace command help.
status reads the stored Site check. Read its availability, data quality, and assessment.scope before reporting a verdict. pull --json writes one envelope per stored-evidence read. It does not follow pagination. Inspect each line's command and error.
performance and scans read Lighthouse lab data. vitals summary and vitals trend read CrUX field data. vitals findings needs a connected Web Analytics provider. Keep these sources separate.
page issues reads raw observations selected by an action or a source and issue. actions dismiss requires the artifact version and optional decision note. Dismissal preserves observations and does not verify a fix. Annotation writes mark changes on the Site timeline.
search indexing summary reports retained URL Inspection evidence. Quote its capture time; it is not a live count of Google's index.
search analytics takes pages, keywords, countries, devices, timeseries, page-detail, keyword-detail, or analysis. page-detail needs --page-url, keyword-detail needs --keyword, and analysis needs --preset. The brand-only and non-brand presets also need --brand-terms. The CLI refuses a missing argument before it sends a request.
analytics takes performance, top-pages, source-medium, key-events, countries, devices, or dimension. The dimension view needs --dimension.
search inspect reads Google's own verdict for one URL. page inspect reads the Nuxt SEO observation store for the same URL.
Run bare nuxtseo in a terminal for a task based menu. It groups Site fixes, performance, research, content, and account setup. The menu prints the direct command it runs.
search status reads stored connection state. It never waits for Google.
research keywords, research serp, and research rankings can use the Team research allowance. Keyword responses report cache use in evidence. SERP and ranking responses report cached: true. A cached response uses no unit.
After a change
Confirm the live HTML first. Google must crawl the changed page before processing its updated content and directives. Search Console can still show the earlier crawl or canonical choice.
An October 2026 report describes internal timings Gary Illyes presented at Search Central Live Deep Dive. The reported typical canonical change took 1 to 3 weeks. Conflicting signals could extend that to months. These observations do not predict when your page will change.
A sitemap submission does not prove Google crawled or indexed its URLs. An indexing request does not guarantee inclusion. A displayed title or snippet can change separately from rankings.
Read Google processing timelines and limits for Gary's caveat and what to check after a change.
Paging
The CLI fetches one page per invocation by default. It never merges responses.
| Command | Paging inputs | Default | --all |
|---|---|---|---|
actions list | --limit 1..25, --offset >=0 | --limit 10 --offset 0 | yes |
actions show | --group-id, --cursor, --limit 1..100 | --limit 50 | no |
page inspect, page issues | --limit 1..200, --offset >=0 | --limit 100 --offset 0 | yes |
vitals findings | --limit 1..50, --offset >=0 | --limit 20 --offset 0 | yes |
scans list | --limit 1..100 | --limit 25 | no |
backlinks recoverable | --limit 1..200, --offset >=0 | --limit 100 --offset 0 | yes |
mentions list | --limit 1..200 | --limit 100 | no |
search analytics | --limit 1..100, --page >=1 | --limit 25 --page 1 | row views only |
search indexing | --limit 1..500, --offset >=0 | --limit 50 --offset 0 | urls view only |
sitemaps urls | --cursor, --limit 1..1000 | --limit 500 | yes |
Keep the server order for actions. To read the next page, pass the returned offset or cursor. Use the cursor unchanged.
--all repeats the same operation until the server reports no more pages. It writes one complete envelope per page, newline delimited. The CLI never merges, unwraps, or re-ranks a page. The loop stops after 50 requests. If pages remain, the CLI exits 9 and stderr names the argument that resumes the read.
Coding agents
The package ships an agent skill that teaches a coding agent how to drive the CLI. Install it with the CLI itself; a global install has no local node_modules to copy from.
nuxtseo skill install # ~/.claude/skills/nuxtseo-cli
nuxtseo skill install --agent codex # ~/.codex/skills/nuxtseo-cli
nuxtseo skill install --target ./.claude/skillsThe command reports the destination it wrote.
The skill covers the JSON contract, Site selection, paging, mutation consent, and what to do for each exit code.
The Nuxt SEO module ships its own skill: view it on skilld.
Exit codes and recovery
| Code | Meaning | Typical recovery |
|---|---|---|
0 | Success, including a closed stdout pipe | Continue |
2 | Invalid input, or a mutation with no confirmation | Fix the arguments. Use --yes for a deliberate mutation |
3 | Missing, invalid, or expired authentication | Replace NUXTSEO_TOKEN, or run nuxtseo login |
4 | Forbidden, scope, or entitlement failure | Use a token with the required access, or change plan |
5 | Conflict, stale evidence, or an ambiguous Site | Refresh the read. Pass --site when selection is ambiguous |
6 | Rate, quota, provider, or request timeout | Read the retry metadata on stderr, then retry later |
7 | Local state, network, contract, or infrastructure failure | Fix the named path or network issue. Keep the request ID |
8 | Resource or accessible Site not found | Run sites list, then sites use, or pass --site |
9 | --all reached its 50 request cap | Resume with the argument stderr names |
130 | Interrupted or cancelled | Confirm no mutation landed before you retry |
The CLI prints the exact server error code. Where the server supplies them, stderr also carries the request ID, the retry delay, the rate limit, the reset time, and structured details.
The CLI never falls back to MCP, a private route, or cached feature data.