@nuxtseo/cli 0.1.2 → 0.1.4
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 +10 -5
- package/dist/cli.js +4 -1
- package/dist/command-contract.d.ts +2 -1
- package/dist/command-contract.js +4 -2
- package/dist/commands.js +96 -1
- package/dist/render.d.ts +4 -1
- package/dist/render.js +40 -0
- package/package.json +3 -3
- package/skills/nuxtseo-cli/SKILL.md +7 -5
- package/skills/nuxtseo-cli/references/protocol.md +2 -1
package/README.md
CHANGED
|
@@ -123,12 +123,14 @@ to stdout and writes the readable recovery message to stderr.
|
|
|
123
123
|
|
|
124
124
|
Local outcomes have no server protocol body. With `--json`, commands such as
|
|
125
125
|
bare `nuxtseo`, `config`, `logout`, and `sites use` emit a tagged CLI-owned JSON
|
|
126
|
-
value with `schemaVersion: 1`.
|
|
127
|
-
and exit code. These tags are separate from
|
|
126
|
+
value with `schemaVersion: 1`. `CliHelp` uses `schemaVersion: 2`. Local failures
|
|
127
|
+
emit `CliError` with a stable code and exit code. These tags are separate from
|
|
128
|
+
protocol envelopes.
|
|
128
129
|
|
|
129
|
-
`--help --json` returns the selected command,
|
|
130
|
-
|
|
131
|
-
|
|
130
|
+
`--help --json` returns the selected command, inherited `globalOptions`,
|
|
131
|
+
positional `arguments`, command-specific `localOptions`, and `subcommands` as
|
|
132
|
+
`CliHelp`. Option names are strict. An unknown option exits `2` before
|
|
133
|
+
authentication or network work.
|
|
132
134
|
|
|
133
135
|
## Automation controls
|
|
134
136
|
|
|
@@ -172,6 +174,7 @@ nuxtseo page scan <url>
|
|
|
172
174
|
nuxtseo performance
|
|
173
175
|
nuxtseo search status
|
|
174
176
|
nuxtseo search analytics <pages|keywords>
|
|
177
|
+
nuxtseo search indexing <summary|urls>
|
|
175
178
|
nuxtseo research overview
|
|
176
179
|
nuxtseo research keywords <topic>
|
|
177
180
|
nuxtseo research serp <keyword>
|
|
@@ -189,6 +192,7 @@ performance, research, content, and account setup. The menu prints the direct
|
|
|
189
192
|
command it runs.
|
|
190
193
|
|
|
191
194
|
`search status` reads stored connection state. It never waits for Google.
|
|
195
|
+
`search indexing summary` reads retained URL Inspection coverage.
|
|
192
196
|
`research keywords`, `research serp`, and `research rankings` can use the Team
|
|
193
197
|
research allowance. Keyword responses report cache use in `evidence`. SERP and
|
|
194
198
|
ranking responses report `cached: true`. Cached responses use no unit.
|
|
@@ -204,6 +208,7 @@ responses.
|
|
|
204
208
|
| `backlinks recoverable` | `--limit 1..200`, `--offset >=0` | `--limit 100 --offset 0` |
|
|
205
209
|
| `mentions list` | `--limit 1..200` | `--limit 100` |
|
|
206
210
|
| `search analytics` | `--limit 1..100`, `--page >=1` | `--limit 25 --page 1` |
|
|
211
|
+
| `search indexing` | `--limit 1..500`, `--offset >=0` | `--limit 50 --offset 0` |
|
|
207
212
|
| `content briefs list` | `--limit 1..100`, `--offset >=0` | `--limit 25 --offset 0` |
|
|
208
213
|
|
|
209
214
|
Keep the server order for actions. For another page, pass the next offset or
|
package/dist/cli.js
CHANGED
|
@@ -252,6 +252,7 @@ async function interactiveBare(runtime, globals) {
|
|
|
252
252
|
options: [
|
|
253
253
|
{ value: 'performance', label: 'Performance overview' },
|
|
254
254
|
{ value: 'connection', label: 'Search Console connection' },
|
|
255
|
+
{ value: 'indexing', label: 'Search indexing coverage' },
|
|
255
256
|
{ value: 'pages', label: 'Search Console Pages' },
|
|
256
257
|
{ value: 'keywords', label: 'Search Console queries' },
|
|
257
258
|
],
|
|
@@ -265,7 +266,9 @@ async function interactiveBare(runtime, globals) {
|
|
|
265
266
|
? ['performance']
|
|
266
267
|
: task === 'connection'
|
|
267
268
|
? ['search', 'status']
|
|
268
|
-
:
|
|
269
|
+
: task === 'indexing'
|
|
270
|
+
? ['search', 'indexing', 'summary']
|
|
271
|
+
: ['search', 'analytics', task];
|
|
269
272
|
return runInteractiveCommand(command, runtime, globals);
|
|
270
273
|
}
|
|
271
274
|
if (group === 'research') {
|
|
@@ -16,12 +16,13 @@ export interface CliHelpArgument {
|
|
|
16
16
|
}
|
|
17
17
|
export interface CliHelpResponse {
|
|
18
18
|
_tag: 'CliHelp';
|
|
19
|
-
schemaVersion:
|
|
19
|
+
schemaVersion: 2;
|
|
20
20
|
cliVersion: string;
|
|
21
21
|
command: string;
|
|
22
22
|
description?: string;
|
|
23
23
|
globalOptions: CliHelpArgument[];
|
|
24
24
|
arguments: CliHelpArgument[];
|
|
25
|
+
localOptions: CliHelpArgument[];
|
|
25
26
|
subcommands: Array<{
|
|
26
27
|
name: string;
|
|
27
28
|
description?: string;
|
package/dist/command-contract.js
CHANGED
|
@@ -54,14 +54,16 @@ function argumentsFor(command) {
|
|
|
54
54
|
export function describeCommand(root, rawArgs, cliVersion) {
|
|
55
55
|
const resolved = resolveCommand(root, rawArgs.filter(argument => argument !== '--help' && argument !== '-h'));
|
|
56
56
|
const meta = commandMeta(resolved.command);
|
|
57
|
+
const localArguments = resolved.command === root ? [] : argumentsFor(resolved.command);
|
|
57
58
|
return {
|
|
58
59
|
_tag: 'CliHelp',
|
|
59
|
-
schemaVersion:
|
|
60
|
+
schemaVersion: 2,
|
|
60
61
|
cliVersion,
|
|
61
62
|
command: resolved.path.join(' '),
|
|
62
63
|
...(meta.description === undefined ? {} : { description: meta.description }),
|
|
63
64
|
globalOptions: argumentsFor(root).filter(argument => argument.type !== 'positional'),
|
|
64
|
-
arguments:
|
|
65
|
+
arguments: localArguments.filter(argument => argument.type === 'positional'),
|
|
66
|
+
localOptions: localArguments.filter(argument => argument.type !== 'positional'),
|
|
65
67
|
subcommands: Object.entries(commandChildren(resolved.command)).flatMap(([name, value]) => {
|
|
66
68
|
const child = childCommand(value);
|
|
67
69
|
if (!child)
|
package/dist/commands.js
CHANGED
|
@@ -5,7 +5,7 @@ import { openBrowser } from './browser.js';
|
|
|
5
5
|
import { EXIT_CODE, fail, fromSdkFailure, ok } from './failures.js';
|
|
6
6
|
import { awaitPairingApproval, createCliPairingClient, startPairing } from './pairing.js';
|
|
7
7
|
import { parseAbsolutePageUrl, parseChoice, parseInteger } from './parse.js';
|
|
8
|
-
import { renderAction, renderActionResolution, renderActions, renderContentBrief, renderContentBriefCreated, renderContentBriefs, renderContentDecay, renderDuplicateClusters, renderKeywordResearch, renderLinkOpportunities, renderMentions, renderPageInspection, renderPageScan, renderPerformance, renderRankingsResearch, renderRecoverableBacklinks, renderResearchOverview, renderSearchAnalytics, renderSearchStatus, renderSerpResearch, renderSites, renderUsage, } from './render.js';
|
|
8
|
+
import { renderAction, renderActionResolution, renderActions, renderContentBrief, renderContentBriefCreated, renderContentBriefs, renderContentDecay, renderDuplicateClusters, renderIndexingDiagnostics, renderKeywordResearch, renderLinkOpportunities, renderMentions, renderPageInspection, renderPageScan, renderPerformance, renderRankingsResearch, renderRecoverableBacklinks, renderResearchOverview, renderSearchAnalytics, renderSearchStatus, renderSerpResearch, renderSites, renderTimeline, renderUsage, } from './render.js';
|
|
9
9
|
import { writeCliResponse, writeDiagnostic, writeOutput, writeProtocolResponse } from './runtime.js';
|
|
10
10
|
import { resolveSite } from './site.js';
|
|
11
11
|
import { clearCredential, getCredentialStatus, readConfig, resolveApiUrl, saveCredential, updateConfig, } from './state/index.js';
|
|
@@ -447,6 +447,36 @@ async function searchAnalytics(runtime, globals, args) {
|
|
|
447
447
|
}, { signal: runtime.requestSignal }));
|
|
448
448
|
return present(runtime, globals, response, value => renderSearchAnalytics(value.data));
|
|
449
449
|
}
|
|
450
|
+
async function searchIndexing(runtime, globals, args) {
|
|
451
|
+
const view = parseChoice(args.view, { name: 'view', choices: ['summary', 'urls'] });
|
|
452
|
+
if (view._tag === 'Err')
|
|
453
|
+
return view;
|
|
454
|
+
const status = args.status === undefined
|
|
455
|
+
? ok(undefined)
|
|
456
|
+
: parseChoice(args.status, { name: '--status', choices: ['indexed', 'not_indexed', 'pending'] });
|
|
457
|
+
if (status._tag === 'Err')
|
|
458
|
+
return status;
|
|
459
|
+
const limit = parseInteger(args.limit, { name: '--limit', minimum: 1, maximum: 500, defaultValue: 50 });
|
|
460
|
+
if (limit._tag === 'Err')
|
|
461
|
+
return limit;
|
|
462
|
+
const offset = parseInteger(args.offset, { name: '--offset', minimum: 0, defaultValue: 0 });
|
|
463
|
+
if (offset._tag === 'Err')
|
|
464
|
+
return offset;
|
|
465
|
+
const resolved = await apiAndSite(runtime, globals);
|
|
466
|
+
if (resolved._tag === 'Err')
|
|
467
|
+
return resolved;
|
|
468
|
+
const response = await withSpinner(runtime, 'Loading Search Console indexing', () => resolved.value.api.client.search.readIndexingDiagnostics({
|
|
469
|
+
params: { siteId: resolved.value.siteId },
|
|
470
|
+
query: {
|
|
471
|
+
view: view.value,
|
|
472
|
+
issue: args.issue,
|
|
473
|
+
status: status.value,
|
|
474
|
+
limit: limit.value,
|
|
475
|
+
offset: offset.value,
|
|
476
|
+
},
|
|
477
|
+
}, { signal: runtime.requestSignal }));
|
|
478
|
+
return present(runtime, globals, response, value => renderIndexingDiagnostics(value.data));
|
|
479
|
+
}
|
|
450
480
|
async function researchOverview(runtime, globals) {
|
|
451
481
|
const resolved = await apiAndSite(runtime, globals);
|
|
452
482
|
if (resolved._tag === 'Err')
|
|
@@ -576,6 +606,27 @@ async function auditLinkOpportunities(runtime, globals) {
|
|
|
576
606
|
}, { signal: runtime.requestSignal }));
|
|
577
607
|
return present(runtime, globals, response, value => renderLinkOpportunities(value.data));
|
|
578
608
|
}
|
|
609
|
+
async function timelineEntries(runtime, globals, args) {
|
|
610
|
+
const limit = parseInteger(args.limit, { name: '--limit', minimum: 1, maximum: 100, defaultValue: 25 });
|
|
611
|
+
if (limit._tag === 'Err')
|
|
612
|
+
return limit;
|
|
613
|
+
const resolved = await apiAndSite(runtime, globals);
|
|
614
|
+
if (resolved._tag === 'Err')
|
|
615
|
+
return resolved;
|
|
616
|
+
const response = await withSpinner(runtime, 'Loading Timeline', () => resolved.value.api.client.timeline.entries({
|
|
617
|
+
params: { siteId: resolved.value.siteId },
|
|
618
|
+
query: {
|
|
619
|
+
kinds: args.kind,
|
|
620
|
+
feature: args.feature,
|
|
621
|
+
severity: args.severity,
|
|
622
|
+
since: args.since,
|
|
623
|
+
limit: limit.value,
|
|
624
|
+
cursor: args.cursor,
|
|
625
|
+
includeClosed: args.includeClosed,
|
|
626
|
+
},
|
|
627
|
+
}, { signal: runtime.requestSignal }));
|
|
628
|
+
return present(runtime, globals, response, value => renderTimeline(value.data));
|
|
629
|
+
}
|
|
579
630
|
async function contentBriefList(runtime, globals, args) {
|
|
580
631
|
const status = args.status === undefined
|
|
581
632
|
? ok(undefined)
|
|
@@ -928,6 +979,49 @@ export function createRootCommand(runtime, globals, execution) {
|
|
|
928
979
|
sortDir: args['sort-dir'],
|
|
929
980
|
}), args._, 1)(),
|
|
930
981
|
}),
|
|
982
|
+
indexing: defineCommand({
|
|
983
|
+
meta: { name: 'indexing', description: 'Read retained Search Console indexing coverage' },
|
|
984
|
+
args: {
|
|
985
|
+
view: positional('summary-or-urls', 'summary or urls'),
|
|
986
|
+
issue: { type: 'string', description: 'Filter URLs by issue type' },
|
|
987
|
+
status: { type: 'enum', options: ['indexed', 'not_indexed', 'pending'], description: 'Filter URLs by indexing status' },
|
|
988
|
+
limit: { type: 'string', description: 'Maximum URLs, 1 to 500' },
|
|
989
|
+
offset: { type: 'string', description: 'Pagination offset' },
|
|
990
|
+
},
|
|
991
|
+
run: ({ args }) => capture(execution, () => searchIndexing(runtime, globals, {
|
|
992
|
+
view: args.view,
|
|
993
|
+
issue: args.issue,
|
|
994
|
+
status: args.status,
|
|
995
|
+
limit: args.limit,
|
|
996
|
+
offset: args.offset,
|
|
997
|
+
}), args._, 1)(),
|
|
998
|
+
}),
|
|
999
|
+
},
|
|
1000
|
+
});
|
|
1001
|
+
const timeline = defineCommand({
|
|
1002
|
+
meta: { name: 'timeline', description: 'Read the Timeline — what changed on the Site' },
|
|
1003
|
+
subCommands: {
|
|
1004
|
+
list: defineCommand({
|
|
1005
|
+
meta: { name: 'list', description: 'List Timeline Entries' },
|
|
1006
|
+
args: {
|
|
1007
|
+
'kind': { type: 'string', description: 'Comma-separated Timeline Entry kinds, e.g. traffic.dropped,indexing.changed' },
|
|
1008
|
+
'feature': { type: 'string', description: 'Filter to the kinds registered under this feature' },
|
|
1009
|
+
'severity': { type: 'string', description: 'Comma-separated severities: info, notable, high' },
|
|
1010
|
+
'since': { type: 'string', description: 'Only entries at or after this ISO timestamp' },
|
|
1011
|
+
'limit': { type: 'string', description: 'Maximum Timeline Entries, 1 to 100' },
|
|
1012
|
+
'cursor': { type: 'string', description: 'Opaque pagination cursor from a previous page' },
|
|
1013
|
+
'include-closed': { type: 'boolean', description: 'Include closed episodes' },
|
|
1014
|
+
},
|
|
1015
|
+
run: ({ args }) => capture(execution, () => timelineEntries(runtime, globals, {
|
|
1016
|
+
kind: args.kind,
|
|
1017
|
+
feature: args.feature,
|
|
1018
|
+
severity: args.severity,
|
|
1019
|
+
since: args.since,
|
|
1020
|
+
limit: args.limit,
|
|
1021
|
+
cursor: args.cursor,
|
|
1022
|
+
includeClosed: args['include-closed'],
|
|
1023
|
+
}), args._, 0)(),
|
|
1024
|
+
}),
|
|
931
1025
|
},
|
|
932
1026
|
});
|
|
933
1027
|
return defineCommand({
|
|
@@ -994,6 +1088,7 @@ export function createRootCommand(runtime, globals, execution) {
|
|
|
994
1088
|
}),
|
|
995
1089
|
research,
|
|
996
1090
|
search,
|
|
1091
|
+
timeline,
|
|
997
1092
|
},
|
|
998
1093
|
});
|
|
999
1094
|
}
|
package/dist/render.d.ts
CHANGED
|
@@ -3,10 +3,11 @@ import type { ActionList, ActionResolve, ActionShow } from '@nuxtseo/protocol/v1
|
|
|
3
3
|
import type { AuditContentDecay, AuditDuplicateClusters, AuditLinkOpportunities } from '@nuxtseo/protocol/v1/audit';
|
|
4
4
|
import type { Mentions, RecoverableBacklinks } from '@nuxtseo/protocol/v1/backlinks';
|
|
5
5
|
import type { ContentBrief, ContentBriefCreateData, ContentBriefListData } from '@nuxtseo/protocol/v1/content';
|
|
6
|
-
import type { SearchAnalyticsData, SearchStatusData } from '@nuxtseo/protocol/v1/gsc';
|
|
6
|
+
import type { IndexingDiagnosticsData, SearchAnalyticsData, SearchStatusData } from '@nuxtseo/protocol/v1/gsc';
|
|
7
7
|
import type { PageInspect, PageScan } from '@nuxtseo/protocol/v1/pages';
|
|
8
8
|
import type { SitePerformanceOverview } from '@nuxtseo/protocol/v1/performance';
|
|
9
9
|
import type { KeywordResearchData, RankingsResearchData, SerpResearchData, StoredResearchOverview } from '@nuxtseo/protocol/v1/research';
|
|
10
|
+
import type { TimelineEntries } from '@nuxtseo/protocol/v1/timeline';
|
|
10
11
|
export declare function renderSites(response: SitesListResponse, selectedSiteId?: string): string;
|
|
11
12
|
export declare function renderUsage(response: AccountUsageResponse): string;
|
|
12
13
|
export declare function renderActions(data: ActionList): string;
|
|
@@ -17,6 +18,7 @@ export declare function renderPageScan(data: PageScan): string;
|
|
|
17
18
|
export declare function renderPerformance(data: SitePerformanceOverview): string;
|
|
18
19
|
export declare function renderSearchStatus(data: SearchStatusData): string;
|
|
19
20
|
export declare function renderSearchAnalytics(data: SearchAnalyticsData): string;
|
|
21
|
+
export declare function renderIndexingDiagnostics(data: IndexingDiagnosticsData): string;
|
|
20
22
|
export declare function renderResearchOverview(data: StoredResearchOverview): string;
|
|
21
23
|
export declare function renderKeywordResearch(data: KeywordResearchData): string;
|
|
22
24
|
export declare function renderSerpResearch(data: SerpResearchData): string;
|
|
@@ -27,5 +29,6 @@ export declare function renderContentBriefCreated(data: ContentBriefCreateData):
|
|
|
27
29
|
export declare function renderContentDecay(data: AuditContentDecay): string;
|
|
28
30
|
export declare function renderDuplicateClusters(data: AuditDuplicateClusters): string;
|
|
29
31
|
export declare function renderLinkOpportunities(data: AuditLinkOpportunities): string;
|
|
32
|
+
export declare function renderTimeline(data: TimelineEntries): string;
|
|
30
33
|
export declare function renderRecoverableBacklinks(data: RecoverableBacklinks): string;
|
|
31
34
|
export declare function renderMentions(data: Mentions): string;
|
package/dist/render.js
CHANGED
|
@@ -151,6 +151,34 @@ export function renderSearchAnalytics(data) {
|
|
|
151
151
|
['Rows', 'rows' in data ? data.rows.length : data.type === 'timeseries' ? data.daily.length : 0],
|
|
152
152
|
]);
|
|
153
153
|
}
|
|
154
|
+
export function renderIndexingDiagnostics(data) {
|
|
155
|
+
if (data.view === 'summary') {
|
|
156
|
+
const indexedPercent = data.totalUrls > 0
|
|
157
|
+
? `${(data.indexed / data.totalUrls * 100).toFixed(1)}%`
|
|
158
|
+
: '0.0%';
|
|
159
|
+
const issues = data.issues
|
|
160
|
+
.filter(issue => issue.count > 0)
|
|
161
|
+
.sort((left, right) => right.count - left.count)
|
|
162
|
+
.map(issue => `${issue.count} ${issue.label} ${issue.severity}`);
|
|
163
|
+
return [
|
|
164
|
+
fields([
|
|
165
|
+
['Known URLs', data.totalUrls],
|
|
166
|
+
['Indexed', data.indexed],
|
|
167
|
+
['Not indexed', Math.max(0, data.totalUrls - data.indexed)],
|
|
168
|
+
['Indexed rate', indexedPercent],
|
|
169
|
+
['As of', data.asOf],
|
|
170
|
+
]),
|
|
171
|
+
...(issues.length > 0 ? ['Issues', ...issues] : []),
|
|
172
|
+
].join('\n');
|
|
173
|
+
}
|
|
174
|
+
if (data.urls.length === 0)
|
|
175
|
+
return 'No Search Console indexing URLs match these filters.';
|
|
176
|
+
return [
|
|
177
|
+
`Search Console indexing URLs (${data.urls.length} of ${data.total})`,
|
|
178
|
+
...data.urls.map(row => `${row.verdict ?? 'unknown'} ${row.coverageState ?? 'unknown'}\n ${row.url}`),
|
|
179
|
+
data.hasMore ? `More URLs available after offset ${data.offset + data.limit}.` : '',
|
|
180
|
+
].filter(Boolean).join('\n');
|
|
181
|
+
}
|
|
154
182
|
export function renderResearchOverview(data) {
|
|
155
183
|
const subject = data.subject
|
|
156
184
|
? fields([
|
|
@@ -242,6 +270,18 @@ export function renderLinkOpportunities(data) {
|
|
|
242
270
|
...data.rows.map(row => `${row.phrase}\n From: ${row.sourceUrl}\n To: ${row.targetUrl}`),
|
|
243
271
|
].join('\n');
|
|
244
272
|
}
|
|
273
|
+
export function renderTimeline(data) {
|
|
274
|
+
if (data.entries.length === 0)
|
|
275
|
+
return 'No Timeline Entries match these filters.';
|
|
276
|
+
return [
|
|
277
|
+
`Timeline (${data.entries.length})`,
|
|
278
|
+
...data.entries.map((entry) => {
|
|
279
|
+
const label = typeof entry.rendered?.label === 'string' ? entry.rendered.label : entry.kind;
|
|
280
|
+
return `${entry.occurredAt} ${entry.severity ?? 'unrated'} ${entry.kind}\n ${label}`;
|
|
281
|
+
}),
|
|
282
|
+
data.nextCursor ? `More Timeline Entries available — pass --cursor ${JSON.stringify(data.nextCursor)}.` : '',
|
|
283
|
+
].filter(Boolean).join('\n');
|
|
284
|
+
}
|
|
245
285
|
export function renderRecoverableBacklinks(data) {
|
|
246
286
|
if (data.items.length === 0)
|
|
247
287
|
return 'No recoverable Backlinks. Every stored inbound link resolves.';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nuxtseo/cli",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.4",
|
|
5
5
|
"description": "Command line interface for the NuxtSEO public API.",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://nuxtseo.com/pro",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"@clack/prompts": "^1.7.0",
|
|
35
35
|
"citty": "^0.2.2",
|
|
36
36
|
"pathe": "^2.0.3",
|
|
37
|
-
"@nuxtseo/sdk": "^0.1.
|
|
37
|
+
"@nuxtseo/sdk": "^0.1.4"
|
|
38
38
|
},
|
|
39
39
|
"optionalDependencies": {
|
|
40
40
|
"@napi-rs/keyring": "^1.3.0"
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"@types/node": "^26.2.0",
|
|
45
45
|
"publint": "^0.3.24",
|
|
46
46
|
"typescript": "npm:typescript-native-bridge@6.0.3-bridge.10.tsgo.7.0.2",
|
|
47
|
-
"@nuxtseo/protocol": "0.1.
|
|
47
|
+
"@nuxtseo/protocol": "0.1.4"
|
|
48
48
|
},
|
|
49
49
|
"publishConfig": {
|
|
50
50
|
"access": "public"
|
|
@@ -26,6 +26,7 @@ report `cached`.
|
|
|
26
26
|
|
|
27
27
|
`search status` reads stored connection state. It never waits for Google.
|
|
28
28
|
`search analytics` reads Search Console rows through the public API.
|
|
29
|
+
`search indexing` reads retained URL Inspection coverage through the public API.
|
|
29
30
|
|
|
30
31
|
## Get the binary
|
|
31
32
|
|
|
@@ -115,6 +116,7 @@ handling failures, read [CLI protocol](references/protocol.md).
|
|
|
115
116
|
| `performance` | Site performance overview | Medians for perf, a11y, SEO, LCP, TBT, CLS |
|
|
116
117
|
| `search status` | Stored Search Console connection | Provider free |
|
|
117
118
|
| `search analytics <pages\|keywords>` | Search Console Page or query rows | `--period`, `--limit`, `--page`, `--search` |
|
|
119
|
+
| `search indexing <summary\|urls>` | Retained URL Inspection coverage | `summary` returns indexed counts; `urls` supports `--issue`, `--status`, `--limit`, `--offset` |
|
|
118
120
|
| `research overview` | Stored Site and competitor research | Metrics, history, gaps, and quick wins |
|
|
119
121
|
| `research keywords <topic>` | Live keyword ideas | Volume, difficulty, intent, and cost data |
|
|
120
122
|
| `research serp <keyword>` | Live SERP snapshot | Results, features, and fetch time |
|
|
@@ -130,11 +132,11 @@ handling failures, read [CLI protocol](references/protocol.md).
|
|
|
130
132
|
`page inspect` and `page scan` take an absolute URL, for example
|
|
131
133
|
`https://example.com/about`.
|
|
132
134
|
|
|
133
|
-
`--help --json` returns a `CliHelp` value for one command level
|
|
134
|
-
`arguments`,
|
|
135
|
-
|
|
136
|
-
example `nuxtseo actions list --help --json`. Use this instead of
|
|
137
|
-
flag, and prefer the table above for anything it already answers.
|
|
135
|
+
`--help --json` returns a `CliHelp` value for one command level. It separates
|
|
136
|
+
positional `arguments`, command-specific `localOptions`, inherited
|
|
137
|
+
`globalOptions`, and `subcommands`. To learn a subcommand's own flags, ask it
|
|
138
|
+
directly, for example `nuxtseo actions list --help --json`. Use this instead of
|
|
139
|
+
guessing a flag, and prefer the table above for anything it already answers.
|
|
138
140
|
|
|
139
141
|
## The triage loop
|
|
140
142
|
|
|
@@ -18,7 +18,8 @@ Protocol failure, still on stdout, with recovery details on stderr:
|
|
|
18
18
|
|
|
19
19
|
Read `data`. The CLI does not unwrap, rename, rank, or enrich fields.
|
|
20
20
|
|
|
21
|
-
Local outcomes have no server body. They carry
|
|
21
|
+
Local outcomes have no server body. They carry one tag and their own schema
|
|
22
|
+
version. `CliHelp` uses version 2. The other values use version 1.
|
|
22
23
|
|
|
23
24
|
| `_tag` | Written by |
|
|
24
25
|
| --- | --- |
|