@letterstory/cli 0.176.101 → 0.176.103
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 +1 -0
- package/lib/cli.mjs +2 -1
- package/lib/commands/domains.mjs +36 -13
- package/lib/commands/replicate.mjs +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -144,6 +144,7 @@ letterstory domains # every domain y
|
|
|
144
144
|
letterstory domains scan # brainstorms the searches in your space, free .com/.org (no charge)
|
|
145
145
|
letterstory domains scan "nano banana pro" # or the phrases you give
|
|
146
146
|
letterstory domains scan "nano banana pro" --tld com,org,ai,xyz --expand space
|
|
147
|
+
letterstory domains scan --domain olapdatabase.com # whether a domain you have in mind is free
|
|
147
148
|
letterstory domains buy nanobananaprofree.com --dry-run # the price and whose account pays
|
|
148
149
|
letterstory domains buy nanobananaprofree.com --yes # buys it (spends money; domains:write)
|
|
149
150
|
```
|
package/lib/cli.mjs
CHANGED
|
@@ -87,7 +87,7 @@ import {
|
|
|
87
87
|
import { fetchParkedSections, withoutParked } from "./parked.mjs";
|
|
88
88
|
|
|
89
89
|
// Matches cli/package.json; publish-cli.yml rewrites both to the published version.
|
|
90
|
-
export const VERSION = "0.176.
|
|
90
|
+
export const VERSION = "0.176.103";
|
|
91
91
|
|
|
92
92
|
/** The exit code for a gate refusal (CARD_REQUIRED, PAYMENT_FAILED, OUT_OF_TOKENS): 1 is a plain error. */
|
|
93
93
|
export const EXIT_PAYMENT_REQUIRED = 3;
|
|
@@ -1983,6 +1983,7 @@ Domains (the domains you hold, and free ones that match what people search):
|
|
|
1983
1983
|
[--no-modifiers] [--market US] [--limit <n>]
|
|
1984
1984
|
Free .com/.org domains on what people search in your
|
|
1985
1985
|
space (brainstormed, or the phrases given), ranked
|
|
1986
|
+
domains scan --domain <domain> [--domain …] Whether each domain is free (a bare name: .com and .org)
|
|
1986
1987
|
domains buy <domain> --dry-run | --yes The price and whose account pays; --yes buys it
|
|
1987
1988
|
domains plan <domain> [--phrase "<search>"] [--searches <n>] [--version <version>] [--no-write]
|
|
1988
1989
|
The most strategic site for the domain, every version
|
package/lib/commands/domains.mjs
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
// letterstory domains [list]
|
|
6
6
|
// letterstory domains scan brainstorms the searches in your space, checks .com and .org
|
|
7
7
|
// letterstory domains scan "nano banana pro" ["ai headshots" …] [--tld com,org,ai] [--expand none|searches|space]
|
|
8
|
+
// letterstory domains scan --domain olapdatabase.com [--domain …] whether each is free (a bare name: .com and .org)
|
|
8
9
|
// letterstory domains buy nanobananaprofree.com --dry-run the price and whose account pays; buys nothing
|
|
9
10
|
// letterstory domains buy nanobananaprofree.com --yes buys it (spends money; domains:write)
|
|
10
11
|
// letterstory domains plan bestaidatalabs.com [--phrase "best ai data labs"] [--searches 880] [--version comparison]
|
|
@@ -22,6 +23,13 @@ export const ARGS = {
|
|
|
22
23
|
// `domains scan "nano banana pro" ["ai headshots" …]` — each positional is one phrase; none brainstorms your space.
|
|
23
24
|
scan_domains: {
|
|
24
25
|
phrases: { value: (flags, positionals) => (positionals.length ? positionals : undefined) },
|
|
26
|
+
// `--domain olapdatabase.com` (repeatable or comma-separated): checked as it is; alone, it is only that check.
|
|
27
|
+
domains: {
|
|
28
|
+
value: (flags) => {
|
|
29
|
+
const domains = flagCsv(flags.domain).map(stripScheme);
|
|
30
|
+
return domains.length ? domains : undefined;
|
|
31
|
+
},
|
|
32
|
+
},
|
|
25
33
|
// `--tld com,org` or `--tld com --tld org`.
|
|
26
34
|
tlds: {
|
|
27
35
|
value: (flags) => {
|
|
@@ -205,6 +213,7 @@ async function domainsLaunch(ctx) {
|
|
|
205
213
|
}
|
|
206
214
|
|
|
207
215
|
const STATUS_MARK = { available: "free", taken: "·", unknown: "?", unchecked: " " };
|
|
216
|
+
const NAMED_MARK = { available: "free", taken: "taken", unknown: "?" };
|
|
208
217
|
|
|
209
218
|
async function domainsScan(ctx) {
|
|
210
219
|
const { client, flags, io } = ctx;
|
|
@@ -218,20 +227,34 @@ async function domainsScan(ctx) {
|
|
|
218
227
|
? "not sold here"
|
|
219
228
|
: `$${p.purchase_usd}${p.purchasable ? "" : " (over cap)"}`;
|
|
220
229
|
const lines = [];
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
lines.push(
|
|
225
|
-
|
|
226
|
-
|
|
230
|
+
const named = r.named ?? [];
|
|
231
|
+
if (named.length) {
|
|
232
|
+
const rows = new Map(r.domains.map((d) => [d.domain, d]));
|
|
233
|
+
lines.push("Domains you named:");
|
|
234
|
+
for (const n of named) {
|
|
235
|
+
lines.push(
|
|
236
|
+
` ${NAMED_MARK[n.status].padEnd(6)} ${n.domain.padEnd(32)} ${price(rows.get(n.domain)?.price)}`.trimEnd()
|
|
237
|
+
);
|
|
238
|
+
}
|
|
227
239
|
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
lines.push(
|
|
233
|
-
|
|
234
|
-
|
|
240
|
+
// Named alone, the check is the whole answer: there was no scan of searches to print.
|
|
241
|
+
if (!named.length || r.phrases.length) {
|
|
242
|
+
if (named.length) lines.push("");
|
|
243
|
+
if (r.space) lines.push(`Searches brainstormed for your space: ${r.space}`);
|
|
244
|
+
lines.push(`Free domains (${r.available} of ${r.checked} checked, searches in ${r.market}):`);
|
|
245
|
+
for (const d of r.domains) {
|
|
246
|
+
lines.push(
|
|
247
|
+
` ${String(d.score).padStart(5)} ${d.domain.padEnd(32)} ${d.match.padEnd(8)} ${searches(d.monthly_searches).padStart(8)}/mo ${d.phrase} ${price(d.price)}`
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
if (!r.domains.length) lines.push(" None free. Try phrases of your own, --expand space, or more --tld.");
|
|
251
|
+
lines.push("", `Exact match on each TLD (free / · taken):`);
|
|
252
|
+
lines.push(` ${"".padEnd(30)} ${"searches".padStart(8)} ${r.tlds.map((t) => t.padEnd(5)).join("")}`);
|
|
253
|
+
for (const row of r.coverage) {
|
|
254
|
+
lines.push(
|
|
255
|
+
` ${row.phrase.slice(0, 30).padEnd(30)} ${searches(row.monthly_searches).padStart(8)} ${row.cells.map((c) => STATUS_MARK[c.status].padEnd(5)).join("")}`
|
|
256
|
+
);
|
|
257
|
+
}
|
|
235
258
|
}
|
|
236
259
|
for (const note of r.notes) lines.push(`Note: ${note}`);
|
|
237
260
|
return lines.join("\n");
|
|
@@ -130,7 +130,7 @@ function limitsLines(l) {
|
|
|
130
130
|
function usageLine(u) {
|
|
131
131
|
if (!u) return [];
|
|
132
132
|
const parts = [
|
|
133
|
-
u.
|
|
133
|
+
u.run_minutes ? `${u.run_minutes} min running` : null,
|
|
134
134
|
u.pages_captured ? `${u.pages_captured} pages` : null,
|
|
135
135
|
u.preview_hours ? `${u.preview_hours} preview hours` : null,
|
|
136
136
|
u.media_bytes ? `${(u.media_bytes / 1e6).toFixed(1)} MB media` : null,
|