@nuxtseo/cli 0.2.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -8
- package/dist/ansi.d.ts +8 -0
- package/dist/ansi.js +35 -0
- package/dist/cli.js +17 -21
- package/dist/commands.d.ts +7 -0
- package/dist/commands.js +91 -116
- package/dist/failures.d.ts +46 -6
- package/dist/failures.js +101 -10
- package/dist/pairing.js +2 -4
- package/dist/pull.d.ts +81 -0
- package/dist/pull.js +358 -0
- package/dist/render.d.ts +5 -9
- package/dist/render.js +1 -22
- package/dist/runtime.d.ts +5 -0
- package/dist/runtime.js +7 -2
- package/dist/skill.d.ts +99 -0
- package/dist/skill.js +372 -15
- package/dist/state/auth.js +2 -2
- package/dist/state/files.js +6 -6
- package/dist/update-check.d.ts +5 -0
- package/dist/update-check.js +18 -1
- package/package.json +4 -4
- package/skills/nuxtseo-cli/SKILL.md +187 -254
- package/skills/nuxtseo-cli/references/commands.md +111 -18
- package/skills/nuxtseo-cli/references/indexing.md +3 -2
- package/skills/nuxtseo-cli/references/protocol.md +84 -1
package/dist/update-check.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { mkdir, readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { checkSkillVersion, skillNoticeLine } from './skill.js';
|
|
2
3
|
import { VERSION } from './version.js';
|
|
3
4
|
/** How long a registry answer stays authoritative, matching npm's update cache. */
|
|
4
5
|
export const UPDATE_CHECK_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
|
@@ -85,13 +86,28 @@ export async function fetchRegistryLatest(url, signal) {
|
|
|
85
86
|
const version = body.version;
|
|
86
87
|
return typeof version === 'string' && version ? version : null;
|
|
87
88
|
}
|
|
89
|
+
async function emitSkillNotice(check, onDiagnostic) {
|
|
90
|
+
const notice = await check.catch(() => {
|
|
91
|
+
// A local read failure must never break a command. The run continues silently.
|
|
92
|
+
return null;
|
|
93
|
+
});
|
|
94
|
+
if (notice && onDiagnostic)
|
|
95
|
+
onDiagnostic(skillNoticeLine(notice));
|
|
96
|
+
}
|
|
88
97
|
export async function checkForUpdate(options) {
|
|
89
98
|
if (updateCheckDisabled(options.env))
|
|
90
99
|
return null;
|
|
100
|
+
// The installed agent skill is the other half of "is this install current".
|
|
101
|
+
// It runs beside the registry fetch so neither waits for the other.
|
|
102
|
+
const skillCheck = options.onDiagnostic
|
|
103
|
+
? checkSkillVersion({ paths: options.paths, env: options.env, now: options.now })
|
|
104
|
+
: Promise.resolve(null);
|
|
91
105
|
const now = options.now?.() ?? new Date();
|
|
92
106
|
const cache = await readUpdateCheckCache(options.paths);
|
|
93
|
-
if (!updateCheckDue(cache, now))
|
|
107
|
+
if (!updateCheckDue(cache, now)) {
|
|
108
|
+
await emitSkillNotice(skillCheck, options.onDiagnostic);
|
|
94
109
|
return updateNoticeFor(cache.latest, VERSION);
|
|
110
|
+
}
|
|
95
111
|
const fetchLatest = options.fetch ?? fetchRegistryLatest;
|
|
96
112
|
const latest = await fetchLatest(REGISTRY_LATEST_URL, AbortSignal.timeout(FETCH_TIMEOUT_MS)).catch(() => {
|
|
97
113
|
// Registry reachability is best effort. The run continues without a hint.
|
|
@@ -99,6 +115,7 @@ export async function checkForUpdate(options) {
|
|
|
99
115
|
});
|
|
100
116
|
if (latest !== null)
|
|
101
117
|
await writeUpdateCheckCache(options.paths, { lastCheckedAt: now.toISOString(), latest });
|
|
118
|
+
await emitSkillNotice(skillCheck, options.onDiagnostic);
|
|
102
119
|
// A stale cached answer still beats no answer while the registry is unreachable.
|
|
103
120
|
return updateNoticeFor(latest ?? cache?.latest ?? null, VERSION);
|
|
104
121
|
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nuxtseo/cli",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.
|
|
5
|
-
"description": "Command line interface for the
|
|
4
|
+
"version": "0.4.0",
|
|
5
|
+
"description": "Command line interface for the Nuxt SEO public API.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://nuxtseo.com/pro",
|
|
8
8
|
"repository": {
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
35
|
"@clack/prompts": "^1.8.0",
|
|
36
|
-
"@nuxtseo/protocol": "^0.
|
|
37
|
-
"@nuxtseo/sdk": "^0.
|
|
36
|
+
"@nuxtseo/protocol": "^0.4.0",
|
|
37
|
+
"@nuxtseo/sdk": "^0.4.0",
|
|
38
38
|
"citty": "^0.2.2",
|
|
39
39
|
"pathe": "^2.0.3"
|
|
40
40
|
},
|
|
@@ -1,110 +1,98 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: nuxtseo-cli
|
|
3
|
-
description: Drives the `nuxtseo` CLI to triage a Site through the
|
|
3
|
+
description: Drives the `nuxtseo` CLI to triage a Site through the Nuxt SEO public API: Site status and ranked issues, Search Console rows, route-family indexing, field and lab Core Web Vitals, Lighthouse Scans, Page Issues, keyword competitor and domain research, backlinks, SERP analysis, rankings, link opportunities, content decay, duplicate clusters, chart annotations, and issue resolution. Use whenever the user mentions NuxtSEO, the `nuxtseo` command, Site SEO work, or Nuxt SEO automation.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
#
|
|
6
|
+
# `nuxtseo` CLI
|
|
7
7
|
|
|
8
|
-
`nuxtseo` reads a Site through the
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
Use it to answer "what is wrong with this site, and what did I break". Then fix
|
|
13
|
-
the code in the repository you are working in.
|
|
8
|
+
`nuxtseo` reads a Site through the Nuxt SEO public API. Use it to answer "what
|
|
9
|
+
is wrong with this site, and what did I break", then fix the cause in the
|
|
10
|
+
repository you are working in. There is no MCP or private-route fallback.
|
|
14
11
|
|
|
15
12
|
## Reference files
|
|
16
13
|
|
|
17
|
-
Read
|
|
18
|
-
|
|
19
|
-
- [references/commands.md](references/commands.md): every command, with its
|
|
20
|
-
flags, ranges, and defaults. Read it instead of guessing a flag.
|
|
21
|
-
- [references/protocol.md](references/protocol.md): response envelopes, paging,
|
|
22
|
-
and exit codes. Read it before you parse output or handle a failure.
|
|
23
|
-
- [references/indexing.md](references/indexing.md): how to answer "is this
|
|
24
|
-
indexed". Read it before you report an indexed count, or name the URLs
|
|
25
|
-
Google indexed.
|
|
26
|
-
|
|
27
|
-
## Get the binary
|
|
28
|
-
|
|
29
|
-
```sh
|
|
30
|
-
pnpm dlx @nuxtseo/cli@latest --version # no install
|
|
31
|
-
pnpm add -g @nuxtseo/cli # or npm install --global
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
Node 22 or newer is required.
|
|
35
|
-
|
|
36
|
-
Inside the NuxtSEO monorepo the package is not published. Run the built entry
|
|
37
|
-
directly:
|
|
14
|
+
Read the matching file before you act on its subject:
|
|
38
15
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
16
|
+
| File | Read it before you |
|
|
17
|
+
| --- | --- |
|
|
18
|
+
| [references/commands.md](references/commands.md) | use a flag, range, or default. Never guess a flag |
|
|
19
|
+
| [references/protocol.md](references/protocol.md) | parse output, page through a list, or handle an exit code |
|
|
20
|
+
| [references/indexing.md](references/indexing.md) | report an indexed count or name indexed URLs |
|
|
21
|
+
|
|
22
|
+
## Setup
|
|
23
|
+
|
|
24
|
+
1. **Binary.** Exit `127` means the CLI is absent. Install it, then continue:
|
|
25
|
+
|
|
26
|
+
```sh
|
|
27
|
+
pnpm dlx @nuxtseo/cli@latest --version # no install
|
|
28
|
+
pnpm add -g @nuxtseo/cli # global install, Node 22+
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Inside the Nuxt SEO monorepo, run `node packages/cli/dist/cli-entry.js`
|
|
32
|
+
instead.
|
|
33
|
+
|
|
34
|
+
2. **Skill version.** Run `nuxtseo --version --json`. If stderr carries a line
|
|
35
|
+
like `skill 0.3.0 installed, CLI 0.4.0. Refresh with: nuxtseo skill install
|
|
36
|
+
--agent claude`, run that command and re-read this file. A stale skill hides
|
|
37
|
+
commands, so a missing command reads as a missing feature. If
|
|
38
|
+
`NUXTSEO_NO_UPDATE_CHECK` is set, the line never appears; compare this
|
|
39
|
+
file's frontmatter `version` with the binary instead.
|
|
40
|
+
|
|
41
|
+
3. **Token.** Run `nuxtseo whoami --json`. It returns the Team, role, scopes,
|
|
42
|
+
and token expiry. Exit `3` means no working token. Ask the user to run
|
|
43
|
+
`nuxtseo login` themselves, because a person must approve it in a browser.
|
|
44
|
+
The other route is a token from
|
|
45
|
+
<https://nuxtseo.com/pro/dashboard/settings/api-tokens>, exported as
|
|
46
|
+
`NUXTSEO_TOKEN`. Never put a token in an argument, a file, or a commit.
|
|
47
|
+
|
|
48
|
+
4. **Scopes.** Read `data.scopes` now, not when a step fails. A `viewer` token
|
|
49
|
+
carries every `*:read` scope plus `feedback:write`. It can run every read,
|
|
50
|
+
including live research, and no write:
|
|
51
|
+
|
|
52
|
+
| Write | Scope |
|
|
53
|
+
| --- | --- |
|
|
54
|
+
| `page scan` | `page:write` |
|
|
55
|
+
| `actions resolve`, `actions dismiss` | `actions:write` |
|
|
56
|
+
| `annotations` writes | `timeline:write` |
|
|
57
|
+
| `sitemaps submit`, `sitemaps delete` | `sites:write` |
|
|
58
|
+
|
|
59
|
+
If a write scope is missing, do the reads, then hand the user the exact
|
|
60
|
+
write commands. Do not discover the block one exit `4` at a time.
|
|
61
|
+
|
|
62
|
+
5. **Site.** Run `nuxtseo sites list --json` once and reuse the ID. If more
|
|
63
|
+
than one Site is accessible and `--site` is absent, the CLI exits `5`
|
|
64
|
+
rather than guess.
|
|
65
|
+
|
|
66
|
+
## Calling convention
|
|
67
|
+
|
|
68
|
+
- Always pass `--json` and `--site <site-id>`. `feedback submit` needs no Site.
|
|
69
|
+
- `--json` writes one envelope to stdout. Diagnostics go to stderr. Parse the
|
|
70
|
+
JSON; never scrape human output.
|
|
71
|
+
- A mutation needs `--yes`. Without it, a non-interactive run exits `2`.
|
|
72
|
+
- `--timeout-ms` raises the 30000 ms deadline, up to 300000.
|
|
73
|
+
- An unknown option exits `2` before any network work.
|
|
74
|
+
- Branch on the exit code, never on message text. The table is in
|
|
75
|
+
[references/protocol.md](references/protocol.md).
|
|
42
76
|
|
|
43
|
-
|
|
44
|
-
`3`; no token has been checked yet. Install it, then continue.
|
|
77
|
+
## The triage loop
|
|
45
78
|
|
|
46
|
-
|
|
79
|
+
Copy this checklist and track your progress:
|
|
47
80
|
|
|
48
|
-
```sh
|
|
49
|
-
nuxtseo whoami --json # validates the token and reports its scopes
|
|
50
81
|
```
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
in a non-interactive shell it falls back to reading a token from stdin.
|
|
60
|
-
|
|
61
|
-
The alternative is a token created at
|
|
62
|
-
<https://nuxtseo.com/pro/dashboard/settings/api-tokens> and exported as
|
|
63
|
-
`NUXTSEO_TOKEN`. Either way the token is bound to a Team role, and that role
|
|
64
|
-
gates what it can do.
|
|
65
|
-
|
|
66
|
-
Never put a token in a command argument, a file you write, or a commit.
|
|
67
|
-
`login` reads a token from a hidden prompt or stdin only.
|
|
68
|
-
|
|
69
|
-
Resolve the Site once and reuse it. `nuxtseo sites list --json` prints every
|
|
70
|
-
accessible Site with its ID.
|
|
71
|
-
|
|
72
|
-
## How to call it as an agent
|
|
73
|
-
|
|
74
|
-
Always pass `--json`. Pass `--site <site-id>` for Site commands.
|
|
75
|
-
`feedback submit` needs no Site.
|
|
76
|
-
|
|
77
|
-
```sh
|
|
78
|
-
nuxtseo actions list --site site_123 --json
|
|
82
|
+
Triage progress:
|
|
83
|
+
- [ ] 1. status: read the verdict and the Next Action
|
|
84
|
+
- [ ] 2. actions list: pick a ranked action, check its freshness
|
|
85
|
+
- [ ] 3. actions show: read the evidence behind it
|
|
86
|
+
- [ ] 4. Fix the cause in the repository
|
|
87
|
+
- [ ] 5. page scan: re-scan a page you changed
|
|
88
|
+
- [ ] 6. actions resolve: claim the action
|
|
89
|
+
- [ ] 7. annotations create: mark the day the fix shipped
|
|
79
90
|
```
|
|
80
91
|
|
|
81
|
-
|
|
82
|
-
also disables prompts. Diagnostics, warnings, spinners, and failure messages go
|
|
83
|
-
to stderr, so stdout stays parseable.
|
|
84
|
-
|
|
85
|
-
`--site` matters for a second reason. An explicit Site ID goes straight to the
|
|
86
|
-
operation and skips the Sites read. A token whose role cannot list Sites still
|
|
87
|
-
works. If more than one Site is accessible and `--site` is absent, the CLI
|
|
88
|
-
exits `5` rather than guessing.
|
|
89
|
-
|
|
90
|
-
Other flags worth knowing:
|
|
91
|
-
|
|
92
|
-
| Flag | Use it when |
|
|
93
|
-
| --- | --- |
|
|
94
|
-
| `--yes`, `-y` | The command mutates. Without it, a non-interactive run exits `2` |
|
|
95
|
-
| `--timeout-ms <ms>` | The default 30000 ms deadline is too short. Maximum is 300000 |
|
|
96
|
-
| `--api-url <url>` | Testing against a non-production host |
|
|
97
|
-
| `--no-input` | Running in a TTY but no prompt is wanted. `--json` already implies this |
|
|
98
|
-
|
|
99
|
-
Unknown options exit `2` before any network work, so a typo costs nothing.
|
|
100
|
-
|
|
101
|
-
Parse JSON. Never scrape human output.
|
|
102
|
-
|
|
103
|
-
Every `--json` run prints one envelope. For example, `status` returns this,
|
|
104
|
-
abridged:
|
|
92
|
+
**1. Read the verdict.**
|
|
105
93
|
|
|
106
94
|
```sh
|
|
107
|
-
nuxtseo status --site
|
|
95
|
+
nuxtseo status --site <site-id> --json
|
|
108
96
|
```
|
|
109
97
|
|
|
110
98
|
```json
|
|
@@ -118,104 +106,73 @@ nuxtseo status --site site_01JXYZ --json
|
|
|
118
106
|
}
|
|
119
107
|
```
|
|
120
108
|
|
|
121
|
-
|
|
122
|
-
Read `
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
This sequence turns CLI output into a code change. Copy the checklist and track
|
|
128
|
-
your progress:
|
|
129
|
-
|
|
130
|
-
```
|
|
131
|
-
Triage progress:
|
|
132
|
-
- [ ] 1. status: read the verdict and the Next Action
|
|
133
|
-
- [ ] 2. actions list: pick a ranked action, check its freshness
|
|
134
|
-
- [ ] 3. actions show: read the evidence behind it
|
|
135
|
-
- [ ] 4. Fix the cause in the repository
|
|
136
|
-
- [ ] 5. page scan: re-scan a page you changed
|
|
137
|
-
- [ ] 6. actions resolve: claim the action
|
|
138
|
-
- [ ] 7. annotations create: mark the day the fix shipped
|
|
139
|
-
```
|
|
109
|
+
- `available: false` means the first assessment has not run.
|
|
110
|
+
- Read `dataQuality.status` before you quote the verdict. `degraded` means
|
|
111
|
+
proofs were missing, so the verdict is Provisional. `unavailable` means it
|
|
112
|
+
has not run.
|
|
113
|
+
- If `nextAction.kind` is `action`, pass its `actionId` to step 3.
|
|
140
114
|
|
|
141
|
-
|
|
115
|
+
For the whole Site instead of the next action, run one `pull`. It performs
|
|
116
|
+
every spend-free Site read and writes one envelope per line:
|
|
142
117
|
|
|
143
118
|
```sh
|
|
144
|
-
nuxtseo
|
|
119
|
+
nuxtseo pull --site <site-id> --json > site.ndjson
|
|
145
120
|
```
|
|
146
121
|
|
|
147
|
-
|
|
148
|
-
and what changed recently. Read `dataQuality.status` before quoting it.
|
|
149
|
-
`degraded` means the assessment ran with proofs missing, so the verdict is real
|
|
150
|
-
but Provisional. `unavailable` means it has not run. If `nextAction.kind` is
|
|
151
|
-
`action`, its `actionId` goes straight into step 3.
|
|
152
|
-
|
|
153
|
-
**Step 2. Pick a ranked action.**
|
|
122
|
+
**2. Pick a ranked action.**
|
|
154
123
|
|
|
155
124
|
```sh
|
|
156
125
|
nuxtseo actions list --site <site-id> --json
|
|
157
126
|
```
|
|
158
127
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
since the observation.
|
|
128
|
+
Keep server order. Check `evidence.freshness` on each row. If `verdict` is
|
|
129
|
+
`aged` with a large `ageHours`, live-check a cheap sample before you fix. The
|
|
130
|
+
Site may have changed since the observation.
|
|
163
131
|
|
|
164
|
-
**
|
|
132
|
+
**3. Read the evidence.**
|
|
165
133
|
|
|
166
134
|
```sh
|
|
167
135
|
nuxtseo actions show <action-id> --site <site-id> --json
|
|
168
136
|
```
|
|
169
137
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
Two reads deepen this step when the action's own evidence is not enough:
|
|
138
|
+
It names the pages, the finding type, and when it was observed. Two reads go
|
|
139
|
+
deeper:
|
|
173
140
|
|
|
174
|
-
- `
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
membership.
|
|
179
|
-
- `nuxtseo scans show <scan-id> --site <site-id> --json` returns the failing
|
|
180
|
-
checks behind a Lighthouse score, so you can locate the cause without
|
|
181
|
-
re-scanning.
|
|
141
|
+
- `page issues --action-id <action-id>`: the raw observations, with URLs,
|
|
142
|
+
status codes, redirect targets, and Lighthouse selectors. This is the
|
|
143
|
+
mutable observation store, never canonical action membership.
|
|
144
|
+
- `scans show <scan-id>`: the failing checks behind a Lighthouse score.
|
|
182
145
|
|
|
183
|
-
**
|
|
146
|
+
**4. Fix the cause.** Map the URLs in the evidence to routes, components, or
|
|
147
|
+
config.
|
|
184
148
|
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
**Step 5. Re-scan a page you changed.**
|
|
188
|
-
|
|
189
|
-
Deploy or preview the fix first. Then ask for fresh Scans:
|
|
149
|
+
**5. Re-scan.** Deploy or preview the fix first:
|
|
190
150
|
|
|
191
151
|
```sh
|
|
192
152
|
nuxtseo page scan <url> --site <site-id> --yes --json
|
|
193
153
|
```
|
|
194
154
|
|
|
195
|
-
**
|
|
155
|
+
**6. Claim the action.**
|
|
196
156
|
|
|
197
157
|
```sh
|
|
198
158
|
nuxtseo actions resolve <action-id> --site <site-id> --yes --json
|
|
199
159
|
```
|
|
200
160
|
|
|
201
|
-
The server verifies
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
exits `5` with `stale_evidence`. Re-run step 3 and decide again.
|
|
161
|
+
The server verifies the claim; the CLI never marks anything fixed. Resolve
|
|
162
|
+
sends the current `artifactVersion` for you. If the evidence moved, it exits
|
|
163
|
+
`5` with `stale_evidence`: re-run step 3 and decide again.
|
|
205
164
|
|
|
206
|
-
|
|
207
|
-
|
|
165
|
+
If the fix is a deliberate removal, dismiss instead. Read `artifactVersion`
|
|
166
|
+
from `actions show`, then:
|
|
208
167
|
|
|
209
168
|
```sh
|
|
210
|
-
nuxtseo actions show <action-id> --site <site-id> --json # read artifactVersion
|
|
211
169
|
nuxtseo actions dismiss <action-id> --site <site-id> --artifact-version <v> --yes --json
|
|
212
170
|
```
|
|
213
171
|
|
|
214
|
-
|
|
215
|
-
evidence and no internal referrers.
|
|
216
|
-
used to hide work.
|
|
172
|
+
The server admits a dismiss only for a broken-page action with complete 404 or
|
|
173
|
+
410 evidence and no internal referrers.
|
|
217
174
|
|
|
218
|
-
**
|
|
175
|
+
**7. Mark the day.**
|
|
219
176
|
|
|
220
177
|
```sh
|
|
221
178
|
nuxtseo annotations create --site <site-id> --date "$(date -u +%F)" --title "Fixed canonicals on /docs" --yes --json
|
|
@@ -223,117 +180,93 @@ nuxtseo annotations create --site <site-id> --date "$(date -u +%F)" --title "Fix
|
|
|
223
180
|
|
|
224
181
|
The next traffic move then has a cause beside it.
|
|
225
182
|
|
|
226
|
-
##
|
|
227
|
-
|
|
228
|
-
Two datasets share the word "vitals":
|
|
229
|
-
|
|
230
|
-
- `performance` and `scans *` read Lighthouse **lab** Scans.
|
|
231
|
-
- `vitals summary`, `vitals trend`, and `vitals findings` read **field**
|
|
232
|
-
(real-user) data. `vitals` reads CrUX. `vitals findings` reads the Site's own
|
|
233
|
-
Web Analytics provider.
|
|
234
|
-
|
|
235
|
-
A lab score and a field p75 disagreeing is normal, not a fault.
|
|
236
|
-
|
|
237
|
-
Two commands inspect the same URL and answer different questions. `page inspect`
|
|
238
|
-
reads the NuxtSEO observation store. `search inspect` reads Google's index
|
|
239
|
-
verdict.
|
|
240
|
-
|
|
241
|
-
`status`, `performance`, and `vitals` answer different questions. `status` is
|
|
242
|
-
the verdict. `performance` is the lab score. `vitals` is what real users
|
|
243
|
-
measured. Never substitute one for another.
|
|
244
|
-
|
|
245
|
-
The Search Console reads also split:
|
|
246
|
-
|
|
247
|
-
- `search status` reads stored connection state. It never waits for Google.
|
|
248
|
-
- `search analytics`, `search indexing`, `search index-history`, and
|
|
249
|
-
`search inspect` read retained Search Console evidence through the public API.
|
|
250
|
-
- `sitemaps submit` and `sitemaps delete` reach Google through the Site's
|
|
251
|
-
stored Search Console credential. Both are mutations.
|
|
183
|
+
## Reading results correctly
|
|
252
184
|
|
|
253
|
-
|
|
185
|
+
**Empty is not clean.** Each read names its own kind of empty. Say which one
|
|
186
|
+
you got:
|
|
254
187
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
188
|
+
| Command | Empty signal |
|
|
189
|
+
| --- | --- |
|
|
190
|
+
| `page inspect` | `observations.coverage` |
|
|
191
|
+
| `page issues` | `availableKeys` |
|
|
192
|
+
| `search cohorts` | `analysed: false`: no completed crawl, or no Google index state |
|
|
193
|
+
| `vitals summary` | `available: false` |
|
|
194
|
+
| `research keywords`, `research rankings`, `research domain-*`, `page issues`, `search cohorts`, `vitals findings` | `data.message`, and `data.tip` for the repair |
|
|
195
|
+
|
|
196
|
+
Read `data.message` before the list. For example, `research keywords` refuses
|
|
197
|
+
a seed over three words, still exits `0`, and returns `keywords: []` with
|
|
198
|
+
`evidence._tag: "no-provider"`. That is a refused argument, not zero demand.
|
|
199
|
+
|
|
200
|
+
**A refusal is not an empty Site.** Exit `4` is a plan, scope, or entitlement
|
|
201
|
+
blocker, for example `entitlement_required`. Exit `5` on `status`, `page
|
|
202
|
+
issues`, or `search cohorts` can mean an archived or paused Site. Report the
|
|
203
|
+
blocker and stop. Do not read it as "no data" or "nothing wrong", and do not
|
|
204
|
+
retry unchanged.
|
|
205
|
+
|
|
206
|
+
**Quote the count the result ships.** Never quote the length of a list. Use
|
|
207
|
+
`data.total` from `page issues`, and `coverage.accessibilityChecksTotal` and
|
|
208
|
+
`coverage.bestPracticesChecksTotal` from `scans show`. `possiblyTruncated:
|
|
209
|
+
true` marks the list as a floor.
|
|
210
|
+
|
|
211
|
+
**Keep these datasets apart:**
|
|
212
|
+
|
|
213
|
+
- `performance` and `scans *` read Lighthouse **lab** Scans. `vitals summary`
|
|
214
|
+
and `vitals trend` read CrUX **field** data. `vitals findings` reads the
|
|
215
|
+
Site's own Web Analytics provider. A lab score and a field p75 that disagree
|
|
216
|
+
is normal.
|
|
217
|
+
- `status` is the verdict, `performance` the lab score, `vitals` what real
|
|
218
|
+
users measured. Never substitute one for another.
|
|
219
|
+
- `page inspect` reads the Nuxt SEO observation store. `search inspect` reads
|
|
220
|
+
Google's index verdict for the same URL.
|
|
221
|
+
- `search status` reads the stored connection and never waits for Google.
|
|
222
|
+
`search analytics`, `search indexing`, `search index-history`, and
|
|
223
|
+
`search inspect` read retained Search Console evidence.
|
|
224
|
+
- An indexed count comes from `search indexing`, never from analytics rows.
|
|
225
|
+
See [references/indexing.md](references/indexing.md).
|
|
226
|
+
|
|
227
|
+
**Route families: `established` versus `ranked`.** Read `search cohorts`
|
|
228
|
+
before you list single not-indexed URLs. Never merge its two lists:
|
|
229
|
+
|
|
230
|
+
- `established` holds only families whose not-indexed rate is significant
|
|
231
|
+
against the rest of the Site, after a Bonferroni correction. Only these rows
|
|
232
|
+
are a finding or a cause.
|
|
233
|
+
- `ranked` orders every family by raw rate, with no significance test. A row
|
|
234
|
+
with `statisticallyEstablished: false` is a lead to verify, for example by
|
|
235
|
+
inspecting its URLs. Presenting it as a cause is a hard failure.
|
|
259
236
|
|
|
260
|
-
|
|
261
|
-
not-indexed rate of their **own complement** after a Bonferroni correction.
|
|
262
|
-
These are the only rows you may report as a finding or a cause.
|
|
263
|
-
- `ranked` orders every family by raw rate, with **no significance test**. It
|
|
264
|
-
always answers "where is indexing worst", even when nothing is provable. A
|
|
265
|
-
row with `statisticallyEstablished: false` is a lead to verify, never a
|
|
266
|
-
conclusion. Presenting one as established is a hard failure.
|
|
237
|
+
## Guardrails
|
|
267
238
|
|
|
268
|
-
|
|
269
|
-
|
|
239
|
+
- **Get consent before a mutation.** `page scan`, `actions resolve`, `actions
|
|
240
|
+
dismiss`, `sitemaps submit`, `sitemaps delete`, and the `annotations` writes
|
|
241
|
+
change server state. `sitemaps` writes also reach Google. `--yes` is consent
|
|
242
|
+
you borrow from the user, so ask first unless they asked for that exact
|
|
243
|
+
action.
|
|
244
|
+
- **Spend limits.** `page scan` spends Lighthouse limit. `research *` and the
|
|
245
|
+
`backlinks` reads spend the Team research limit, except `backlinks
|
|
246
|
+
recoverable` and `mentions list`, which read retained rows. A `cache` or
|
|
247
|
+
`no-provider` evidence tag, or `cached: true`, means nothing was spent.
|
|
248
|
+
Check `usage` before any run over many Pages, keywords, or domains.
|
|
249
|
+
- **No shell loops.** Use `pull` for Site reads and `--all` for paging. `--all`
|
|
250
|
+
stops at 50 requests with exit `9`; treat that as a stop and resume with the
|
|
251
|
+
argument stderr names.
|
|
270
252
|
|
|
271
253
|
## Report CLI feedback
|
|
272
254
|
|
|
273
|
-
If CLI
|
|
274
|
-
|
|
275
|
-
|
|
255
|
+
If the CLI blocks or slows your work, report it once per distinct problem, then
|
|
256
|
+
continue the task. This skill authorizes that; no confirmation is needed unless
|
|
257
|
+
the user forbids reporting.
|
|
276
258
|
|
|
277
259
|
```sh
|
|
278
|
-
nuxtseo feedback submit --command "search cohorts" --agent "
|
|
279
|
-
--comment "Agent report by
|
|
260
|
+
nuxtseo feedback submit --command "search cohorts" --agent "<your agent name>" \
|
|
261
|
+
--comment "Agent report by <your agent name>. Expected a reason for missing data. Received an empty list. Used search status instead." \
|
|
280
262
|
--yes --json
|
|
281
263
|
```
|
|
282
264
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
Self-reporting sanitized CLI feedback is authorized by this skill. No separate confirmation is needed.
|
|
293
|
-
This permission covers feedback only. Respect any user instruction that forbids reporting.
|
|
294
|
-
The endpoint requires a working credential with `feedback:write`, available to every Team role.
|
|
295
|
-
It uses no paid limit and allows ten reports per credential each hour.
|
|
296
|
-
|
|
297
|
-
Success returns `data.id` and `data.status: "new"`. Keep the ID with your task notes.
|
|
298
|
-
If reporting fails, mention the failure and continue. Never retry uncertain submissions or report failures recursively.
|
|
299
|
-
If authentication is broken, describe the feedback to the user. Do not invent another endpoint.
|
|
300
|
-
|
|
301
|
-
Reports use the existing feedback queue through `POST /api/v1/account/feedback`.
|
|
302
|
-
Health checks show unresolved reports across all dates.
|
|
303
|
-
Operators use **Pro feedback** in admin to record a fix reference and set `fixed` after verification.
|
|
304
|
-
Fixed, replied, closed, and ignored reports leave the health check list. Reopening restores them.
|
|
305
|
-
|
|
306
|
-
## Guardrails
|
|
307
|
-
|
|
308
|
-
- **Get consent before a mutation.** `actions resolve`, `actions dismiss`,
|
|
309
|
-
`page scan`, `sitemaps submit`, `sitemaps delete`, `content briefs create`,
|
|
310
|
-
and the `annotations` writes all change server state. `page scan` also spends
|
|
311
|
-
against the Lighthouse limit. `--yes` is consent you borrow from the user, so
|
|
312
|
-
ask first, unless the user already asked for that exact action. `actions
|
|
313
|
-
dismiss` says the page stays removed, so use it only when that is the
|
|
314
|
-
decision.
|
|
315
|
-
- **Live research spends against the Team research limit.** `research
|
|
316
|
-
keywords`, `research serp`, `research rankings`, `research domain-traffic`,
|
|
317
|
-
`research domain-availability`, and the `backlinks` reads other than
|
|
318
|
-
`backlinks recoverable` can all start it. Each one reports what it did.
|
|
319
|
-
Keyword, domain, and backlink JSON report cache use in `evidence`; a `cache`
|
|
320
|
-
or `no-provider` tag means nothing was spent. SERP and ranking JSON report
|
|
321
|
-
`cached`. `backlinks recoverable` and `mentions list` read retained rows and
|
|
322
|
-
spend nothing.
|
|
323
|
-
- **Never loop unattended.** Check `usage` before any run over Pages, keywords,
|
|
324
|
-
or domains. Use `--all` rather than your own offset loop. It writes one
|
|
325
|
-
envelope per line and stops at 50 requests with exit `9`. Treat exit `9` as a
|
|
326
|
-
stop, then resume with the argument stderr names.
|
|
327
|
-
- **Report the result as the CLI gave it.** Report failures as they are; there
|
|
328
|
-
is no MCP or private-route fallback. Never treat an empty result as clean:
|
|
329
|
-
`page inspect` names the kind of empty through `observations.coverage`,
|
|
330
|
-
`page issues` through `availableKeys`, `search cohorts` through
|
|
331
|
-
`analysed: false`, and `vitals summary` through `available: false`. A refusal
|
|
332
|
-
reads differently again: `status`, `page issues` and `search cohorts` exit
|
|
333
|
-
`4` or `5` on an archived or paused Site, which is never an empty Site. Other
|
|
334
|
-
commands may still return Provisional evidence. Quote the counts a result
|
|
335
|
-
ships with, never the length of its list: `data.total` from `page issues`,
|
|
336
|
-
then `coverage.accessibilityChecksTotal` and
|
|
337
|
-
`coverage.bestPracticesChecksTotal` from `scans show`. Neither command
|
|
338
|
-
reports the dropped row count, so `possiblyTruncated: true` marks the list as
|
|
339
|
-
a floor.
|
|
265
|
+
- Start the comment with an agent disclosure. Give reproduction steps, the
|
|
266
|
+
expected and actual behaviour, and any workaround.
|
|
267
|
+
- Pass `--request-id` when the response had one. Use `--intent improvement`
|
|
268
|
+
for a suggestion; the default is `bug`.
|
|
269
|
+
- Send sanitized details only: no tokens, cookies, personal data, private URLs,
|
|
270
|
+
customer content, raw logs, or full response bodies.
|
|
271
|
+
- The limit is ten reports per credential per hour. If a report fails, say so
|
|
272
|
+
and continue. Never retry it or report the failure.
|