@series-a/cli 1.3.0 → 1.3.2
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/CHANGELOG.md +184 -51
- package/LICENSE +7 -0
- package/README.md +249 -115
- package/SKILLS.md +359 -0
- package/bin/advisoros.mjs +2 -0
- package/package.json +50 -15
- package/src/api.mjs +102 -0
- package/src/commands/auth.mjs +193 -0
- package/src/commands/brand.mjs +439 -0
- package/src/commands/email.mjs +130 -0
- package/src/commands/flow.mjs +175 -0
- package/src/commands/insights.mjs +1813 -0
- package/src/commands/knowledge-sync.mjs +519 -0
- package/src/commands/resources.mjs +2214 -0
- package/src/commands/strategies.mjs +242 -0
- package/src/commands/voice.mjs +212 -0
- package/src/config.mjs +82 -0
- package/src/index.mjs +79 -0
- package/src/ui.mjs +104 -0
- package/bin/setu.mjs +0 -797
- package/lib/api.mjs +0 -84
- package/lib/config.mjs +0 -42
- package/lib/ui.mjs +0 -68
package/README.md
CHANGED
|
@@ -1,183 +1,317 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @series-a/cli
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A command-line interface to the AdvisorPro platform — drive leads, campaigns, sequences and agents from your terminal. Built on top of the [`/agent-api`](https://github.com/series-a/advisoros/blob/main/docs/agent-api.md) M2M router, so anything the CLI does is auditable and workspace-scoped.
|
|
4
|
+
|
|
5
|
+
---
|
|
4
6
|
|
|
5
7
|
## Install
|
|
6
8
|
|
|
7
9
|
```bash
|
|
8
|
-
|
|
9
|
-
|
|
10
|
+
# Run without installing — always fetches latest
|
|
11
|
+
npx @series-a/cli@latest --help
|
|
12
|
+
|
|
13
|
+
# Pin a version (recommended for CI)
|
|
14
|
+
npx @series-a/cli@0.1.0 --help
|
|
15
|
+
|
|
16
|
+
# Or install globally
|
|
17
|
+
npm i -g @series-a/cli
|
|
18
|
+
advisoros --help
|
|
10
19
|
```
|
|
11
20
|
|
|
12
|
-
|
|
13
|
-
`~/.config/setu/config.json` (chmod 600). You can also set `SETU_CLI_API_KEY`
|
|
14
|
-
and `SETU_API_URL` as environment variables in CI.
|
|
21
|
+
Requires **Node.js ≥ 20**.
|
|
15
22
|
|
|
16
|
-
|
|
23
|
+
> Releases are tagged `cli-vX.Y.Z` in the repo and published to npm with [provenance](https://docs.npmjs.com/generating-provenance-statements). See [`CHANGELOG.md`](./CHANGELOG.md).
|
|
17
24
|
|
|
18
|
-
|
|
19
|
-
setu practice create --url https://smiledental.co.uk
|
|
20
|
-
setu practice create --name "Smile Dental" --town Portsmouth
|
|
21
|
-
setu practice review <draft-id>
|
|
22
|
-
setu practice publish <draft-id>
|
|
23
|
-
```
|
|
25
|
+
## 1. Get an API key
|
|
24
26
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
27
|
+
1. Sign in to AdvisorPro.
|
|
28
|
+
2. Open **Settings → API Keys**.
|
|
29
|
+
3. Click **New key** → choose **Workspace** scope (recommended).
|
|
30
|
+
4. Copy the key — you won't see it again.
|
|
28
31
|
|
|
29
|
-
|
|
30
|
-
"Unclaimed" badge, ranked below live subscribed practices, with enquiry capture
|
|
31
|
-
instead of booking. It also seeds any clinicians the AI detected (skip with
|
|
32
|
-
`--no-dentists`).
|
|
32
|
+
The **CLI quickstart** card on that page shows a copy-paste `npx` command pre-filled with your workspace ID.
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
> Admin keys (cross-workspace) also work but are intentionally restricted. Default to workspace keys.
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
## 2. Log in
|
|
37
37
|
|
|
38
38
|
```bash
|
|
39
|
-
|
|
39
|
+
npx @series-a/cli@latest login
|
|
40
|
+
# Prompts for API key + workspace ID (the 6-char slug, e.g. dmw9wj)
|
|
40
41
|
```
|
|
41
42
|
|
|
42
|
-
|
|
43
|
-
are listed at the end so you can retry them.
|
|
43
|
+
### Admin login
|
|
44
44
|
|
|
45
|
-
|
|
45
|
+
Admin keys (`advos_admin_…`) are detected automatically — no workspace prompt:
|
|
46
46
|
|
|
47
47
|
```bash
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
48
|
+
advisoros login --admin
|
|
49
|
+
# ✓ Logged in as admin profile "default" — N workspaces reachable
|
|
50
|
+
|
|
51
|
+
advisoros workspaces list # admin-only, no workspace needed
|
|
52
|
+
advisoros campaigns list --workspace dmw9wj # pass workspace per command
|
|
53
|
+
advisoros whoami # shows scope: admin (cross-workspace)
|
|
53
54
|
```
|
|
54
55
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
Multiple workspaces?
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
advisoros login --profile acme # save as "acme"
|
|
60
|
+
advisoros leads list --profile acme # use the named profile
|
|
61
|
+
```
|
|
60
62
|
|
|
61
|
-
|
|
63
|
+
Config is stored at `~/.advisoros/config.json` with mode `0600`. You can also use env vars: `ADVISOROS_API_KEY`, `ADVISOROS_WORKSPACE_ID`, `ADVISOROS_PROFILE`, `ADVISOROS_BASE_URL`.
|
|
62
64
|
|
|
63
65
|
```bash
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
setu claims show <claim-id> # claimant, method, attempts, target profile
|
|
68
|
-
setu claims approve <claim-id> # transfer the profile to the claimant
|
|
69
|
-
setu claims decline <claim-id> --reason "Not the practice owner"
|
|
66
|
+
advisoros whoami
|
|
67
|
+
advisoros profiles
|
|
68
|
+
advisoros logout --profile acme
|
|
70
69
|
```
|
|
71
70
|
|
|
72
|
-
|
|
73
|
-
membership and marks the practice's clinicians as claimed. A claim can only be
|
|
74
|
-
approved once the claimant has signed in, so there's an account to transfer to.
|
|
71
|
+
## 3. Command reference
|
|
75
72
|
|
|
76
|
-
|
|
73
|
+
Global flags (work on every subcommand):
|
|
77
74
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
75
|
+
| Flag | Description |
|
|
76
|
+
|---|---|
|
|
77
|
+
| `--json` | Emit raw JSON instead of formatted tables. |
|
|
78
|
+
| `-w, --workspace <id>` | Override the workspace from your profile. |
|
|
79
|
+
| `-p, --profile <name>` | Pick a saved profile. |
|
|
80
|
+
| `--api-key <key>` | Override the saved API key. |
|
|
81
|
+
|
|
82
|
+
### Leads
|
|
82
83
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
84
|
+
```bash
|
|
85
|
+
advisoros leads list [--status new] [--persona founder] [--search acme] [--limit 50]
|
|
86
|
+
advisoros leads get <id>
|
|
87
|
+
advisoros leads set-status <id> <new|engaged|won|lost>
|
|
88
|
+
advisoros leads import --file leads.csv [--persona founder]
|
|
89
|
+
advisoros leads import-from <source> [--query ...] [--post <url>] [--file <path>] [--audience <name>] [--campaign <id>] [--limit 50] [--no-enrich]
|
|
90
|
+
advisoros leads import-status <jobId>
|
|
91
|
+
advisoros leads update <id> [--name ...] [--title ...] [--company ...] [--email ...] [--linkedin ...] [--persona ...] [--score ...] [--status ...] [--notes ...]
|
|
92
|
+
advisoros leads delete <id>
|
|
93
|
+
advisoros leads verify <id>
|
|
86
94
|
```
|
|
87
95
|
|
|
88
|
-
|
|
96
|
+
`leads import` accepts CSV (header row), JSON array, or JSONL. Upserts on `(workspace_id, linkedin_url)`. Bulk requests are auto-chunked at 200/call (server cap: 500/call).
|
|
89
97
|
|
|
90
|
-
|
|
91
|
-
seeded profiles to you.
|
|
98
|
+
`leads import-from` runs any of the import sources in **Get Leads → Import Leads**:
|
|
92
99
|
|
|
93
|
-
|
|
100
|
+
| source | required params | what it does |
|
|
101
|
+
|---|---|---|
|
|
102
|
+
| `linkedin_search` | `--query` | keyword / title / company people search via Unipile |
|
|
103
|
+
| `company_search` | `--query` | LinkedIn company search |
|
|
104
|
+
| `post_reactors` | `--post <url>` | everyone who reacted to a LinkedIn post |
|
|
105
|
+
| `paste_profiles` | `--file <path>` | name + LinkedIn URL lines; rest is enriched |
|
|
106
|
+
| `csv` | `--file <path>` | same CSV parser the UI uses |
|
|
107
|
+
| `heyreach` | `--file <path>` `--campaign <id>` | HeyReach campaign CSV, statuses preserved |
|
|
108
|
+
| `sales_nav_url` | `--url <sales-nav-search-url>` | queues a background Sales Navigator import, drip-fed inside the LinkedIn read limits |
|
|
109
|
+
| `sales_nav_keywords` | `--query` | same background queue, from Sales Navigator keywords |
|
|
94
110
|
|
|
95
|
-
|
|
96
|
-
transient failures (network drops, 429, 5xx) with exponential backoff
|
|
97
|
-
(`SETU_RETRIES`, default 3). `Retry-After` is honoured.
|
|
98
|
-
- `--verbose` prints retry attempts and stack traces.
|
|
99
|
-
- `setu logout` removes the stored key from this machine.
|
|
100
|
-
- Unknown commands and failed bulk imports exit non-zero (safe for scripts/CI).
|
|
111
|
+
All sources accept `--audience` to attach leads to a segment (created if missing). LinkedIn-backed sources run at bulk read priority so live campaigns are not starved. Long-running imports return a `job_id`; poll with `advisoros leads import-status <jobId>`.
|
|
101
112
|
|
|
102
|
-
|
|
113
|
+
Sales Navigator sources do not run inline — they create a **scheduled import** that the
|
|
114
|
+
cap-aware scheduler drip-feeds over hours or days:
|
|
103
115
|
|
|
104
116
|
```bash
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
117
|
+
advisoros leads import-from sales_nav_url --url "https://www.linkedin.com/sales/search/people?..." \
|
|
118
|
+
--limit 500 --audience "Q3 ICP" --priority high
|
|
119
|
+
advisoros leads import-schedules
|
|
120
|
+
advisoros leads import-schedule pause|resume|cancel <id>
|
|
109
121
|
```
|
|
110
122
|
|
|
111
|
-
|
|
112
|
-
else is reported and skipped before any API call is made.
|
|
123
|
+
Cancelling keeps the leads already imported.
|
|
113
124
|
|
|
114
|
-
|
|
125
|
+
### Campaigns
|
|
115
126
|
|
|
116
127
|
```bash
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
128
|
+
advisoros campaigns list [--status active]
|
|
129
|
+
advisoros campaigns show <id>
|
|
130
|
+
advisoros campaigns create --name "Founder Pitch Club" \
|
|
131
|
+
--sequence <sequenceId> \
|
|
132
|
+
--senders acc_a,acc_b \
|
|
133
|
+
--daily-limit 25
|
|
134
|
+
advisoros campaigns add-leads <campaignId> --lead-ids id1,id2,id3
|
|
135
|
+
advisoros campaigns add-leads <campaignId> --file lead-ids.txt
|
|
136
|
+
advisoros campaigns launch <id>
|
|
137
|
+
advisoros campaigns pause <id>
|
|
138
|
+
advisoros campaigns resume <id>
|
|
139
|
+
advisoros campaigns rename <id> "New name" # rename without touching other settings
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
`launch` flips status to `active` — the `enforce_campaign_char_limits` trigger validates every step's copy against LinkedIn limits before allowing the transition.
|
|
143
|
+
|
|
144
|
+
### Sequences / Inbox / Content / Agents / Meetings / Newsletter / Integrations
|
|
145
|
+
|
|
146
|
+
```bash
|
|
147
|
+
advisoros sequences list
|
|
148
|
+
advisoros sequences show <id>
|
|
149
|
+
|
|
150
|
+
advisoros inbox threads [--campaign <id>] [--lead <id>] [--needs-attention] [--limit 50]
|
|
151
|
+
|
|
152
|
+
advisoros content list [--status published] [--type post] [--search ...]
|
|
153
|
+
advisoros content show <id>
|
|
154
|
+
advisoros content publish <id>
|
|
155
|
+
|
|
156
|
+
advisoros agents list
|
|
157
|
+
advisoros agents run <name> --input '{"foo":"bar"}'
|
|
158
|
+
advisoros agents trigger <name> --input '{"foo":"bar"}'
|
|
159
|
+
advisoros agents history [--agent <name>] [--days 30] [--limit 50]
|
|
160
|
+
advisoros agents job <jobId>
|
|
161
|
+
|
|
162
|
+
advisoros meetings list [--limit 50]
|
|
163
|
+
advisoros meetings transcripts [--provider fireflies|roam] [--since 2026-01-01] [--limit 50]
|
|
164
|
+
advisoros meetings transcript <transcriptId> [--original | --mode anonymised|original]
|
|
165
|
+
|
|
166
|
+
advisoros newsletter list
|
|
167
|
+
advisoros newsletter create --subject "Weekly roundup" --body "<html>..." [--preview-text "..."]
|
|
168
|
+
advisoros newsletter edit <id> [--subject ...] [--body ...] [--preview-text ...] [--status draft|scheduled]
|
|
169
|
+
advisoros newsletter delete <id>
|
|
170
|
+
|
|
171
|
+
advisoros integrations status
|
|
172
|
+
advisoros integrations check <platform>
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
> **Heads-up:** `inbox send`/`reply` are intentionally **not** in v1. Outbound goes through `campaigns launch` (sender resolution + char limits + per-sender daily budget). For one-off DMs, use the web inbox.
|
|
176
|
+
|
|
177
|
+
`meetings transcript` returns anonymised text by default, once anonymisation is ready; otherwise metadata is returned with an explicit reason. Add `--original` to get the original text and speaker identities — your key needs this permission (all unrestricted keys already have it) and every original read is audited.
|
|
178
|
+
|
|
179
|
+
`integrations status` is read-only and never returns credentials. `integrations check <platform>` runs a live health probe for the requested platform (e.g. `linkedin_tool`).
|
|
120
180
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
181
|
+
### Obsidian vault mirror (`kb`) — one-way
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
advisoros kb link ./client-vault --workspace dmw9wj
|
|
185
|
+
advisoros kb status ./client-vault # dry-run preview
|
|
186
|
+
advisoros kb pull ./client-vault # mirror notes + graph entities
|
|
187
|
+
advisoros kb pull ./client-vault --preserve-local
|
|
124
188
|
```
|
|
125
189
|
|
|
126
|
-
|
|
190
|
+
One-way push, AdvisorPro → Obsidian. Markdown notes with frontmatter, `[[wikilinks]]` and an
|
|
191
|
+
`## Entities` block, plus `Entities/<Type>/*.md` for graph nodes. Local edits are overwritten unless
|
|
192
|
+
`--preserve-local` is used (remote copy lands as `<slug>.remote.md`). Nothing is pushed back.
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
## Examples
|
|
127
196
|
|
|
128
|
-
|
|
129
|
-
live in the nested profile record — positioning, amenities, default currency — use
|
|
130
|
-
`--set-enrichment`:
|
|
197
|
+
**Spin up a campaign from a fresh CSV:**
|
|
131
198
|
|
|
132
199
|
```bash
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
200
|
+
advisoros leads import --file ./prospects.csv --persona founder
|
|
201
|
+
advisoros leads list --persona founder --limit 200 --json \
|
|
202
|
+
| jq -r '.leads[].id' > lead-ids.txt
|
|
203
|
+
|
|
204
|
+
advisoros campaigns create --name "Q3 Founder Outreach" \
|
|
205
|
+
--sequence 1a2b3c4d-... --senders acc_milan --daily-limit 25
|
|
206
|
+
# → ✓ Created campaign 8297f04d-...
|
|
207
|
+
|
|
208
|
+
advisoros campaigns add-leads 8297f04d-... --file lead-ids.txt
|
|
209
|
+
advisoros campaigns launch 8297f04d-...
|
|
138
210
|
```
|
|
139
211
|
|
|
140
|
-
|
|
212
|
+
**Tail a long-running agent job:**
|
|
141
213
|
|
|
142
214
|
```bash
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
setu practice images <practice-id> --remove 2 # by index, or pass the URL
|
|
146
|
-
setu practice images <practice-id> --order "https://.../hero.jpg" # move these to the front
|
|
147
|
-
setu practice images <practice-id> --replace "https://a.jpg,https://b.jpg"
|
|
148
|
-
setu practice images <practice-id> --logo https://.../logo.png
|
|
149
|
-
setu dentist images <dentist-id> --logo https://.../headshot.jpg # main photo
|
|
215
|
+
JOB=$(advisoros agents run lead-intelligence --input '{}' --json | jq -r '.run.job_id')
|
|
216
|
+
watch -n 5 "advisoros agents job $JOB --json | jq '{status,progress}'"
|
|
150
217
|
```
|
|
151
218
|
|
|
152
|
-
|
|
153
|
-
|
|
219
|
+
## Safety rails
|
|
220
|
+
|
|
221
|
+
Anything that stops sending, un-enrols leads or deletes data now asks first.
|
|
154
222
|
|
|
155
223
|
```bash
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
224
|
+
# Launch is a dry run until you confirm — preflight runs server-side.
|
|
225
|
+
advisoros campaigns preflight 9884b9ec
|
|
226
|
+
advisoros campaigns launch 9884b9ec # shows blockers, changes nothing
|
|
227
|
+
advisoros campaigns launch 9884b9ec --confirm # actually launches
|
|
228
|
+
|
|
229
|
+
# Destructive commands prompt; scripts must pass --yes.
|
|
230
|
+
advisoros campaigns delete 9884b9ec --dry-run
|
|
231
|
+
advisoros campaigns delete 9884b9ec --yes
|
|
232
|
+
advisoros sequences delete-step 6b60d6ad --yes
|
|
159
233
|
```
|
|
160
234
|
|
|
161
|
-
|
|
235
|
+
A campaign with no leads, no sequence, no steps or no sender account is
|
|
236
|
+
**refused**, not silently activated. `--force` overrides once you know why.
|
|
237
|
+
|
|
238
|
+
New commands: `campaigns preflight|archive|clone|delete|remove-leads`,
|
|
239
|
+
`sequences delete|update-step|delete-step`.
|
|
240
|
+
|
|
241
|
+
## Reading more than 200 rows
|
|
242
|
+
|
|
243
|
+
List commands accept `--limit` up to 1000 and every list response carries
|
|
244
|
+
`pagination` (`total`, `limit`, `offset`, `next_cursor`, `has_more`). If you ask
|
|
245
|
+
for more than the maximum, the response says it was clamped instead of quietly
|
|
246
|
+
truncating.
|
|
247
|
+
|
|
248
|
+
## Exit codes
|
|
249
|
+
|
|
250
|
+
| Code | Meaning |
|
|
251
|
+
|---|---|
|
|
252
|
+
| 0 | Success |
|
|
253
|
+
| 1 | Generic failure (`error` in JSON response or thrown). Stderr contains the message. |
|
|
254
|
+
|
|
255
|
+
## Programmatic use
|
|
256
|
+
|
|
257
|
+
```js
|
|
258
|
+
import { call } from "@series-a/cli/src/api.mjs";
|
|
259
|
+
|
|
260
|
+
const { campaigns } = await call("campaigns", "list", { status: "active" }, {
|
|
261
|
+
apiKey: process.env.ADVISOROS_API_KEY,
|
|
262
|
+
workspaceId: "dmw9wj",
|
|
263
|
+
});
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
## Troubleshooting
|
|
267
|
+
|
|
268
|
+
- **401 Unauthorized** — key wrong / revoked / wrong base URL. Re-run `advisoros login`.
|
|
269
|
+
- **403 not authorized for the requested workspace_id** — workspace-scoped key + `--workspace` to a different workspace. Use the matching key.
|
|
270
|
+
- **CHAR_LIMIT_EXCEEDED on launch** — a sequence step exceeds LinkedIn limits (200 invitations / 8000 DMs / 1250 comments). Fix in web app.
|
|
271
|
+
- **Network error** — check `ADVISOROS_BASE_URL` if you're pointing at a non-default deployment.
|
|
272
|
+
|
|
273
|
+
## Releasing (maintainers)
|
|
162
274
|
|
|
163
275
|
```bash
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
276
|
+
cd tools/cli
|
|
277
|
+
npx changeset # describe the change
|
|
278
|
+
npm run version-packages # bump package.json + CHANGELOG.md
|
|
279
|
+
git commit -am "chore(cli): release v$(node -p "require('./package.json').version")"
|
|
280
|
+
git tag "cli-v$(node -p "require('./package.json').version")"
|
|
281
|
+
git push --follow-tags
|
|
282
|
+
# → .github/workflows/cli-release.yml publishes to npm with provenance
|
|
169
283
|
```
|
|
170
284
|
|
|
171
|
-
|
|
172
|
-
|
|
285
|
+
`NPM_TOKEN` must be set in the repo's GitHub Actions secrets (automation token with publish access to the `@series-a` org).
|
|
286
|
+
|
|
287
|
+
## Roadmap (v1.1)
|
|
288
|
+
|
|
289
|
+
- `inbox send` / `inbox reply` with explicit `--confirm` + per-sender budget enforcement.
|
|
290
|
+
- `agents tail <jobId>` (SSE).
|
|
291
|
+
- `admin workspaces …` (admin keys only).
|
|
292
|
+
- Single-binary builds via `pkg`.
|
|
173
293
|
|
|
174
|
-
##
|
|
294
|
+
## Full API reference
|
|
295
|
+
|
|
296
|
+
See [`docs/agent-api.md`](../../docs/agent-api.md) for the underlying `/agent-api` envelope.
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
|
|
300
|
+
## Admin keys
|
|
301
|
+
|
|
302
|
+
Admin keys (`advos_admin_…`) are authorised by the key itself — they do **not** need an
|
|
303
|
+
`agent_workspace_bindings` row. `agent_name` is an audit label only.
|
|
175
304
|
|
|
176
305
|
```bash
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
306
|
+
advisoros login --admin --profile ops # no workspace prompt; prints reachable workspace count
|
|
307
|
+
advisoros whoami --profile ops # scope: admin (cross-workspace) + reachable count
|
|
308
|
+
advisoros workspaces list --profile ops # every reachable workspace (paginated, up to 1000)
|
|
309
|
+
advisoros analytics overview --workspace dmw9wj --profile ops
|
|
181
310
|
```
|
|
182
311
|
|
|
183
|
-
|
|
312
|
+
Caller identity is overridable: `--as-agent <name>` on any command, `ADVISOROS_AGENT_NAME`
|
|
313
|
+
in the environment, or the `agentName` stored on the profile at login (default `advisoros-cli`).
|
|
314
|
+
|
|
315
|
+
Workspace-scoped keys are unchanged: they can only reach their own workspace (403 otherwise)
|
|
316
|
+
and cannot use the `workspaces` resource. An agent without bindings now gets a typed 403
|
|
317
|
+
explaining to use an admin key, instead of a 500.
|