@soku-ai/cli 0.1.0-alpha.11 → 0.1.0-alpha.13

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,595 +1,137 @@
1
1
  ---
2
2
  name: soku
3
3
  description: >-
4
- Use when calling Soku ads/GA4/PostHog marketing-data capabilities or SEO
5
- Hosting domain connections from the shell
6
- running `soku auth login`, switching org/brand with `soku org use` /
7
- `soku brand use`, discovering capabilities, calling a data action, routing a
8
- third-party API call (Ahrefs/DataForSEO/Firecrawl/Gemini/…) through
9
- `soku egress`, managing `soku seo-hosting connections`, managing
10
- `soku automation`, using typed Meta Ads write commands, handling 401/403
11
- errors, or installing/updating the Soku CLI.
4
+ Use when calling Soku CLI capabilities from a shell: auth, workspace
5
+ selection, ads/GA4/PostHog data reads, typed ads writes, SEO Hosting,
6
+ automations, Context Hub files, temporary file publishing, brand skills,
7
+ third-party egress, review-gated writes, skill installation, or CLI updates.
12
8
  license: Proprietary
13
9
  metadata:
14
10
  author: nex-ad
15
- version: "0.3"
11
+ version: "0.4"
16
12
  ---
17
13
 
18
14
  # Soku CLI
19
15
 
20
- The `soku` CLI calls Soku's ads, GA4, PostHog, SEO Hosting, and Automation
21
- capabilities over HTTP. It is the preferred way for an agent to use Soku from
22
- any shell, with no MCP host required. Output is JSON on stdout; errors are a
23
- JSON envelope on stderr with a semantic exit code.
16
+ The `soku` CLI is the shell-native way for an AI agent to use Soku from Claude
17
+ Code, Codex, Cursor, or any terminal. It talks to Soku over `/api/cli/*`; no MCP
18
+ host is required. Treat this file as the router. Load the relevant reference
19
+ file before acting on a detailed workflow.
24
20
 
25
- ## Output & exit codes
21
+ ## Reference Router
26
22
 
27
- Every command prints JSON. When piped (non-TTY) success is
28
- `{"ok": true, "data": ...}`; errors are `{"ok": false, "error": {"type", "message", "hint"}}`.
23
+ Read only the reference files needed for the user's task:
29
24
 
30
- | Exit | Meaning | What to do |
31
- |------|---------|------------|
32
- | 0 | Success | Parse `data`. |
33
- | 1 | Usage / no workspace selected | Fix arguments, or run `soku org use` / `soku brand use`. |
34
- | 2 | Auth not signed in or token expired/revoked | Run `soku auth login` (or set `SOKU_TOKEN`). |
35
- | 4 | Not found (unknown capability) | Re-check via `soku --help` / `soku <ns> --help`. |
36
- | 5 | Runtime / network | Retry; if behind a proxy set `ALL_PROXY`. |
37
-
38
- ## Authentication
39
-
40
- `soku` authenticates once per machine with a long-lived, **org-agnostic** session
41
- token. The org and brand are chosen at runtime (see Workspace), not at login.
42
- By default, `soku auth login` requests every resource bundle known to the CLI so
43
- agents can use reads, approved writes, SEO Hosting, automations, Context Hub,
44
- asset publishing, and Brand Skills without re-authenticating. Only pass
45
- `--resource` when the user explicitly wants a narrower token.
46
-
47
- ### Agent path (recommended): non-blocking split-flow
48
-
49
- Do NOT block a turn waiting for a human at a browser. Start login with
50
- `--no-wait`, surface the URL, end your turn, then resume:
51
-
52
- ```bash
53
- soku auth login --no-wait
54
- ```
55
-
56
- This returns immediately, e.g.:
57
-
58
- ```json
59
- {"ok":true,"data":{"user_code":"MWVP-ZTSZ","verification_uri":"https://studio.nex.ad/device","verification_uri_complete":"https://studio.nex.ad/device?user_code=MWVP-ZTSZ","device_code":"...","next":"soku auth login --device-code ..."}}
60
- ```
61
-
62
- Surface `verification_uri` and `user_code` to the user as your turn's final
63
- message (treat the URL as an opaque string — do not edit, re-encode, or
64
- re-assemble it). After the user says they approved, resume polling:
65
-
66
- ```bash
67
- soku auth login --device-code <device_code>
68
- ```
69
-
70
- ### Human path
71
-
72
- `soku auth login` opens the browser and polls until the user approves. Add
73
- `--qr` to render the verification URL as a QR code.
74
-
75
- ### CI / non-interactive
76
-
77
- Set `SOKU_TOKEN` to a pre-issued token; it overrides stored credentials and
78
- skips all interactive auth. This is the right path for CI and headless agents —
79
- it also avoids the OS keychain, which may be unavailable in containers.
80
-
81
- ### Session state
82
-
83
- - `soku auth status` — show the current identity.
84
- - `soku auth logout` — delete the stored token.
85
- - On exit code 2 with `expired` / `key_revoked`, the stored token is dropped
86
- automatically; re-run `soku auth login`.
87
-
88
- ## Workspace (org + brand)
89
-
90
- The session token carries no org/brand. Pick a workspace before calling data
91
- actions; the selection is saved to `~/.soku/config.json` and sent as
92
- `X-Soku-Org` / `X-Soku-Brand` headers.
93
-
94
- ```bash
95
- soku org list # organizations you belong to
96
- soku org use <slug|id> # set active org (id, slug, or name; clears a now-mismatched brand)
97
- soku brand list # brands in the active org
98
- soku brand use <slug|id> # id, slug, or name
99
- soku workspace status # show the active org/brand and whether it is ready
100
- soku workspace resolve <brand> # inspect accessible brand matches across orgs
101
- soku workspace use-brand <brand> # set org + brand together when the match is unique
102
- ```
103
-
104
- Env overrides for one-off invocations: `SOKU_ORG_ID`, `SOKU_BRAND_ID`.
105
-
106
- Do not infer Soku workspace state from the current shell directory. The working
107
- directory may contain unrelated README/AGENTS/context files from the user's local
108
- project. Start with `soku workspace status`; if the target brand is unknown, use
109
- `soku workspace resolve <brand>` and then `soku workspace use-brand <brand>`.
110
-
111
- ## Brand memory
112
-
113
- Memory is scoped to the active Soku workspace, not to the local shell directory.
114
- After `soku workspace status` is ready, these commands read memory for the
115
- current brand only:
116
-
117
- ```bash
118
- soku memory list
119
- soku memory search "policy 2026-05-31"
120
- soku memory get reference noiz-policy-event
121
- ```
122
-
123
- Use brand memory as background, hypotheses, and investigation leads. Do not
124
- treat a memory note as a verified data fact unless this turn also confirms it
125
- with data actions, change history, billing evidence, or another authoritative
126
- source. In reports, label memory-derived context separately from data-confirmed
127
- findings.
128
-
129
- ## Calling capabilities (discover with --help, then run)
130
-
131
- Each data capability is a typed sub-command under its namespace. Discover and
132
- inspect them with `--help` — never guess action names or flags.
133
-
134
- ```bash
135
- soku resources list # what's granted (e.g. data-infra, seo-hosting, automation)
136
- soku --help # namespaces: ads, ga4, posthog, …
137
- soku ads --help # actions in the ads namespace
138
- soku posthog --help # customer PostHog read actions
139
- soku ads query-single-dimension --help # flags, types, and usage for one action
140
-
141
- soku ads list-ad-accounts --platform google
142
- soku ads query-single-dimension --account-id 123 --dimension campaign \
143
- --date-start 2026-05-01 --date-end 2026-05-18
144
- ```
145
-
146
- `<command> --help` is authoritative for valid flags, required vs optional, types,
147
- and usage. Read it before invoking an unfamiliar action. Typed command names use
148
- kebab-case (`soku ads query-single-dimension`); raw `soku call` action names use
149
- registry snake_case (`soku call ads query_single_dimension`). Object/list flags
150
- take a JSON string, e.g. `--filters '{"campaign_id":["123"]}'`.
151
-
152
- ### Google Ads GAQL fallback
153
-
154
- Prefer cached ads analytics first:
155
-
156
- ```bash
157
- soku ads list-dimensions --platform google --account-id 123
158
- soku ads query-single-dimension --account-id 123 --dimension campaign ...
159
- soku ads query-multi-dimension --account-id 123 --dimensions '["campaign","device"]' ...
160
- ```
161
-
162
- Use GAQL only when cached query actions cannot expose the Google-native fields
163
- or segment combination you need:
164
-
165
- ```bash
166
- soku ads get-resource-metadata --platform google --account-id 123 --resource-name campaign
167
- soku ads gaql-search --platform google --account-id 123 \
168
- --dimensions '["date","campaign"]' --metrics '["cost","clicks"]' --limit 20
169
- ```
170
-
171
- Do not write full `SELECT ... FROM ...` GAQL SQL. `gaql-search` takes structured
172
- `dimensions`, `metrics`, `filters`, `date_range`, `order_by`, and `limit`; the
173
- server translates those into real GAQL. For the same action through the raw
174
- escape hatch, use snake_case: `soku call ads gaql_search --payload '{...}'`.
175
-
176
- ### PostHog customer analytics
177
-
178
- PostHog data uses the same backend MCP forwarding gateway as the sandbox agent.
179
- Start by listing the current brand's granted projects, then inspect the live
180
- tool menu, then run an allowlisted read tool. Do not ask the user for a project
181
- id before listing projects.
182
-
183
- ```bash
184
- soku posthog list-projects
185
- soku posthog list-tools --project-id 12345
186
- soku posthog query --project-id 12345 --tool execute-sql \
187
- --arguments '{"query":"SELECT count() FROM events WHERE event = '\''$pageview'\''"}'
188
- ```
189
-
190
- Use `read-data-schema` before writing HogQL if field names are unclear:
191
-
192
- ```bash
193
- soku posthog query --project-id 12345 --tool read-data-schema --arguments '{}'
194
- ```
195
-
196
- The CLI default read surface does not expose `posthog/request_change`; writes and
197
- unvetted PostHog MCP tools remain outside the generated command tree.
198
-
199
- ### Raw escape hatch
200
-
201
- `soku call <namespace> <action>` runs any action by its raw (snake_case) name
202
- with a JSON payload. Use it only when a typed sub-command isn't available — e.g.
203
- a newer action than this CLI version ships:
204
-
205
- ```bash
206
- soku call ads list_ad_accounts -p platform=google
207
- soku call ads query_single_dimension --payload '{"account_id":"123","dimension":"campaign"}'
208
- soku call posthog query --payload '{"project_id":"12345","tool":"execute-sql","arguments":{"query":"SELECT count() FROM events"}}'
209
- ```
210
-
211
- ### Meta Ads typed commands
212
-
213
- Meta Ads campaign-tree and creative workflows have an ergonomic typed command
214
- tree under `soku ads meta`. Use these commands before the raw escape hatch; they
215
- wrap the same backend actions but expose stable, platform-specific flags and
216
- client-side validation. Always inspect the exact command help before invoking a
217
- new verb:
218
-
219
- ```bash
220
- soku ads meta --help
221
- soku ads meta campaign create --help
222
- soku ads meta asset upload-images --help
223
- soku ads meta creative create --help
224
- ```
25
+ | Task | Read |
26
+ | --- | --- |
27
+ | First-time setup, expired token, workspace selection, org/brand ambiguity | `references/auth-workspace.md` |
28
+ | Ads, GA4, or PostHog reads; raw `soku call`; command discovery | `references/data-capabilities.md` and `references/capability-flow.md` |
29
+ | Meta/Google Ads writes, uploads, bulk create, review-gated approval | `references/ads-write.md` |
30
+ | SEO Hosting, automations, Context Hub files, temporary public file URLs | `references/seo-automation-files.md` |
31
+ | Third-party APIs through server-side credential injection; security rules | `references/egress-security.md` |
32
+ | Installing, updating, or removing Soku-managed local skills | `references/skills-updates.md` |
225
33
 
226
- Use the normal agent login before Meta write workflows:
34
+ For an installed business skill such as `soku-ads-report`, read that skill too.
35
+ Business skills carry their own "Running this skill with the Soku CLI" section.
227
36
 
228
- ```bash
229
- soku auth login --no-wait
230
- soku workspace status
231
- soku ads list-ad-accounts --platform meta
232
- ```
233
-
234
- If you are intentionally using a restricted token, it must include
235
- `data-infra,ads-write` for this workflow.
236
-
237
- Useful read helpers:
238
-
239
- ```bash
240
- soku ads meta account pages --account-id <meta_account_id>
241
- soku ads meta campaign get --account-id <meta_account_id> --campaign-id <campaign_id>
242
- soku ads meta ad get --account-id <meta_account_id> --ad-id <ad_id>
243
- ```
244
-
245
- Asset upload is a direct support action: it mutates Meta's asset library but
246
- does not change delivery and does not require a review summary. Local image
247
- files are read by the CLI and sent as bytes; public URLs are passed as URLs.
248
- The result includes `image_hash` values for creative creation.
249
-
250
- ```bash
251
- soku ads meta asset upload-images --account-id <meta_account_id> ./hero.png ./square.jpg
252
- soku ads meta asset upload-images --account-id <meta_account_id> \
253
- --url https://example.com/hero.png --name-prefix launch
254
- ```
255
-
256
- Common single-object write flow. Campaign and ad creation land paused; other
257
- delivery-changing writes are review-gated. Every gated command requires
258
- `--summary`, returns a review id, and executes only after human approval.
259
-
260
- ```bash
261
- soku ads meta campaign create \
262
- --account-id <meta_account_id> \
263
- --name "Launch Test" \
264
- --objective OUTCOME_TRAFFIC \
265
- --summary "Create paused Meta traffic campaign Launch Test"
266
-
267
- soku ads meta adset create \
268
- --account-id <meta_account_id> \
269
- --campaign-id <campaign_id> \
270
- --name "US Prospecting" \
271
- --optimization-goal LINK_CLICKS \
272
- --billing-event IMPRESSIONS \
273
- -p targeting='{"geo_locations":{"countries":["US"]}}' \
274
- --summary "Create paused Meta ad set US Prospecting"
275
-
276
- soku ads meta creative create \
277
- --account-id <meta_account_id> \
278
- --name "Hero image creative" \
279
- --page-id <page_id> \
280
- --image-hash <image_hash> \
281
- --message "Primary text" \
282
- --headline "Headline" \
283
- --link https://example.com \
284
- --call-to-action-type LEARN_MORE \
285
- --summary "Create Meta image creative for Launch Test"
286
-
287
- soku ads meta ad create \
288
- --account-id <meta_account_id> \
289
- --adset-id <adset_id> \
290
- --name "Hero image ad" \
291
- --creative-id <creative_id> \
292
- --summary "Create paused Meta ad Hero image ad"
293
- ```
294
-
295
- Status controls exist at all three delivery levels:
296
-
297
- ```bash
298
- soku ads meta campaign activate --campaign-id <campaign_id> --account-id <meta_account_id> --summary "Activate campaign"
299
- soku ads meta adset pause --adset-id <adset_id> --account-id <meta_account_id> --summary "Pause ad set"
300
- soku ads meta ad pause --ad-id <ad_id> --account-id <meta_account_id> --summary "Pause ad"
301
- ```
302
-
303
- Bulk commands are intentionally one layer at a time. Each command takes a JSON
304
- array file, and each item must be an object with a unique non-empty
305
- `client_ref`. The CLI injects `platform=meta` and the `--account-id`; item fields
306
- mirror the corresponding raw action payload (`create_campaign`,
307
- `create_adset`, `create_ad_creative`, or `create_ad`). Bulk approvals execute
308
- asynchronously after the human approves the review; poll with
309
- `soku review show <review_id>`.
310
-
311
- ```bash
312
- cat > campaigns.json <<'JSON'
313
- [
314
- {
315
- "client_ref": "campaign-us-traffic",
316
- "name": "US Traffic Test",
317
- "objective": "OUTCOME_TRAFFIC"
318
- }
319
- ]
320
- JSON
321
-
322
- soku ads meta campaign bulk-create \
323
- --account-id <meta_account_id> \
324
- --items-file campaigns.json \
325
- --summary "Bulk-create paused Meta campaigns for launch test"
326
-
327
- soku ads meta adset bulk-create --account-id <meta_account_id> --items-file adsets.json --summary "Bulk-create Meta ad sets"
328
- soku ads meta creative bulk-create --account-id <meta_account_id> --items-file creatives.json --summary "Bulk-create Meta creatives"
329
- soku ads meta ad bulk-create --account-id <meta_account_id> --items-file ads.json --summary "Bulk-create paused Meta ads"
330
- ```
331
-
332
- Use `soku call ads <raw_action>` only when the Meta action is not exposed in the
333
- typed tree, such as some audience, pixel, lead form, label, rule, targeting, or
334
- live-insights operations.
335
-
336
- ## Automations
337
-
338
- Use `soku automation` to manage automations for the active brand. Default agent
339
- login includes the `automation` resource. If you are intentionally using a
340
- restricted token, include `automation` explicitly:
37
+ ## Default Flow
341
38
 
342
- ```bash
343
- # Restricted-token examples only:
344
- soku auth login --resource automation
345
- soku auth login --resource data-infra,automation
346
- ```
347
-
348
- The workspace must be ready before any automation call:
39
+ 1. Check auth/workspace state:
349
40
 
350
41
  ```bash
42
+ soku auth status
351
43
  soku workspace status
352
- soku org use <slug|id>
353
- soku brand use <slug|id>
354
- soku resources list
355
- ```
356
-
357
- Commands:
358
-
359
- ```bash
360
- soku automation list
361
- soku automation create --name "Fast check" --prompt "Check account health" --cron "* * * * *" --timezone UTC
362
- soku automation trigger <automation_id>
363
- soku automation runs <automation_id>
364
- ```
365
-
366
- `create` requires exactly one schedule option:
367
-
368
- - `--cron <expr>` with optional `--timezone <iana>` (default `UTC`).
369
- - `--interval-seconds <seconds>` for interval schedules; must be at least
370
- `3600` and divisible by `60`.
371
- - `--once-at <iso>` for a one-time UTC instant.
372
-
373
- `runs` shows run status and a browser link when a conversation exists. The CLI
374
- does not read conversation content; open the printed link in Studio to inspect
375
- the actual chat. For local development links, set `SOKU_WEB_BASE`, for example:
376
-
377
- ```bash
378
- SOKU_WEB_BASE=http://127.0.0.1:47627 soku automation runs <automation_id>
379
44
  ```
380
45
 
381
- ## SEO Hosting domain connections
46
+ 2. If auth is missing or expired, use the agent split-flow from
47
+ `references/auth-workspace.md`.
382
48
 
383
- Use `soku seo-hosting` to manage SEO Hosting for the active brand. Default agent
384
- login includes the `seo-hosting` resource. If you are intentionally using a
385
- restricted token, include `seo-hosting` explicitly:
49
+ 3. If the workspace is not ready, resolve and select the remote Soku brand:
386
50
 
387
51
  ```bash
388
- # Restricted-token examples only:
389
- soku auth login --resource seo-hosting
390
- soku auth login --resource data-infra,seo-hosting
391
- ```
392
-
393
- The workspace must be ready before any connection call:
394
-
395
- ```bash
396
- soku workspace status
397
- soku org use <slug|id>
398
- soku brand use <slug|id>
52
+ soku workspace resolve <brand>
53
+ soku workspace use-brand <brand>
399
54
  ```
400
55
 
401
- ### Posts
56
+ 4. Pick the reference for the task. Do not infer Soku org/brand from the current
57
+ local repo directory.
402
58
 
403
- Use typed `pages` commands for the same SEO Hosting content actions exposed to
404
- runtime agents through `seo_hosting/*`. SEO Hosting pages are **complete HTML
405
- documents** (not Markdown) served as owned-media web pages on the brand's
406
- connected domain; they are identified by `section` + `slug` (there are no post
407
- ids). They are not social posts.
408
-
409
- Always check status first:
410
-
411
- ```bash
412
- soku seo-hosting status
413
- ```
414
-
415
- `status` shows each connected domain, whether it is `live`, and which sections it
416
- serves. If no domain is live, do not publish yet; connect or fix a domain first.
417
- When hosting is live:
59
+ 5. Inspect command help before unfamiliar calls:
418
60
 
419
61
  ```bash
420
- soku seo-hosting pages list --section blog --status draft
421
- soku seo-hosting pages put --section blog --slug how-to --title "How to ..." --html-file page.html
422
- soku seo-hosting pages publish --section blog --slug how-to
423
- soku seo-hosting pages unpublish --section blog --slug how-to
424
- soku seo-hosting pages delete --section blog --slug how-to --confirm
425
- soku seo-hosting pages upload-asset --path blog/how-to/hero.png --file ./hero.png
62
+ soku --help
63
+ soku <namespace> --help
64
+ soku <namespace> <action> --help
426
65
  ```
427
66
 
428
- `put` creates or overwrites a page as a **draft** and requires `--section`,
429
- `--slug`, `--title`, and exactly one HTML source: `--html`, `--html-file`, or
430
- `--html-stdin`. Optional metadata flags are `--description`, `--template`, and
431
- `--seo '<json object>'`. Reference images / CSS / fonts by the absolute URL
432
- returned from `pages upload-asset` (no custom JavaScript — HTML + CSS only).
433
-
434
- `publish` runs the validation gate (no `<script>` / inline JS) and
435
- makes the page live once a domain serves its section; it also prints advisory
436
- `Link warnings` for dead internal links (these do not block publishing — fix the
437
- links and re-publish). `unpublish` reverts it to draft. Writes run immediately
438
- (no-review), so confirm intent with the user before publishing or deleting.
439
-
440
- ### Domain connections
441
-
442
- Connection commands:
443
-
444
- ```bash
445
- soku seo-hosting connections list
446
- soku seo-hosting connections connect-cname --hostname blog.example.com
447
- soku seo-hosting connections verify <connection_id>
448
- soku seo-hosting connections disconnect <connection_id> --confirm
449
- ```
67
+ 6. Run the command and parse JSON output. In non-TTY contexts, success is
68
+ `{"ok":true,"data":...}` and errors are `{"ok":false,"error":...}`.
450
69
 
451
- Cloudflare Worker reverse proxy setup runs a probe before provisioning. Use it
452
- when the customer's root or existing hostname is already on Cloudflare and SEO
453
- Hosting needs to mount sections such as `/blog`, `/use-cases`, or
454
- `/alternatives`:
70
+ ## Non-Negotiable Rules
455
71
 
456
- ```bash
457
- soku seo-hosting connections probe --hostname example.com --sections blog,use-cases
458
- soku seo-hosting connections connect-worker --hostname example.com \
459
- --sections blog,use-cases --cf-token-env CLOUDFLARE_API_TOKEN
460
- printf %s "$CLOUDFLARE_API_TOKEN" | soku seo-hosting connections connect-worker \
461
- --hostname example.com --sections blog --cf-token-stdin
462
- ```
72
+ - Never print or persist the Soku access token.
73
+ - Never ask the user to paste third-party provider keys for covered providers.
74
+ - Do not fail just because an upstream provider key env var is unset. Use
75
+ `soku egress -- curl ...` for covered third-party APIs.
76
+ - Do not approve review-gated writes on the user's behalf. Surface the
77
+ `review_id` and let the user run `soku review approve <id>`.
78
+ - Pass user values as separate argv elements. Do not build a shell command by
79
+ string-concatenating untrusted values.
80
+ - Do not scan local repo files, `AGENTS.md`, or `context/` folders for Soku
81
+ workspace state unless the user explicitly asks about local files.
82
+ - When a command prints a hint, follow it before retrying. Do not loop blindly.
463
83
 
464
- Allowed sections are `blog`, `use-cases`, and `alternatives`; omitted sections
465
- default to `blog`. If the probe reports existing mounted content, add
466
- `--accept-conflicts` only after the user confirms SEO Hosting may shadow those
467
- paths. If the hostname serves its own Next.js assets, add
468
- `--accept-next-assets-warning` only after confirming `/_next/static/*` may route
469
- through the Worker.
84
+ ## Exit Codes
470
85
 
471
- Do not pass Cloudflare API tokens as literal argv values or print them. Use
472
- `--cf-token-env <ENV_NAME>` or `--cf-token-stdin` exactly once. Vercel OAuth
473
- domain connections are not exposed in the CLI yet; use the Studio web settings
474
- for Vercel-backed domains.
86
+ | Exit | Meaning | What to do |
87
+ | --- | --- | --- |
88
+ | 0 | Success | Parse `data`. |
89
+ | 1 | Usage or no workspace | Fix args, or run `soku workspace status` / `use-brand`. |
90
+ | 2 | Auth missing, expired, or revoked | Run `soku auth login --no-wait`. |
91
+ | 4 | Not found or unknown capability | Re-check `soku --help` / `soku <ns> --help`. |
92
+ | 5 | Runtime or network failure | Retry if transient; if behind a proxy set `ALL_PROXY`. |
475
93
 
476
- ## Write actions (human approval required)
94
+ ## Capability Discovery
477
95
 
478
- Some actions mutate state and are **review-gated**. Prefer typed commands when
479
- they exist (`soku ads meta ...`, `soku ads google ...`). Use `soku call` for raw
480
- actions that are not exposed as typed commands. Review-gated commands do NOT
481
- execute immediately; they return a review that a human approves.
96
+ Typed command names are kebab-case:
482
97
 
483
98
  ```bash
484
- soku call ads create_conversion_group --summary "create group: qualified leads" -p name="Qualified leads"
485
- # → {"ok":true,"data":{"status":"pending_review","review_id":"<id>","summary":"..."}}
486
-
487
- soku review list # see pending reviews
488
- soku review show <id> # full payload + (after approval) result
489
- soku review approve <id> # a human approves → the action executes now
490
- soku review deny <id> --feedback "wrong account"
99
+ soku ads query-single-dimension --help
491
100
  ```
492
101
 
493
- - The write resource must be granted to the session. Default login includes
494
- `conversion-groups-write`; restricted tokens must include it explicitly, for
495
- example `soku auth login --resource data-infra,conversion-groups-write`.
496
- Without it, `soku call` returns 403.
497
- - Approval is **single-use**: one review = one execution. Approving an already
498
- decided review is a no-op that returns the existing result.
499
- - Do NOT loop `soku review approve` expecting retries; a failed approval is
500
- terminal — create a fresh `soku call` to try again.
501
- - As an agent: surface the `review_id` + summary to the user and let THEM run
502
- `soku review approve`. Do not approve on the user's behalf.
503
-
504
- ## Third-party APIs (egress)
505
-
506
- Skills that call third-party providers (Ahrefs, DataForSEO, Firecrawl, Gemini, …)
507
- must route the call through `soku egress`. The credential is injected
508
- server-side, so **no third-party API key lives on this machine**.
509
-
510
- Prefix the skill's `curl` with `soku egress --`:
102
+ Raw `soku call` action names use registry snake_case:
511
103
 
512
104
  ```bash
513
- soku egress -- curl -H "Authorization: Bearer $AHREFS_API_KEY" "https://api.ahrefs.com/v3/..."
105
+ soku call ads query_single_dimension --payload '{"account_id":"123","dimension":"campaign"}'
514
106
  ```
515
107
 
516
- `$AHREFS_API_KEY` is not set here, and that is expected — `soku egress` strips the
517
- empty auth header, Soku injects the real key, and the upstream response is
518
- returned verbatim on stdout.
108
+ Prefer typed commands when they exist. Use `soku call` only as a forward-compatible
109
+ escape hatch for a newer action or an action not yet exposed ergonomically.
519
110
 
520
- - Do NOT pre-flight check whether an API key env var is set, and do NOT abort a
521
- skill because a key looks missing (no `[ -z "$X_API_KEY" ]` guards, no
522
- `if not os.environ.get(...)` early-exits). Assume the credential is available;
523
- just make the call through `soku egress`.
524
- - A skill's own `SKILL.md` shows the raw `curl -H "Authorization: Bearer $X"`
525
- form for reference. Ignore whether the key is set — prefix the whole command
526
- with `soku egress --`.
527
- - `soku egress providers` lists the covered hosts. For a host NOT listed, the
528
- proxy does not inject a credential — follow that skill's own auth instead.
111
+ ## Installed Skill Names
529
112
 
530
- ## Installing / updating the skill
113
+ The bundled CLI meta skill is named `soku`. Business skills are installed with a
114
+ Soku prefix, for example `soku-ads-report` and `soku-google-ads`.
531
115
 
532
116
  ```bash
533
- soku update status # show CLI + installed skill update status
534
- soku update skills # refresh this meta-skill and installed business skills
535
- soku update cli # install the latest CLI from npm
536
- soku skill install # this meta-skill into .claude / .codex / .cursor (project)
537
- soku skill install --global # into ~/.claude, ~/.codex, ~/.cursor
538
- soku skill install --agent claude --global
117
+ soku skill list
118
+ soku skill install ads-report google-ads
119
+ soku skill status
539
120
  ```
540
121
 
541
- Normal `soku` commands schedule a background refresh for installed Soku-managed
542
- skills at most once every 24 hours. Set `SOKU_NO_SKILL_AUTO_UPDATE=1` to disable
543
- skill auto updates, or `SOKU_UPDATE_INTERVAL_HOURS=<n>` to change the interval.
544
-
545
- The CLI binary itself is advisory by default. To opt into automatic npm CLI
546
- updates, set `SOKU_AUTO_UPDATE_CLI=1`; otherwise run `soku update cli` when
547
- `soku update status` shows a newer version.
548
-
549
- A global `npm i -g @soku-ai/cli` refreshes this already-installed global
550
- meta-skill after npm finishes installing. It does not install new skills and it
551
- does not update project-local skills.
122
+ When asking an AI client to invoke a business skill, write
123
+ `use @soku-ads-report skill`, not `@ads-report`.
552
124
 
553
- ## Installing business skills (account audits, Google Ads, reports, …)
125
+ ## Updating This Skill
554
126
 
555
- Beyond this meta-skill, Soku publishes a catalog of domain skills (e.g.
556
- `account-audit`, `google-ads`, `ads-report`) that already know which `soku call`
557
- actions and `soku egress` providers to use install one and your agent gains
558
- that playbook.
559
-
560
- ```bash
561
- soku skill list # browse the catalog
562
- soku skill install account-audit # install one (into soku-account-audit/)
563
- soku skill install ads-report google-ads
564
- soku skill install --all # install everything
565
- soku skill status # what's installed locally
566
- soku skill list-installed # same as status
567
- soku skill remove account-audit
568
- ```
127
+ `soku update skills` refreshes the bundled `soku` meta skill and every installed
128
+ Soku-managed business skill recorded in `.soku-skills.json`. It also refreshes
129
+ legacy meta-only installs that have `soku/SKILL.md` but no manifest, so older
130
+ installations receive this `references/` directory.
569
131
 
570
- Catalog slugs are used for install/remove commands (`ads-report`). Installed AI
571
- client skill names are Soku-prefixed (`soku-ads-report`). When asking an agent to
572
- run an installed business skill, write `use @soku-ads-report skill`, not
573
- `@ads-report`.
574
-
575
- Business skill updates are detected from `.soku-skills.json`: for each installed
576
- catalog slug, Soku compares local `version`, `sha256`, and `source` against the
577
- latest catalog `index.json`. A changed version, changed hash, or old source is
578
- treated as an update; missing catalog entries are reported but not deleted.
579
-
580
- Each installed skill carries a "Running this skill with the Soku CLI" section
581
- (its data actions mapped to `soku call`, its third-party APIs to `soku egress`),
582
- so it runs through this same CLI — no in-sandbox tools, no local API keys.
583
-
584
- ## Security rules
585
-
586
- - Never print the access token (it grants account access). Prefer `SOKU_TOKEN`
587
- for CI rather than echoing it.
588
- - Reads (`data-infra`) run directly. Review-gated writes, whether invoked with
589
- typed commands or `soku call`, create a pending review and only
590
- `soku review approve` (a human action) executes them. Direct support writes
591
- such as Meta image upload or SEO Hosting page writes execute immediately, so
592
- confirm user intent before running them. Don't approve on the user's behalf,
593
- and don't assume a `--yes`-style bypass exists — there isn't one.
594
- - Pass user-provided values as separate argv elements (the `-p key=value` form),
595
- never by string-concatenating them into a shell command.
132
+ `soku update cli` also silently refreshes an already-installed global `soku`
133
+ meta skill as an npm postinstall side effect. Its JSON result carries
134
+ `mustRereadMetaSkill: true` plus `metaSkillRefreshed: [<paths>]` when that
135
+ happened. After running `soku update cli`, check that field: if true, re-read
136
+ this file (and `references/`) from the listed path before continuing — do not
137
+ keep acting on this session's previously loaded copy of this skill.