@nuxtseo/cli
v0.5.10
Published
Command line interface for the Nuxt SEO public API.
Readme
nuxtseo CLI
Use Nuxt SEO public Site operations from a terminal, script, or coding agent.
The CLI sends feature requests through @nuxtseo/sdk. It does not call MCP or
private routes. Live research uses declared public API operations.
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 CI secret store, then list the Sites the token can access:
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 \
--jsonAuthentication
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, and approve. The CLI then receives a Team API
token and stores it.
The token is an ordinary Team API token labelled CLI on <hostname>. It appears
under Settings > API tokens and is revoked there like any other.
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 insteadA 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. It
then stores the token in the OS keychain through optional @napi-rs/keyring.
When keychain support is unavailable, it warns on stderr and uses
~/.nuxtseo/auth.json with mode 0600.
nuxtseo whoami reads the same operation, so an agent learns about a missing
scope before the request that needs it.
nuxtseo logout removes the local credential. Revoke the token from the
Nuxt SEO dashboard when it must stop working everywhere. An environment token
always wins and is unchanged by login or logout.
API host resolution order is:
--api-urlNUXTSEO_API_URL- The host stored by
nuxtseo config https://nuxtseo.com
Site selection
Site scoped commands currently 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. Multiple Sites outside a TTY produce
exit 5; the CLI never guesses.
An explicit argument, environment value, or stored Site ID goes directly to the
requested operation. It does not add a sites.list request or require
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 use
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 protocol structure are preserved. Whitespace and object key order from the wire are not a byte level guarantee.
When 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. CliHelp uses schemaVersion: 2. Local failures
emit CliError with a stable code and exit code. These tags are separate from
protocol envelopes.
--help --json returns the selected command, inherited globalOptions,
positional arguments, command-specific localOptions, and subcommands as
CliHelp. 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 in a terminal session. --json also implies --no-input.
Mutations require confirmation. Pass --yes or -y in automation:
nuxtseo page scan https://example.com/about --site site_123 --yes --jsonAgent controls:
| Option | Behavior |
| --- | --- |
| --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 |
Request timeouts return CliError code request_timeout and exit 6. The
error prints an exact retry command with a longer deadline.
SIGINT and SIGTERM abort the active request and return exit 130.
Commands and paging
nuxtseo login
nuxtseo logout
nuxtseo whoami
nuxtseo config
nuxtseo sites list
nuxtseo sites use <site-id>
nuxtseo usage
nuxtseo status
nuxtseo actions list
nuxtseo actions show <action-id>
nuxtseo actions resolve <action-id>
nuxtseo actions dismiss <action-id>
nuxtseo backlinks summary
nuxtseo backlinks referring-domains
nuxtseo backlinks anchors
nuxtseo backlinks history
nuxtseo backlinks recoverable
nuxtseo mentions list
nuxtseo page inspect <url>
nuxtseo page issues
nuxtseo page scan <url>
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 analytics <view>
nuxtseo search indexing <summary|urls>
nuxtseo search cohorts
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 competitors list
nuxtseo research competitors add <domain> --yes
nuxtseo research competitors remove <competitor-id> --yes
nuxtseo research domain-traffic <domain>
nuxtseo research domain-availability <domains>
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 timeline list
nuxtseo skill installsearch 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.
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.
performance reads the stored Lighthouse lab overview. Real-user field data is
a different dataset: vitals summary and vitals trend read CrUX field p75,
and vitals findings names the DOM element behind each failing vital.
status reads the Site assessment: the verdict, the one ranked Next Action, and
what changed. Start there. status, page issues and search cohorts refuse
with exit 4 or 5 on a paused Site. Removed Sites return not_found with exit 8.
The four live backlinks reads need the Site to have a URL. Without one they
exit 2, and retrying will not help; set the Site URL first.
status reports assessment.scope: site when the headline covers the whole
Site, route-family when one family leads. assessment.aggregate always holds
the whole-Site verdict.
search cohorts returns analysed: false with reason: sampled-index-state
when the not-indexed list is a sample. Otherwise it returns two lists. Only established is proven; ranked is
ordered by raw rate with no significance test and is leads only.
backlinks summary, backlinks referring-domains, backlinks anchors,
backlinks history, research domain-traffic and research domain-availability
can use the Team research limit. Each response reports
cache use in evidence; a cached response spends nothing. backlinks recoverable
reads retained rows and spends nothing.
search status reads stored connection state. It never waits for Google.
search indexing summary reads retained URL Inspection coverage. asOf and oldestCheckAt bound the age of its verdicts.
search index-history dates an indexing change against known releases.
search inspect <url> reads the latest retained Google URL Inspection for one URL.
search inspect <url> --fresh --yes requests Google URL Inspection through the Site connection and uses inspection quota.
Fresh inspection reports errors and skipped URLs with a nonzero exit code. If the request needs more time, add --timeout-ms 60000.
page inspect <url> reads the Nuxt SEO observation store for the same URL.
research keywords, research serp, and research rankings can use the Team
research limit. Keyword responses report cache use in evidence. SERP and
ranking responses report cached: true. A cached response spends nothing.
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 | --limit 1..200, --offset >=0 | --limit 100 --offset 0 | yes |
| backlinks recoverable | --limit 1..200, --offset >=0 | --limit 100 --offset 0 | yes |
| backlinks referring-domains | --limit 1..1000 | --limit 100 | no |
| backlinks anchors | --limit 1..1000 | --limit 100 | no |
| vitals findings | --limit 1..50, --offset >=0 | --limit 20 --offset 0 | yes |
| page issues | --limit 1..200, --offset >=0 | --limit 100 --offset 0 | yes |
| scans list | --limit 1..100 | --limit 25 | no |
| search cohorts | --limit 1..50, --min-pages 1..500 | --limit 12 --min-pages 5 | no |
| 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 |
| timeline list | --kind, --feature, --severity, --since, --cursor, --limit 1..100 | --limit 25 | no |
Keep the server order for actions. For another page, pass the next offset or cursor reported by the response. A cursor is opaque; do not edit or infer it.
--all
--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. Read the stream one JSON value per line.
The loop stops after 50 requests. If pages remain at that point, the CLI exits
9 and stderr names the exact argument that resumes the read, for example
--offset 50. Exit 9 is a stop, never an end of data.
--all covers the Search Console views the server pages: pages, keywords,
countries, devices, and analysis, plus the urls indexing view. Every
other view returns one payload, so the CLI refuses --all there with exit 2.
Coding agents
The package ships an agent skill that teaches coding agents 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. With --json it emits
CliSkillInstall carrying the source and the destination.
The skill covers the JSON contract, Site selection, paging, mutation consent, and what to do for each exit code.
Exit codes and recovery
| Code | Meaning | Typical recovery |
| ---: | --- | --- |
| 0 | Success, including a closed stdout pipe | Continue |
| 2 | Invalid input or missing mutation confirmation | Fix 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 ambiguous Site | Refresh the read; pass --site when selection is ambiguous |
| 6 | Rate, quota, provider, or request timeout | Read retry metadata on stderr and 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 result before retrying |
The CLI prints the exact server error code. When available, stderr also includes the request ID, retry delay, rate limit, reset time, and structured details. The CLI never falls back to MCP, a private route, or cached feature data.
Claim response
actions resolve saves your Claim. It returns before a requested scan finishes starting.
status: "open" stays unchanged until the engine verifies the Action.
Human output shows Claimed, verifying and the suggested check-back time.
Claimed Actions leave actions list. Use actions show <action-id> to check them.
Both resolve and show return these additive fields:
| Field | Meaning |
| --- | --- |
| markedAt | ISO timestamp when your Claim was saved, or null before a Claim. |
| checkBackAt | Suggested ISO timestamp to check again, or null when no automated check applies. |
A check-back time does not promise a completed check.
scan-queued can mean a re-assessment using scheduled crawl results, without a new scan.
A self-resolved Claim returns status: "verified" and verification: "user-resolved".
