@clize/clize 0.28.1 → 0.29.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.
@@ -1,28 +1,180 @@
1
1
  ---
2
2
  name: clize-seo
3
3
  description: >-
4
- Read what `clize seo` returns and decide what to do about it. The commands give facts —
4
+ Run and read an SEO/GEO analysis with `clize seo`. The commands give facts —
5
5
  keyword metrics, who occupies a results page, your positions, where your traffic comes
6
- from, what Search Console is showing you. This skill is the judgment layer: which keywords
7
- are worth attacking at your authority level, what a results page is actually telling you,
8
- where to place content so it gets found, how to write so AI engines can quote you, and how
9
- to read a `seo check` without fooling yourself.
10
- Triggers: "should I go after this keyword", "why aren't we ranking", "what does this SERP
11
- mean", "read my seo check", "how do I get cited by ChatGPT", "write this page for AI search",
12
- "where should I publish this", "is our SEO working".
6
+ from, what Search Console is showing you. This skill is the judgment layer: where the
7
+ keywords to test come from in the first place, how big and how expensive one analysis is,
8
+ what it has to deliver, which keywords are worth attacking at your authority level, what a
9
+ results page is actually telling you, where to place content so it gets found, how to write
10
+ so AI engines can quote you, and how to read a `seo check` without fooling yourself.
11
+ Triggers: "do keyword research", "find keyword opportunities", "should I go after this
12
+ keyword", "why aren't we ranking", "what does this SERP mean", "read my seo check", "how do
13
+ I get cited by ChatGPT", "write this page for AI search", "where should I publish this",
14
+ "is our SEO working".
13
15
  ---
14
16
 
15
- # Reading and acting on `clize seo`
17
+ # Running and reading `clize seo`
16
18
 
17
19
  The commands are deliberately dumb: they compress facts, they never advise. `serp` will tell
18
20
  you a page is a `listicle_window`; it will not tell you to pitch those listicles. That call is
19
21
  yours, and this file is how to make it.
20
22
 
21
- Run `clize seo <cmd> --help` for exact flags. Everything below assumes you have the output.
23
+ Run `clize seo <cmd> --help` for exact flags.
24
+
25
+ **§1–§3 are how to run an analysis. §4–§8 are how to read what comes back.** If you are here
26
+ because someone asked for "keyword opportunities", start at §1 — the most common failure of
27
+ this product is not misreading a number, it is testing a keyword set that was never enumerated.
28
+
29
+ ---
30
+
31
+ ## 1. Where the seeds come from
32
+
33
+ Every command except `competitors` is a **verifier**: you hand it words, it prices them. None
34
+ of them will hand you a word you did not think of — except `competitors`, and the `newQueries`
35
+ that come back from `check`. So the quality ceiling of the whole analysis is set before you
36
+ spend a cent, by how the candidate list was built.
37
+
38
+ **Enumerate the list. Do not recall it.** A list you produced by thinking hard about the
39
+ product is a sample of your own memory, and it will be small, English-only, and biased toward
40
+ words you already believed in.
41
+
42
+ Measured case (kunavo.com, 2026-08-31). Round one: 19 keywords written down off the top of the
43
+ head. Output: six thematic directions, zero rows anyone could start work on. Round two: a
44
+ 37-keyword matrix built by enumeration, same site, same day. Output included `openrouter
45
+ alternative` at KD 1 with eight named roundups to pitch, a German pricing cluster, a Japanese
46
+ error-message query at 2,900/month that turned out to be a pure-UGC wall (worth knowing — it
47
+ killed a page that was about to be written), and two payment long-tails with no recorded volume
48
+ that Search Console showed sitting at positions 4.5 and 8. **None of those exist in the 19.**
49
+
50
+ ### 1.1 Competitor teardown — the only command that produces words
51
+
52
+ ```
53
+ clize seo competitors rival-one.com rival-two.com --limit 25
54
+ ```
55
+
56
+ Two or three competitors × `--limit 25` is **50–75 candidates for about $0.09 a domain**, and
57
+ they are pre-filtered by the only filter that matters: somebody is already ranking on them.
58
+ Read `topKeywords[].keyword`, ignore their brand terms, keep everything else as a candidate.
59
+
60
+ Pick competitors that are *your size or one step up*. Tearing down a category leader gives you
61
+ their head terms, which you cannot have. Tearing down the site that ranks #4 on the queries you
62
+ care about gives you the long tail that is actually reachable.
63
+
64
+ Run this **first**, before you write down a single keyword of your own. It anchors the list in
65
+ the market instead of in your head.
66
+
67
+ ### 1.2 Capability-surface enumeration — cross the axes, don't brainstorm
68
+
69
+ Ask: *what can this product actually absorb a visitor for?* Then find the axes of that surface
70
+ and take the cross-product. This is mechanical, and mechanical is the point.
71
+
72
+ Common axes, and what a row looks like:
73
+
74
+ | pattern | axis A | axis B | rows you get |
75
+ | --- | --- | --- | --- |
76
+ | Error-message capture | the exact strings your users see | each UI language you ship | `メッセージストリームでエラー`, `error in message stream` |
77
+ | Payment/checkout tail | payment method (alipay, wechat, sepa, pix…) | your category noun | `alipay checkout api`, `pix payment link` |
78
+ | Competitor displacement | each competitor brand | `alternative` / `vs <you>` / `pricing` / `review` | `openrouter alternative` |
79
+ | New-thing window | model / API / spec names released in the last 90 days | `api`, `pricing`, `how to use` | `seedance api pricing` |
80
+ | Locale × head term | your two or three head terms | each market you can serve | `de-DE` pricing cluster |
81
+
82
+ Rules for the matrix:
83
+
84
+ - **Write every cell, then filter.** Filtering while enumerating is just recalling again.
85
+ - **Do the non-English cells.** They are where the low-competition rows are, and they are the
86
+ cells a memory-driven list always skips. Supported markets: `en-US, en-GB, en-CA, en-AU,
87
+ de-DE, fr-FR, es-ES, ja-JP` — anything else is a 400, so do not build rows you cannot price.
88
+ - **Cells you can't serve are not candidates.** Ranking for a query you cannot answer is a
89
+ bounce, not a win.
90
+ - 30–100 cells is a normal matrix. If you have twelve, you have not found your axes yet.
91
+
92
+ ### 1.3 Search Console feedback — free, and it does not repeat your bias
93
+
94
+ `clize seo check` returns `gsc.newQueries`: queries Google is already showing you for that are
95
+ not on your list. This is Google telling you what it thinks you are relevant for, which is
96
+ information no amount of enumeration produces. It costs nothing. Fold it back into the matrix
97
+ every round — it is the loop that makes the second analysis better than the first.
98
+
99
+ ---
100
+
101
+ ## 2. The shape of one analysis
102
+
103
+ A cold start is a funnel, and the funnel has a known size and a known price.
104
+
105
+ ```
106
+ 30–100 candidates (§1: competitor teardown + capability matrix)
107
+ → seo keywords price the whole list in one batched call
108
+ → drop `wall`, keep `attackable` + interesting `no_volume` (§5)
109
+ → 10–20 survivors
110
+ → seo serp each survivor the SERP check that KD cannot replace (§4)
111
+ → 10–20 rows in the deliverable table (§3)
112
+ → seo check --keywords <the survivors> the baseline you measure against
113
+ ```
114
+
115
+ ### What it costs (measured, current version)
116
+
117
+ | step | price | note |
118
+ | --- | --- | --- |
119
+ | `seo keywords`, 40 words | **~$0.10** | one batched call; per-word cost is negligible next to the fixed cost, so **always send the whole list at once** |
120
+ | `seo competitors`, 3 domains × 25 | **~$0.28** | the cheapest words you will ever buy |
121
+ | `seo serp`, one keyword | **~$0.02** | 10–20 of these is $0.20–0.40 |
122
+ | `seo check` | **free**, plus ~$0.005/word to price words it has never priced | the metrics are reused for 30 days, so a re-check costs nothing |
123
+
124
+ **A complete cold start runs about $0.70–1.00.** The default account cap is **$5/month**, so a
125
+ careful analysis fits inside it four or five times over.
126
+
127
+ Two behaviours follow, and both matter:
128
+
129
+ - **Do not sample to save money.** Checking 12 of 40 keywords saves about six cents and costs
130
+ you the analysis. There is no version of this work where a smaller keyword batch is the right
131
+ economy. Price the whole list.
132
+ - **Do not run blind into the wall either.** Every response carries a `budget` block
133
+ (`capUsd` / `spentThisMonth` / `remainingUsd`). Read it. If a call is refused with a 429, the
134
+ message names the exact flag to raise the cap — `--cap <usd>` on any `clize seo` command,
135
+ which both raises it and runs the command. Passing the flag *is* the consent; there is no
136
+ second confirmation, and there is no support ticket.
137
+ - `check --budget` is a **per-domain** cap and is a different number from `--cap`. If you set a
138
+ domain budget above the account cap, `check` says so in `notes` — you would hit the account
139
+ wall first.
140
+
141
+ > If you are carrying a mental model where `seo check` cost a dollar or two: that was the old
142
+ > check, which scraped a full SERP for every tracked keyword every round. It doesn't any more.
143
+ > Measurement is free; the exact-position scrape is now a deliberate single act (`seo serp`).
22
144
 
23
145
  ---
24
146
 
25
- ## 1. Reading a results page (`seo serp`)
147
+ ## 3. What an analysis delivers
148
+
149
+ **The deliverable is a table. Prose is the footnote, not the product.**
150
+
151
+ A finished analysis is a keyword worksheet, one row per keyword, where every row can be handed
152
+ to someone as a unit of work without further interpretation:
153
+
154
+ | keyword | locale | sv | kd | serp verdict | intent | target page | format | priority |
155
+ | --- | --- | --- | --- | --- | --- | --- | --- | --- |
156
+ | openrouter alternative | en-US | 1,300 | 1 | listicle_window | commercial | /compare/openrouter/ | comparison + pitch 8 roundups | P0 |
157
+ | メッセージストリームでエラー | ja-JP | 2,900 | 0 | definition_wall (UGC) | informational | — | skip: Reddit/Zenn own it | — |
158
+
159
+ - **`target page` and `format` are part of the row.** "This keyword is good" is not a unit of
160
+ work; "write /compare/openrouter/ as a comparison page and pitch these eight roundups" is.
161
+ - **Rows you decided against stay in the table**, with the reason. That is what stops the next
162
+ session from re-buying the same keyword — and a `skip` row with a reason is a real finding.
163
+ - **Write the table to a file.** Cross-session handoff is the file, not a retelling in chat. A
164
+ summary of a table is not a table.
165
+ - **Narrative goes underneath as footnotes.** Two or three lines about what the pattern means.
166
+ Not six paragraphs of themes.
167
+
168
+ ### The pass/fail test
169
+
170
+ If what you produced is a set of *directions* or *themes*, or the table has fewer than ten
171
+ actionable rows, **the analysis failed and the fix is upstream, in §1**. Do not write it up.
172
+ Go back and enumerate more cells. This is exactly what happened in round one of the kunavo
173
+ dogfood: six well-argued themes, and not one row anybody could start on.
174
+
175
+ ---
176
+
177
+ ## 4. Reading a results page (`seo serp`)
26
178
 
27
179
  `verdict` compresses **who occupies the page**. Four values, and what each one means for
28
180
  whether you can get in:
@@ -49,6 +201,11 @@ keyword returns `official_wall`: three of the top five are Stripe's own properti
49
201
  difficulty score on a page nobody can enter is not an opportunity.** Never pick keywords from
50
202
  `band` alone; run `serp` on anything you are about to invest a page in.
51
203
 
204
+ The reverse trap is just as expensive: a Japanese error-message query at 2,900/month and KD 0
205
+ looks like a gift until `serp` shows the page is wall-to-wall Reddit, Zenn and Qiita threads.
206
+ High volume plus zero difficulty plus a pure-UGC page means *the demand is real and it is not
207
+ available to you*.
208
+
52
209
  ### The classifier does not judge intent — you do
53
210
 
54
211
  `ai agent deployment` returns `open`. Read the items and you find they are all about deploying
@@ -62,25 +219,40 @@ before committing to a keyword**, whatever the verdict says.
62
219
  An AI Overview sits above the organic results and answers the query in place. Position 3 under
63
220
  an AI Overview is worth much less than position 3 without one, and some of your impressions will
64
221
  never become clicks no matter what you do. Note it, factor it into expectations, and lean harder
65
- on being *quotable* (§4) than on being *ranked*.
222
+ on being *quotable* (§7) than on being *ranked*.
66
223
 
67
224
  ---
68
225
 
69
- ## 2. Picking keywords at your authority level (`seo keywords`)
226
+ ## 5. Picking keywords at your authority level (`seo keywords`)
70
227
 
71
- `band` is a mechanical bucket of keyword difficulty: `attackable` (<10), `stretch` (10–30),
72
- `wall` (>30), `no_volume`.
228
+ `band` is a mechanical bucket: `attackable` (KD <10), `stretch` (10–30), `wall` (>30),
229
+ `no_volume`, `no_data`.
73
230
 
74
231
  For a site with near-zero authority (new domain, few referring domains):
75
232
 
76
- - Attack `attackable` **that also pass the SERP check** (§1).
233
+ - Attack `attackable` **that also pass the SERP check** (§4).
77
234
  - `stretch` is a 6–12 month bet; take at most one or two, and only if the SERP is a
78
235
  `listicle_window` you can parasitize meanwhile.
79
236
  - `wall` is not a plan. Skip it.
80
- - `no_volume` is not automatically worthless: a keyword with no recorded volume whose SERP is
81
- already full of category roundups is a **pre-emergence** signal — the searches exist, the
82
- keyword tools have not caught up. `email api for ai agents` had no volume and a
83
- `listicle_window` with four roundups on it. That is a keyword worth an early page.
237
+
238
+ ### `no_data` and `no_volume` mean opposite things
239
+
240
+ They used to be one value. They are not one thing:
241
+
242
+ - **`no_data`** — we have no volume figure for this keyword. Either it was never priced, or it
243
+ was priced and the upstream has no row for it. It is an **absence of data** and it says
244
+ nothing whatsoever about demand. Never report it as "nobody searches for this."
245
+ - **`no_volume`** — it *was* priced and the volume really is 0. That is a **signal**, and often
246
+ a valuable one: a keyword the tools have not caught up with. `email api for ai agents` had no
247
+ volume and a `listicle_window` with four roundups on it. On kunavo, two payment long-tails
248
+ came back at volume 0 and Search Console showed them at positions 4.5 and 8 with real
249
+ impressions — **people were already arriving on words the keyword tool scored as empty.**
250
+ That configuration has a name in `check` output: `pre_emergence` (§8).
251
+
252
+ So: a `no_volume` row whose SERP is already full of category roundups is worth an early page.
253
+ A `no_data` row is worth *pricing*, not deciding on.
254
+
255
+ ### `--ai` is a different unit
84
256
 
85
257
  `--ai` adds `aiSv`, the volume inside AI engines. **It is a different unit from `sv`.** Measured:
86
258
  `agent mail` is 5,400 on Google and 125 in AI engines; `ai email agent` is 140 and 5. Compare a
@@ -89,7 +261,7 @@ the same sentence as if they were the same quantity, and never add them.
89
261
 
90
262
  ---
91
263
 
92
- ## 3. Where to place content
264
+ ## 6. Where to place content
93
265
 
94
266
  Priority order, most effective first for a low-authority site:
95
267
 
@@ -105,7 +277,7 @@ Priority order, most effective first for a low-authority site:
105
277
 
106
278
  ---
107
279
 
108
- ## 4. Writing so AI engines can quote you
280
+ ## 7. Writing so AI engines can quote you
109
281
 
110
282
  Retrieval-augmented engines quote passages, not pages. What survives extraction:
111
283
 
@@ -121,21 +293,24 @@ Retrieval-augmented engines quote passages, not pages. What survives extraction:
121
293
 
122
294
  ---
123
295
 
124
- ## 5. Reading a `seo check`
296
+ ## 8. Reading a `seo check`
125
297
 
126
298
  ### `rank`
127
299
 
128
- `rank.source` is always `"gsc"`: positions come from Search Console, free, and `check` makes no
129
- upstream calls at all. Read them accordingly.
300
+ `rank.source` is always `"gsc"`: positions come from Search Console. Measurement makes no
301
+ upstream calls; the only thing `check` may pay for is pricing keywords it has never priced.
130
302
 
131
303
  - `position` is the **impression-weighted average over `rank.window`**, not your rank at a moment.
132
304
  A 62.4 means "across the window, the average slot Google gave you was ~62". Two consequences:
133
- a single good day barely moves it, and it is **not comparable** to a scraped SERP position
134
- (or to any number a pre-0.28.0 check reported).
305
+ a single good day barely moves it, and it is **not comparable** to a scraped SERP position.
135
306
  - `delta` is **positive when you moved up** (the number got smaller), measured against
136
307
  `rank.prevWindow` — the equal-length window right before this one. `movers` shifted by 3+;
137
308
  anything smaller is averaging noise. `series` is weekly, newest first; weeks with no
138
309
  impressions are simply absent, so read the dates, not the spacing.
310
+ - Each row also carries **`sv` and `kd` next to the Search Console numbers**. That is the whole
311
+ point of the row: demand and delivery side by side. A row with `sv: 27100` and `position: 74`
312
+ is a completely different situation from `sv: 0` and `position: 4.5`, and you should never
313
+ have to go find the second number somewhere else to see it.
139
314
  - `unseen` lists the keywords on your list that **Search Console did not see this window**.
140
315
  This is not "not ranking" — GSC only has a row once you get impressions. It is the honest
141
316
  statement "no data yet", and it costs nothing to say. **If you need one of these words' real
@@ -148,6 +323,35 @@ upstream calls at all. Read them accordingly.
148
323
  - **Competitor positions are not in `check`.** `--competitors` is remembered configuration only;
149
324
  a head-to-head on one keyword is `seo serp <keyword>`, where the whole page comes back at once.
150
325
 
326
+ ### `rank.signals` — the cross-source read, done for you
327
+
328
+ `signals` is where the three sources are put side by side and labelled. It is **fact
329
+ compression, not advice** — the same kind of thing as `serp`'s `verdict`. Every row carries the
330
+ numbers the label was derived from (`sv`, `kd`, `position`, `impressions`, `clicks`), so you can
331
+ overrule it. Three forms:
332
+
333
+ | form | the configuration | how to read it |
334
+ | --- | --- | --- |
335
+ | `pre_emergence` | priced volume is **0**, and Search Console shows real impressions anyway | The demand exists and the keyword tools have not caught up. On a low-authority site this is the cheapest entry you will find: nobody is optimising for a keyword the tools score as empty. Write the page. |
336
+ | `authority_limited` | many impressions, position 50+, **zero clicks** | Google is offering you the keyword surface and withholding the position. This is an authority bottleneck, not a content problem — **another page on the same theme will not move it.** Go do §6.1. |
337
+ | `demand_no_surface` | real search volume, and Search Console gave you **no impressions at all** this window | The mirror image. Google is not even putting you on the shelf. That is a **discovery** question (is this reachable at your authority? what occupies it? → `seo serp`), not a measurement one. Running the measurement again will not answer it. |
338
+
339
+ An empty `signals` array is not a failure; it means no keyword on your list is currently in one
340
+ of these three shapes.
341
+
342
+ There is deliberately **no** `data_conflict` form. That would need two independent position
343
+ sources to disagree, and `check` has only one (Search Console). If you want the scraped-position
344
+ comparison, that is an explicit `seo serp <keyword>` — and when the two disagree, believe
345
+ Search Console: it is a 28-day average of what Google actually served, while a scrape is one
346
+ personalised fetch of a rotating page.
347
+
348
+ ### `keywords.byBand`
349
+
350
+ Counts **only keywords that have been priced**. Words on your list that have never been priced
351
+ are excluded and the gap is stated in `notes` — an empty bucket is an honest empty, not a
352
+ fabricated `no_volume`. `no_data` inside `byBand` means "we asked and the upstream has no row
353
+ for it", which is a genuine finding about a very long-tail word.
354
+
151
355
  ### `traffic`
152
356
 
153
357
  - `ai` is always present, **including when it is all zeros — zero is the finding.** First
@@ -158,46 +362,40 @@ upstream calls at all. Read them accordingly.
158
362
 
159
363
  ### `gsc`
160
364
 
161
- - `newQueries` is the feedback loop closing: Google is telling you which queries it *considers*
162
- you relevant for. Queries you never targeted showing real impressions are the most valuable
163
- output of the whole command.
164
- - **Impressions with zero clicks at position 60–90 is not a content problem.** It means Google
165
- is offering you the keyword surface and withholding the position. That is an authority
166
- bottleneck; writing another page on the same theme will not move it. Go do §3.1.
365
+ - `newQueries` is the feedback loop closing (§1.3): Google telling you which queries it
366
+ *considers* you relevant for. Queries you never targeted showing real impressions are the most
367
+ valuable output of the whole command. Fold them into the matrix.
167
368
  - `gsc: null` is not an error. Read `notes` — usually it means the service account has not been
168
369
  added to that property yet.
169
370
 
170
371
  ### The one rule that ties it together
171
372
 
172
- When `rank` puts you at ~70 on a keyword, `gsc` shows hundreds of impressions and almost no
173
- clicks on it, and `serp` says that page is a `listicle_window` — that is a complete, actionable
373
+ When a row shows `sv` in the thousands, `position` around 70, hundreds of impressions and almost
374
+ no clicks, and `serp` on that keyword says `listicle_window` — that is a complete, actionable
174
375
  picture: **the demand exists, the position is authority-limited, and the way in is the roundups,
175
- not another page.** This exact configuration is what clize.ai looked like on 2026-08-30.
176
-
177
- The mirror image is a word sitting in `unseen` round after round: no impressions at all means
178
- Google is not even offering you the surface. That is a **discovery** question (is this word
179
- reachable at your authority? what occupies it? — `seo serp`), not a measurement one. Running
180
- the measurement again will not answer it.
376
+ not another page.** `check` now labels the middle of that sentence for you (`authority_limited`);
377
+ the roundups still come from a deliberate `seo serp`.
181
378
 
182
379
  ---
183
380
 
184
- ## 6. Two playbooks
381
+ ## 9. Two playbooks
185
382
 
186
- **New site, cold start.** `seo keywords` on your seed set drop `wall`, keep `attackable` and
187
- interesting `no_volume` → `seo serp` each survivordiscard `official_wall` and
188
- `definition_wall` for `listicle_window`, collect `parasiteTargets` and start outreach write
189
- one page per surviving keyword following §4deploy `seo check --keywords <the survivors>
190
- --brand <you> --competitors <the two you keep seeing>`. That first check is your baseline.
383
+ **New site, cold start.** `seo competitors <2–3 rivals>` build the capability matrix (§1.2)
384
+ merge into 30–100 candidates → `seo keywords <the whole list>` in one call drop `wall`, keep
385
+ `attackable` and interesting `no_volume` `seo serp` each survivordiscard `official_wall`
386
+ and `definition_wall` for `listicle_window`, collect `parasiteTargets`write the table (§3)
387
+ write one page per P0 row following §7 deploy → `seo check --keywords <the survivors>
388
+ --brand <you>`. That first check is your baseline. Total: about $1.
191
389
 
192
- **Recheck.** `clize seo check` with no flags (it remembers everything) → read `movers` first,
193
- then `traffic.ai`, then `gsc.newQueries`, then what is still in `unseen` decide: keep waiting,
194
- add the new queries to the tracked list, or change approach. The check is free, so nothing stops
195
- you running it — but **SEO is a weeks-to-months system, and the window it measures is 4 weeks
196
- wide: checking daily just re-reads the same window.** Every two weeks is plenty.
390
+ **Recheck.** `clize seo check` with no flags (it remembers everything) → read `signals` first,
391
+ then `movers`, then `traffic.ai`, then `gsc.newQueries` fold the new queries into the matrix
392
+ and decide: keep waiting, extend the tracked list, or change approach. **SEO is a
393
+ weeks-to-months system and the window it measures is 4 weeks wide: checking daily just re-reads
394
+ the same window.** Every two weeks is plenty.
197
395
 
198
396
  ---
199
397
 
200
- ## 7. Calibration discipline
398
+ ## 10. Calibration discipline
201
399
 
202
400
  Every measurement here is a sample, not a census. Rank sampling is one fetch of a personalized,
203
401
  rotating results page. Traffic is adaptively sampled. AI-engine visibility measured by any tool