@whereamimentioned/cli 0.0.0-stage → 0.1.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 +318 -2
- package/dist/index.js +5468 -0
- package/package.json +56 -3
package/README.md
CHANGED
|
@@ -1,3 +1,319 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @whereamimentioned/cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`wam`: track and score your brand's visibility in AI answers, from the terminal and from CI.
|
|
4
|
+
|
|
5
|
+
whereamimentioned asks AI assistants the questions your buyers ask, checks whether your brand is in
|
|
6
|
+
the answers, and scores how often you show up against the competitors that appear instead. The CLI
|
|
7
|
+
is the same product from a shell: free site checks that need no account, sign-in, scans and reports,
|
|
8
|
+
a gate for CI, and the installer for the MCP server.
|
|
9
|
+
|
|
10
|
+
Full documentation: https://whereamimentioned.com/docs/cli
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
npx @whereamimentioned/cli --help
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Or install it once:
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
npm install -g @whereamimentioned/cli
|
|
22
|
+
wam --help
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Always install or run it by the scoped package name. The unscoped `wam` on npm is an unrelated
|
|
26
|
+
package. The binary is `wam`, with `wamctl` as an alias for machines where `wam` is already taken on
|
|
27
|
+
the PATH. Requires Node 20.19 or newer.
|
|
28
|
+
|
|
29
|
+
## Free site checks, no account needed
|
|
30
|
+
|
|
31
|
+
Seven commands work with no account, no key and no config, from a cold `npx`. They spend no credits.
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
wam site check-crawlers <url> which AI crawlers your robots.txt lets in
|
|
35
|
+
wam site validate-llms-txt <url> score and findings for an existing llms.txt
|
|
36
|
+
wam site generate-llms-txt <url> [--full] [-o <file>] crawl the site and write an llms.txt
|
|
37
|
+
wam site generate-sitemap <url> [-o <file>] crawl the site and write a sitemap.xml
|
|
38
|
+
wam site validate-schema <url> validate the page's structured data
|
|
39
|
+
wam site check-meta <url> [--keyword <keyword>] check the page's meta description
|
|
40
|
+
wam site analyze-chunks <url> how the page's content chunks for retrieval
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
npx @whereamimentioned/cli site check-crawlers example.com
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Every URL is fetched by the server, never by the CLI, so the checks see your site from the public
|
|
48
|
+
internet and not from inside your network. `generate-llms-txt` and `generate-sitemap` write the
|
|
49
|
+
generated file to stdout, so `> llms.txt` works, and put every count and notice on stderr; with `-o`
|
|
50
|
+
they write the file and print a summary to stderr. Add `--json` to any of them for the full
|
|
51
|
+
structured result.
|
|
52
|
+
|
|
53
|
+
## Sign in
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
wam auth login
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The default flow opens your browser at whereamimentioned.com. You pick an organization and approve,
|
|
60
|
+
and the key comes back to the CLI over a loopback port on your own machine (a PKCE code exchange, no
|
|
61
|
+
client secret, nothing to paste). Two alternatives:
|
|
62
|
+
|
|
63
|
+
- `wam auth login --device` for SSH sessions, containers, WSL and Codespaces, where no browser can
|
|
64
|
+
reach back to the machine. It prints a URL and a short code; you enter the code in a browser
|
|
65
|
+
anywhere.
|
|
66
|
+
- `wam auth login --token` reads a key you already minted in the dashboard, from stdin or a prompt.
|
|
67
|
+
|
|
68
|
+
By default the key is an organization key, bound to the organization you picked.
|
|
69
|
+
`wam auth login --account-wide` mints a key that reaches every organization your account belongs
|
|
70
|
+
to; the CLI spells out what that means and asks before the browser opens. An account-wide key gives
|
|
71
|
+
you no more permission anywhere, only more places to use it: in each organization it acts at your
|
|
72
|
+
own role there.
|
|
73
|
+
|
|
74
|
+
`wam auth status` (alias `wam whoami`) shows the key, the organization, the credit balance and where
|
|
75
|
+
the credential is stored. `wam auth logout` revokes the key on the server, then clears it locally.
|
|
76
|
+
|
|
77
|
+
**CI never calls `wam auth login`.** It sets `WAM_TOKEN` and nothing else. Mint that key with a
|
|
78
|
+
plain `wam auth login` on your own machine or in the dashboard, and keep it an organization key: a
|
|
79
|
+
CI secret that reaches every organization you belong to has a blast radius the job never needed.
|
|
80
|
+
|
|
81
|
+
## Scans, reports and the rest
|
|
82
|
+
|
|
83
|
+
```
|
|
84
|
+
wam scan estimate
|
|
85
|
+
wam scan run [--wait] [--yes] [--fail-under <n>] [--timeout <seconds>]
|
|
86
|
+
[--poll <seconds>] [--no-follow] [--idempotency-key <key>]
|
|
87
|
+
wam scan status <scanId> [--wait] [--timeout <seconds>] [--poll <seconds>]
|
|
88
|
+
wam scan list [--limit <n>] [--cursor <c>] [--status <queued|running|done|failed>]
|
|
89
|
+
wam scan evidence <scanId> [--limit <1..100>] [--cursor <c>] [--model <id>]
|
|
90
|
+
wam report get [--scan <scanId>] [--format json|csv|pdf] [-o <file>] [--fail-under <n>]
|
|
91
|
+
wam org list
|
|
92
|
+
wam org create <name> [--type brand|agency] [--yes] [--idempotency-key <key>]
|
|
93
|
+
wam workspace list
|
|
94
|
+
wam workspace use <org/workspace>
|
|
95
|
+
wam workspace create <name> [--yes]
|
|
96
|
+
wam competitor list
|
|
97
|
+
wam competitor add <name> [--domain <domain>] [--alias <alias>]...
|
|
98
|
+
wam prompt list [--enabled true|false] [--source generated|template|custom] [--stage <stage>]
|
|
99
|
+
wam prompt add <text> [--stage <awareness|research|comparison|purchase|branded>]
|
|
100
|
+
wam prompt enable <id>
|
|
101
|
+
wam prompt disable <id>
|
|
102
|
+
wam prompt remove <id>
|
|
103
|
+
wam config list | get <key> | set <key> <value> | unset <key> | path
|
|
104
|
+
wam mcp url [--readonly] [--scope org|workspace|none]
|
|
105
|
+
wam mcp install --client <client> [--readonly] [--scope org|workspace|none] [--global] [--print] [--yes]
|
|
106
|
+
wam completion bash | zsh | fish | powershell
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
`wam <group> --help` lists the subcommands and every command's help ends with a copy-pasteable
|
|
110
|
+
example.
|
|
111
|
+
|
|
112
|
+
### What spends credits, and what does not
|
|
113
|
+
|
|
114
|
+
`wam scan run` is the one command that spends credits. It always estimates first and prints the cost
|
|
115
|
+
before anything is charged, then asks; the default answer is no. In a non-interactive context (a
|
|
116
|
+
pipe, CI, `--json`) it will not prompt: pass `--yes`, or it exits 2 without spending anything. There
|
|
117
|
+
is no retry and no automatic rescan anywhere in the CLI. Every scan is started by exactly one
|
|
118
|
+
explicit command.
|
|
119
|
+
|
|
120
|
+
Everything else is free: `scan estimate`, `scan status`, `scan list`, `scan evidence`,
|
|
121
|
+
`report get`, `prompt list`, `competitor list`, `org list`, `workspace list` and every `wam site`
|
|
122
|
+
command spend zero credits. `wam org create` and `wam workspace create` spend nothing either; they
|
|
123
|
+
still ask for confirmation because neither can be undone from the CLI.
|
|
124
|
+
|
|
125
|
+
### Output
|
|
126
|
+
|
|
127
|
+
stdout is data, stderr is chatter. `--json` prints a single JSON document on stdout (NDJSON under
|
|
128
|
+
`--wait`) and is a stability contract, so `wam report get --json | jq .score` works with no
|
|
129
|
+
`2>/dev/null`. Under `--json` an error is itself the data: it goes to stdout as a JSON object, with
|
|
130
|
+
the same exit code.
|
|
131
|
+
|
|
132
|
+
## In CI
|
|
133
|
+
|
|
134
|
+
```yaml
|
|
135
|
+
# .github/workflows/ai-visibility.yml
|
|
136
|
+
name: AI visibility
|
|
137
|
+
|
|
138
|
+
on:
|
|
139
|
+
schedule:
|
|
140
|
+
# Weekly, Monday 07:00 UTC. See the cost note below before making this more frequent.
|
|
141
|
+
- cron: "0 7 * * 1"
|
|
142
|
+
workflow_dispatch:
|
|
143
|
+
|
|
144
|
+
# Prevents two scheduled runs overlapping. The API would 409 anyway, but this is cheaper.
|
|
145
|
+
concurrency:
|
|
146
|
+
group: ai-visibility
|
|
147
|
+
cancel-in-progress: false
|
|
148
|
+
|
|
149
|
+
jobs:
|
|
150
|
+
scan:
|
|
151
|
+
runs-on: ubuntu-latest
|
|
152
|
+
timeout-minutes: 45
|
|
153
|
+
permissions:
|
|
154
|
+
contents: read
|
|
155
|
+
steps:
|
|
156
|
+
- uses: actions/setup-node@v7
|
|
157
|
+
with:
|
|
158
|
+
node-version: 22
|
|
159
|
+
|
|
160
|
+
# Fail early and cheaply if the balance cannot cover a scan. Costs nothing.
|
|
161
|
+
- name: Check the balance
|
|
162
|
+
env:
|
|
163
|
+
WAM_TOKEN: ${{ secrets.WAM_TOKEN }}
|
|
164
|
+
WAM_ORG: acme
|
|
165
|
+
WAM_WORKSPACE: acme-eu
|
|
166
|
+
run: npx --yes @whereamimentioned/cli@0.1 scan estimate --json
|
|
167
|
+
|
|
168
|
+
- name: Run the scan
|
|
169
|
+
id: scan
|
|
170
|
+
env:
|
|
171
|
+
WAM_TOKEN: ${{ secrets.WAM_TOKEN }}
|
|
172
|
+
WAM_ORG: acme
|
|
173
|
+
WAM_WORKSPACE: acme-eu
|
|
174
|
+
run: |
|
|
175
|
+
npx --yes @whereamimentioned/cli@0.1 scan run \
|
|
176
|
+
--wait --yes \
|
|
177
|
+
--fail-under 55 \
|
|
178
|
+
--timeout 2400 \
|
|
179
|
+
--json | tee scan.ndjson
|
|
180
|
+
tail -n 1 scan.ndjson > scan-result.json
|
|
181
|
+
|
|
182
|
+
- name: Fetch the full report
|
|
183
|
+
if: always() && steps.scan.outcome != 'skipped'
|
|
184
|
+
env:
|
|
185
|
+
WAM_TOKEN: ${{ secrets.WAM_TOKEN }}
|
|
186
|
+
WAM_ORG: acme
|
|
187
|
+
WAM_WORKSPACE: acme-eu
|
|
188
|
+
run: npx --yes @whereamimentioned/cli@0.1 report get --json -o report.json
|
|
189
|
+
|
|
190
|
+
- uses: actions/upload-artifact@v4
|
|
191
|
+
if: always()
|
|
192
|
+
with:
|
|
193
|
+
name: ai-visibility
|
|
194
|
+
path: |
|
|
195
|
+
scan.ndjson
|
|
196
|
+
report.json
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
What that workflow does on purpose:
|
|
200
|
+
|
|
201
|
+
- `WAM_TOKEN` is an organization key, not an account-wide one. Nothing on the server can enforce
|
|
202
|
+
that; it is a rule for whoever mints the secret.
|
|
203
|
+
- `@0.1` pins the minor. While the package is `0.x`, a breaking change to the output lands in the
|
|
204
|
+
minor, so `@0` would protect nothing. Move the pins to `@1` on the day `1.0.0` ships.
|
|
205
|
+
- `--yes` is mandatory. Without it, `scan run` refuses in a non-interactive context and exits 2, so
|
|
206
|
+
no workflow spends credits by accident.
|
|
207
|
+
- The estimate step runs first and exits 4 when the balance is short, before anything is charged.
|
|
208
|
+
- `--timeout 2400` is below the job's `timeout-minutes`. On timeout the CLI exits 1 with the scan id
|
|
209
|
+
and the scan keeps running server side, so the next run can still read the report.
|
|
210
|
+
- `--fail-under 55` is an example threshold. Put yours on the flag or in `wam.json` as `failUnder`.
|
|
211
|
+
It compares the AI visibility score and exits 7 when the score is below it.
|
|
212
|
+
- A retried step does not start a second scan. The idempotency key is derived from the organization,
|
|
213
|
+
the workspace, the date and the CI run id, so a re-run follows the scan that already exists.
|
|
214
|
+
|
|
215
|
+
## Exit codes
|
|
216
|
+
|
|
217
|
+
Nothing above 125 is used, because the shell reserves 126, 127 and 128 and above.
|
|
218
|
+
|
|
219
|
+
| Code | Meaning | Typical cause |
|
|
220
|
+
|---|---|---|
|
|
221
|
+
| 0 | Success | |
|
|
222
|
+
| 1 | Generic failure | Unexpected server 500, unhandled condition |
|
|
223
|
+
| 2 | Usage error | Unknown flag, missing argument, bad value, no workspace resolved, no org resolved on an account-wide key |
|
|
224
|
+
| 3 | Auth required or expired | No credential, a credential the server no longer accepts (revoked or expired), insufficient scope, insufficient role, tier gate |
|
|
225
|
+
| 4 | Insufficient credits | HTTP 402 from the scan-create route |
|
|
226
|
+
| 5 | Rate limited | HTTP 429 |
|
|
227
|
+
| 6 | Scan failed | The scan reached `status: "failed"` while being followed |
|
|
228
|
+
| 7 | Threshold not met | `--fail-under` was set and the score was below it |
|
|
229
|
+
| 8 | Scan already running | A 409 `scan_already_running` and `--no-follow` was passed |
|
|
230
|
+
| 9 | Conflict | The server rejected the request as conflicting (409 `conflict`): the priced terms moved, or an `Idempotency-Key` was reused with different terms |
|
|
231
|
+
| 10 | Ceiling reached | A 409 `conflict` at a limit that waiting does not clear: the plan's workspace cap, or the 25 organizations one account may own |
|
|
232
|
+
| 11 | No paid organization | A 403 `feature_not_available` from `wam org create`, because the account owns no organization on a paid plan |
|
|
233
|
+
|
|
234
|
+
## Telemetry
|
|
235
|
+
|
|
236
|
+
This CLI sends no telemetry. It transmits nothing beyond the API calls needed to serve the command
|
|
237
|
+
you ran: no usage pings, no crash reporting, no anonymous metrics, no first-run beacon. The one other
|
|
238
|
+
network request is the update check against the npm registry, at most once a day, on stderr and never
|
|
239
|
+
blocking; it is off under `--json`, `--quiet`, in a pipe, when `CI` is set, or when
|
|
240
|
+
`WAM_NO_UPDATE_NOTIFIER` is set. The CLI never self-updates.
|
|
241
|
+
|
|
242
|
+
## Credential storage
|
|
243
|
+
|
|
244
|
+
Keys are stored in the operating system's credential store, one entry per profile (the default
|
|
245
|
+
profile is `default`): the macOS Keychain, the Windows Credential Manager, or Secret Service (GNOME
|
|
246
|
+
Keyring, KWallet) on Linux, under the service name `whereamimentioned`. A profile holds one
|
|
247
|
+
credential, so you can keep one key per organization and switch with `--profile`, or hold one
|
|
248
|
+
account-wide key and switch organizations with `--org`. Both patterns work.
|
|
249
|
+
|
|
250
|
+
Where the credential store is not available (headless Linux, containers, no D-Bus session), the CLI
|
|
251
|
+
falls back to a file: `${XDG_CONFIG_HOME:-~/.config}/whereamimentioned/credentials.json` on Linux and
|
|
252
|
+
macOS, `%APPDATA%\whereamimentioned\credentials.json` on Windows. On Linux and macOS the file is
|
|
253
|
+
written with mode `0600` inside a `0700` directory, and if it is later found with looser permissions
|
|
254
|
+
the CLI refuses to read it and prints the `chmod` that fixes it. `wam auth status` always says which
|
|
255
|
+
of the two backends is in use, because a silently failing keyring is the usual reason for "why does
|
|
256
|
+
it keep asking me to log in". The CLI never prints the token, not under `--debug` and not in an error.
|
|
257
|
+
|
|
258
|
+
## Configuration
|
|
259
|
+
|
|
260
|
+
Precedence, highest first: the command-line flag (`--org`, `--workspace`, `--api-url`,
|
|
261
|
+
`--profile`), the environment variable, the nearest `wam.json` found by walking up from the current
|
|
262
|
+
directory, the user config (`${XDG_CONFIG_HOME:-~/.config}/whereamimentioned/config.json`, or
|
|
263
|
+
`%APPDATA%\whereamimentioned\config.json` on Windows), then the built-in default. `wam config list`
|
|
264
|
+
prints the winning source for each key.
|
|
265
|
+
|
|
266
|
+
A committed `wam.json` pins the organization and workspace for a repo, so every checkout and every CI
|
|
267
|
+
run agree:
|
|
268
|
+
|
|
269
|
+
```json
|
|
270
|
+
{
|
|
271
|
+
"$schema": "https://whereamimentioned.com/schema/wam.config.json",
|
|
272
|
+
"org": "acme",
|
|
273
|
+
"workspace": "acme-eu",
|
|
274
|
+
"failUnder": 55
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
An unknown key in that file is a usage error (exit 2), not a silent ignore, and it has no field for a
|
|
279
|
+
token: a token in `wam.json` is a parse error. It cannot set `apiUrl` either: a committed file must
|
|
280
|
+
not get to decide where your key is sent, so set the server with `WAM_API_URL`, `--api-url` or
|
|
281
|
+
`wam config set apiUrl` instead, and an `apiUrl` in `wam.json` is refused with exit 2. `wam config set`
|
|
282
|
+
writes to the user config only, never to the project file.
|
|
283
|
+
|
|
284
|
+
## Environment variables
|
|
285
|
+
|
|
286
|
+
| Variable | Meaning |
|
|
287
|
+
|---|---|
|
|
288
|
+
| `WAM_TOKEN` | The API key. Highest-precedence credential source. |
|
|
289
|
+
| `WAM_API_URL` | API origin override. Default `https://whereamimentioned.com`. |
|
|
290
|
+
| `WAM_ORG` | Org slug override. |
|
|
291
|
+
| `WAM_WORKSPACE` | Workspace slug override. |
|
|
292
|
+
| `WAM_PROFILE` | Credential and config profile name. Default `default`. |
|
|
293
|
+
| `WAM_CONFIG_DIR` | Override the user config and credential directory wholesale. |
|
|
294
|
+
| `WAM_NO_UPDATE_NOTIFIER` | Any non-empty value disables the update check. |
|
|
295
|
+
| `WAM_MCP_URL` | Only read by `wam mcp url` / `wam mcp install`, for staging. |
|
|
296
|
+
| `NO_COLOR` | Standard. Presence disables colour regardless of value. |
|
|
297
|
+
| `CI` | Standard. Presence implies `--non-interactive`. |
|
|
298
|
+
|
|
299
|
+
Credential precedence: the `--token` flag, then `WAM_TOKEN`, then the credential store or file for
|
|
300
|
+
the active profile. Prefer `WAM_TOKEN` over `--token`: arguments leak into shell history and process
|
|
301
|
+
listings.
|
|
302
|
+
|
|
303
|
+
## Installing the MCP server
|
|
304
|
+
|
|
305
|
+
The CLI is the installer for the whereamimentioned MCP server, because no single config snippet works
|
|
306
|
+
everywhere: the top-level key and the transport name differ per client.
|
|
307
|
+
|
|
308
|
+
```
|
|
309
|
+
wam mcp install --client cursor
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
`--client` accepts `claude-code`, `cursor`, `vscode`, `windsurf`, `zed`, `warp`, `opencode`, `amp`
|
|
313
|
+
and `jetbrains`. The command merges the `whereamimentioned` entry into the client's existing config
|
|
314
|
+
and writes a backup next to it first. A project-scoped file never receives the raw token: it gets
|
|
315
|
+
`${WAM_TOKEN}` and a reminder to export it. Only `--global` writes the literal token, and only after
|
|
316
|
+
you confirm. `--print` writes the snippet to stdout and touches nothing. `wam mcp url` prints the
|
|
317
|
+
endpoint URL for the current organization and workspace, and nothing else, so it composes.
|
|
318
|
+
|
|
319
|
+
The server itself is documented at https://whereamimentioned.com/docs/mcp.
|