@soku-ai/cli 0.1.0-alpha.1 → 0.1.0-alpha.10

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.
Files changed (92) hide show
  1. package/dist/auth/device.d.ts +9 -0
  2. package/dist/auth/device.d.ts.map +1 -1
  3. package/dist/auth/device.js +6 -1
  4. package/dist/auth/device.js.map +1 -1
  5. package/dist/commands/ads.d.ts +32 -0
  6. package/dist/commands/ads.d.ts.map +1 -0
  7. package/dist/commands/ads.js +752 -0
  8. package/dist/commands/ads.js.map +1 -0
  9. package/dist/commands/auth.d.ts +2 -0
  10. package/dist/commands/auth.d.ts.map +1 -1
  11. package/dist/commands/auth.js +28 -7
  12. package/dist/commands/auth.js.map +1 -1
  13. package/dist/commands/automation.d.ts +80 -0
  14. package/dist/commands/automation.d.ts.map +1 -0
  15. package/dist/commands/automation.js +213 -0
  16. package/dist/commands/automation.js.map +1 -0
  17. package/dist/commands/brand-skill.d.ts +72 -0
  18. package/dist/commands/brand-skill.d.ts.map +1 -0
  19. package/dist/commands/brand-skill.js +351 -0
  20. package/dist/commands/brand-skill.js.map +1 -0
  21. package/dist/commands/brand.d.ts.map +1 -1
  22. package/dist/commands/brand.js +59 -1
  23. package/dist/commands/brand.js.map +1 -1
  24. package/dist/commands/call.d.ts.map +1 -1
  25. package/dist/commands/call.js +6 -3
  26. package/dist/commands/call.js.map +1 -1
  27. package/dist/commands/context.d.ts +23 -0
  28. package/dist/commands/context.d.ts.map +1 -0
  29. package/dist/commands/context.js +291 -0
  30. package/dist/commands/context.js.map +1 -0
  31. package/dist/commands/files.d.ts +10 -0
  32. package/dist/commands/files.d.ts.map +1 -0
  33. package/dist/commands/files.js +48 -0
  34. package/dist/commands/files.js.map +1 -0
  35. package/dist/commands/generated.d.ts +24 -3
  36. package/dist/commands/generated.d.ts.map +1 -1
  37. package/dist/commands/generated.js +97 -10
  38. package/dist/commands/generated.js.map +1 -1
  39. package/dist/commands/memory.d.ts +18 -0
  40. package/dist/commands/memory.d.ts.map +1 -0
  41. package/dist/commands/memory.js +70 -0
  42. package/dist/commands/memory.js.map +1 -0
  43. package/dist/commands/review.d.ts.map +1 -1
  44. package/dist/commands/review.js +46 -2
  45. package/dist/commands/review.js.map +1 -1
  46. package/dist/commands/seo-hosting.d.ts +107 -0
  47. package/dist/commands/seo-hosting.d.ts.map +1 -0
  48. package/dist/commands/seo-hosting.js +499 -0
  49. package/dist/commands/seo-hosting.js.map +1 -0
  50. package/dist/commands/skill.d.ts +50 -6
  51. package/dist/commands/skill.d.ts.map +1 -1
  52. package/dist/commands/skill.js +120 -56
  53. package/dist/commands/skill.js.map +1 -1
  54. package/dist/commands/update.d.ts +23 -0
  55. package/dist/commands/update.d.ts.map +1 -0
  56. package/dist/commands/update.js +345 -0
  57. package/dist/commands/update.js.map +1 -0
  58. package/dist/commands/workspace.d.ts +4 -0
  59. package/dist/commands/workspace.d.ts.map +1 -0
  60. package/dist/commands/workspace.js +132 -0
  61. package/dist/commands/workspace.js.map +1 -0
  62. package/dist/config.d.ts +5 -4
  63. package/dist/config.d.ts.map +1 -1
  64. package/dist/config.js +5 -7
  65. package/dist/config.js.map +1 -1
  66. package/dist/generated/capabilities.json +291 -30
  67. package/dist/http/client.d.ts.map +1 -1
  68. package/dist/http/client.js +74 -16
  69. package/dist/http/client.js.map +1 -1
  70. package/dist/index.js +35 -3
  71. package/dist/index.js.map +1 -1
  72. package/dist/output/envelope.d.ts +5 -0
  73. package/dist/output/envelope.d.ts.map +1 -1
  74. package/dist/output/envelope.js +101 -2
  75. package/dist/output/envelope.js.map +1 -1
  76. package/dist/output/unwrap.d.ts.map +1 -1
  77. package/dist/output/unwrap.js +18 -1
  78. package/dist/output/unwrap.js.map +1 -1
  79. package/dist/skills/unzip.d.ts +1 -1
  80. package/dist/skills/unzip.js +1 -1
  81. package/dist/update-check.d.ts +0 -1
  82. package/dist/update-check.d.ts.map +1 -1
  83. package/dist/update-check.js +4 -54
  84. package/dist/update-check.js.map +1 -1
  85. package/dist/version.d.ts +1 -1
  86. package/dist/version.d.ts.map +1 -1
  87. package/dist/version.js +1 -1
  88. package/dist/version.js.map +1 -1
  89. package/package.json +7 -4
  90. package/postinstall.cjs +85 -0
  91. package/skills/soku/SKILL.md +254 -18
  92. package/README.md +0 -91
@@ -1 +1 @@
1
- {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,iBAAiB,CAAA;AAC9C,eAAO,MAAM,WAAW,kBAAkB,CAAA"}
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,iBAAiB,CAAA;AAC9C,eAAO,MAAM,WAAW,mBAAmB,CAAA"}
package/dist/version.js CHANGED
@@ -1,3 +1,3 @@
1
1
  export const CLI_PACKAGE_NAME = '@soku-ai/cli';
2
- export const CLI_VERSION = '0.1.0-alpha.1';
2
+ export const CLI_VERSION = '0.1.0-alpha.10';
3
3
  //# sourceMappingURL=version.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gBAAgB,GAAG,cAAc,CAAA;AAC9C,MAAM,CAAC,MAAM,WAAW,GAAG,eAAe,CAAA"}
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,gBAAgB,GAAG,cAAc,CAAA;AAC9C,MAAM,CAAC,MAAM,WAAW,GAAG,gBAAgB,CAAA"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@soku-ai/cli",
3
- "version": "0.1.0-alpha.1",
4
- "description": "Soku CLI — call Soku ads/GA4 data capabilities from any AI agent or shell.",
3
+ "version": "0.1.0-alpha.10",
4
+ "description": "Soku CLI — call Soku ads/GA4/PostHog data capabilities from any AI agent or shell.",
5
5
  "license": "Proprietary",
6
6
  "author": "Soku",
7
7
  "homepage": "https://soku.ai/cli",
@@ -19,7 +19,8 @@
19
19
  "ai-agent",
20
20
  "marketing-analytics",
21
21
  "google-ads",
22
- "ga4"
22
+ "ga4",
23
+ "posthog"
23
24
  ],
24
25
  "type": "module",
25
26
  "bin": {
@@ -27,6 +28,7 @@
27
28
  },
28
29
  "files": [
29
30
  "dist",
31
+ "postinstall.cjs",
30
32
  "skills"
31
33
  ],
32
34
  "engines": {
@@ -39,9 +41,10 @@
39
41
  "scripts": {
40
42
  "build": "tsc && mkdir -p dist/generated && cp src/generated/capabilities.json dist/generated/capabilities.json",
41
43
  "typecheck": "tsc --noEmit",
42
- "test": "tsc -p tsconfig.test.json && node --test \".test-build/**/*.test.js\"",
44
+ "test": "tsc -p tsconfig.test.json && find .test-build -name '*.test.js' -print | sort | xargs node --test",
43
45
  "gen:capabilities": "pnpm run build && node scripts/gen-capabilities.ts",
44
46
  "clean": "rm -rf dist .test-build",
47
+ "postinstall": "node postinstall.cjs",
45
48
  "prepublishOnly": "pnpm run clean && pnpm run build"
46
49
  },
47
50
  "dependencies": {
@@ -0,0 +1,85 @@
1
+ #!/usr/bin/env node
2
+ /*
3
+ * Refresh previously installed bundled Soku meta-skills after a global npm
4
+ * install. Business skills still update through `soku update skills`, because
5
+ * that path verifies catalog zip checksums and may need network access.
6
+ */
7
+
8
+ const fs = require('node:fs')
9
+ const os = require('node:os')
10
+ const path = require('node:path')
11
+
12
+ const MANIFEST_FILE = '.soku-skills.json'
13
+ const SOKU_META = 'soku'
14
+
15
+ function shouldRun() {
16
+ return process.env.npm_config_global === 'true' || process.env.npm_config_global === '1'
17
+ }
18
+
19
+ function copyDir(source, dest) {
20
+ fs.mkdirSync(dest, { recursive: true })
21
+ for (const entry of fs.readdirSync(source, { withFileTypes: true })) {
22
+ const from = path.join(source, entry.name)
23
+ const to = path.join(dest, entry.name)
24
+ if (entry.isDirectory()) {
25
+ copyDir(from, to)
26
+ } else if (entry.isFile()) {
27
+ fs.copyFileSync(from, to)
28
+ }
29
+ }
30
+ }
31
+
32
+ function loadManifest(baseDir) {
33
+ try {
34
+ return JSON.parse(fs.readFileSync(path.join(baseDir, MANIFEST_FILE), 'utf8'))
35
+ } catch {
36
+ return {}
37
+ }
38
+ }
39
+
40
+ function hasSokuSkill(baseDir) {
41
+ const manifest = loadManifest(baseDir)
42
+ return (
43
+ Object.keys(manifest).length > 0 ||
44
+ fs.existsSync(path.join(baseDir, SOKU_META, 'SKILL.md'))
45
+ )
46
+ }
47
+
48
+ function refreshMetaSkill(baseDir, bundledDir) {
49
+ if (!hasSokuSkill(baseDir)) return
50
+
51
+ const dest = path.join(baseDir, SOKU_META)
52
+ fs.mkdirSync(dest, { recursive: true })
53
+ fs.rmSync(path.join(dest, 'SKILL.md'), { force: true })
54
+ fs.rmSync(path.join(dest, 'references'), { recursive: true, force: true })
55
+ fs.copyFileSync(path.join(bundledDir, 'SKILL.md'), path.join(dest, 'SKILL.md'))
56
+ const referencesDir = path.join(bundledDir, 'references')
57
+ if (fs.existsSync(referencesDir)) {
58
+ copyDir(referencesDir, path.join(dest, 'references'))
59
+ }
60
+
61
+ const manifest = loadManifest(baseDir)
62
+ manifest[SOKU_META] = {
63
+ sha256: '',
64
+ installed_at: new Date().toISOString(),
65
+ source: 'bundled',
66
+ }
67
+ fs.writeFileSync(path.join(baseDir, MANIFEST_FILE), `${JSON.stringify(manifest, null, 2)}\n`)
68
+ }
69
+
70
+ function main() {
71
+ if (!shouldRun()) return
72
+ const bundledDir = path.join(__dirname, 'skills', SOKU_META)
73
+ if (!fs.existsSync(path.join(bundledDir, 'SKILL.md'))) return
74
+
75
+ for (const agentDir of ['.claude/skills', '.codex/skills', '.cursor/skills']) {
76
+ try {
77
+ refreshMetaSkill(path.join(os.homedir(), agentDir), bundledDir)
78
+ } catch {
79
+ // Best-effort lifecycle hook: npm install must not fail because an agent
80
+ // skill directory is missing, locked, or otherwise temporarily unreadable.
81
+ }
82
+ }
83
+ }
84
+
85
+ main()
@@ -1,23 +1,26 @@
1
1
  ---
2
2
  name: soku
3
3
  description: >-
4
- Use when calling Soku ads/GA4 marketing-data capabilities from the shell —
4
+ Use when calling Soku ads/GA4/PostHog marketing-data capabilities or SEO
5
+ Hosting domain connections from the shell —
5
6
  running `soku auth login`, switching org/brand with `soku org use` /
6
7
  `soku brand use`, discovering capabilities, calling a data action, routing a
7
8
  third-party API call (Ahrefs/DataForSEO/Firecrawl/Gemini/…) through
8
- `soku egress`, handling 401/403 errors, or installing/updating the Soku CLI.
9
+ `soku egress`, managing `soku seo-hosting connections`, managing
10
+ `soku automation`, handling 401/403 errors, or installing/updating the Soku
11
+ CLI.
9
12
  license: Proprietary
10
13
  metadata:
11
14
  author: nex-ad
12
- version: "0.1"
15
+ version: "0.2"
13
16
  ---
14
17
 
15
18
  # Soku CLI
16
19
 
17
- The `soku` CLI calls Soku's ads + GA4 data capabilities over HTTP. It is the
18
- preferred way for an agent to use Soku data — it works in any shell, with no MCP
19
- host required. Output is JSON on stdout; errors are a JSON envelope on stderr
20
- with a semantic exit code.
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.
21
24
 
22
25
  ## Output & exit codes
23
26
 
@@ -89,19 +92,46 @@ soku org list # organizations you belong to
89
92
  soku org use <slug|id> # set active org (id, slug, or name; clears a now-mismatched brand)
90
93
  soku brand list # brands in the active org
91
94
  soku brand use <slug|id> # id, slug, or name
95
+ soku workspace status # show the active org/brand and whether it is ready
96
+ soku workspace resolve <brand> # inspect accessible brand matches across orgs
97
+ soku workspace use-brand <brand> # set org + brand together when the match is unique
92
98
  ```
93
99
 
94
100
  Env overrides for one-off invocations: `SOKU_ORG_ID`, `SOKU_BRAND_ID`.
95
101
 
102
+ Do not infer Soku workspace state from the current shell directory. The working
103
+ directory may contain unrelated README/AGENTS/context files from the user's local
104
+ project. Start with `soku workspace status`; if the target brand is unknown, use
105
+ `soku workspace resolve <brand>` and then `soku workspace use-brand <brand>`.
106
+
107
+ ## Brand memory
108
+
109
+ Memory is scoped to the active Soku workspace, not to the local shell directory.
110
+ After `soku workspace status` is ready, these commands read memory for the
111
+ current brand only:
112
+
113
+ ```bash
114
+ soku memory list
115
+ soku memory search "policy 2026-05-31"
116
+ soku memory get reference noiz-policy-event
117
+ ```
118
+
119
+ Use brand memory as background, hypotheses, and investigation leads. Do not
120
+ treat a memory note as a verified data fact unless this turn also confirms it
121
+ with data actions, change history, billing evidence, or another authoritative
122
+ source. In reports, label memory-derived context separately from data-confirmed
123
+ findings.
124
+
96
125
  ## Calling capabilities (discover with --help, then run)
97
126
 
98
127
  Each data capability is a typed sub-command under its namespace. Discover and
99
128
  inspect them with `--help` — never guess action names or flags.
100
129
 
101
130
  ```bash
102
- soku resources list # what's granted (e.g. data-infra)
103
- soku --help # namespaces: ads, ga4, …
131
+ soku resources list # what's granted (e.g. data-infra, seo-hosting, automation)
132
+ soku --help # namespaces: ads, ga4, posthog,
104
133
  soku ads --help # actions in the ads namespace
134
+ soku posthog --help # customer PostHog read actions
105
135
  soku ads query-single-dimension --help # flags, types, and usage for one action
106
136
 
107
137
  soku ads list-ad-accounts --platform google
@@ -110,8 +140,57 @@ soku ads query-single-dimension --account-id 123 --dimension campaign \
110
140
  ```
111
141
 
112
142
  `<command> --help` is authoritative for valid flags, required vs optional, types,
113
- and usage. Read it before invoking an unfamiliar action. Object/list flags take a
114
- JSON string, e.g. `--filters '{"campaign_id":["123"]}'`.
143
+ and usage. Read it before invoking an unfamiliar action. Typed command names use
144
+ kebab-case (`soku ads query-single-dimension`); raw `soku call` action names use
145
+ registry snake_case (`soku call ads query_single_dimension`). Object/list flags
146
+ take a JSON string, e.g. `--filters '{"campaign_id":["123"]}'`.
147
+
148
+ ### Google Ads GAQL fallback
149
+
150
+ Prefer cached ads analytics first:
151
+
152
+ ```bash
153
+ soku ads list-dimensions --platform google --account-id 123
154
+ soku ads query-single-dimension --account-id 123 --dimension campaign ...
155
+ soku ads query-multi-dimension --account-id 123 --dimensions '["campaign","device"]' ...
156
+ ```
157
+
158
+ Use GAQL only when cached query actions cannot expose the Google-native fields
159
+ or segment combination you need:
160
+
161
+ ```bash
162
+ soku ads get-resource-metadata --platform google --account-id 123 --resource-name campaign
163
+ soku ads gaql-search --platform google --account-id 123 \
164
+ --dimensions '["date","campaign"]' --metrics '["cost","clicks"]' --limit 20
165
+ ```
166
+
167
+ Do not write full `SELECT ... FROM ...` GAQL SQL. `gaql-search` takes structured
168
+ `dimensions`, `metrics`, `filters`, `date_range`, `order_by`, and `limit`; the
169
+ server translates those into real GAQL. For the same action through the raw
170
+ escape hatch, use snake_case: `soku call ads gaql_search --payload '{...}'`.
171
+
172
+ ### PostHog customer analytics
173
+
174
+ PostHog data uses the same backend MCP forwarding gateway as the sandbox agent.
175
+ Start by listing the current brand's granted projects, then inspect the live
176
+ tool menu, then run an allowlisted read tool. Do not ask the user for a project
177
+ id before listing projects.
178
+
179
+ ```bash
180
+ soku posthog list-projects
181
+ soku posthog list-tools --project-id 12345
182
+ soku posthog query --project-id 12345 --tool execute-sql \
183
+ --arguments '{"query":"SELECT count() FROM events WHERE event = '\''$pageview'\''"}'
184
+ ```
185
+
186
+ Use `read-data-schema` before writing HogQL if field names are unclear:
187
+
188
+ ```bash
189
+ soku posthog query --project-id 12345 --tool read-data-schema --arguments '{}'
190
+ ```
191
+
192
+ The CLI default read surface does not expose `posthog/request_change`; writes and
193
+ unvetted PostHog MCP tools remain outside the generated command tree.
115
194
 
116
195
  ### Raw escape hatch
117
196
 
@@ -122,8 +201,147 @@ a newer action than this CLI version ships:
122
201
  ```bash
123
202
  soku call ads list_ad_accounts -p platform=google
124
203
  soku call ads query_single_dimension --payload '{"account_id":"123","dimension":"campaign"}'
204
+ soku call posthog query --payload '{"project_id":"12345","tool":"execute-sql","arguments":{"query":"SELECT count() FROM events"}}'
205
+ ```
206
+
207
+ ## Automations
208
+
209
+ Use `soku automation` to manage automations for the active brand. The session
210
+ must include the `automation` resource. Request it at login:
211
+
212
+ ```bash
213
+ soku auth login --resource automation
214
+ # or include it with data access:
215
+ soku auth login --resource data-infra,automation
125
216
  ```
126
217
 
218
+ The workspace must be ready before any automation call:
219
+
220
+ ```bash
221
+ soku workspace status
222
+ soku org use <slug|id>
223
+ soku brand use <slug|id>
224
+ soku resources list
225
+ ```
226
+
227
+ Commands:
228
+
229
+ ```bash
230
+ soku automation list
231
+ soku automation create --name "Fast check" --prompt "Check account health" --cron "* * * * *" --timezone UTC
232
+ soku automation trigger <automation_id>
233
+ soku automation runs <automation_id>
234
+ ```
235
+
236
+ `create` requires exactly one schedule option:
237
+
238
+ - `--cron <expr>` with optional `--timezone <iana>` (default `UTC`).
239
+ - `--interval-seconds <seconds>` for interval schedules; must be at least
240
+ `3600` and divisible by `60`.
241
+ - `--once-at <iso>` for a one-time UTC instant.
242
+
243
+ `runs` shows run status and a browser link when a conversation exists. The CLI
244
+ does not read conversation content; open the printed link in Studio to inspect
245
+ the actual chat. For local development links, set `SOKU_WEB_BASE`, for example:
246
+
247
+ ```bash
248
+ SOKU_WEB_BASE=http://127.0.0.1:47627 soku automation runs <automation_id>
249
+ ```
250
+
251
+ ## SEO Hosting domain connections
252
+
253
+ Use `soku seo-hosting` to manage SEO Hosting for the active brand. The session
254
+ must include the `seo-hosting` resource. Request it at login:
255
+
256
+ ```bash
257
+ soku auth login --resource seo-hosting
258
+ # or include it with data access:
259
+ soku auth login --resource data-infra,seo-hosting
260
+ ```
261
+
262
+ The workspace must be ready before any connection call:
263
+
264
+ ```bash
265
+ soku workspace status
266
+ soku org use <slug|id>
267
+ soku brand use <slug|id>
268
+ ```
269
+
270
+ ### Posts
271
+
272
+ Use typed `pages` commands for the same SEO Hosting content actions exposed to
273
+ runtime agents through `seo_hosting/*`. SEO Hosting pages are **complete HTML
274
+ documents** (not Markdown) served as owned-media web pages on the brand's
275
+ connected domain; they are identified by `section` + `slug` (there are no post
276
+ ids). They are not social posts.
277
+
278
+ Always check status first:
279
+
280
+ ```bash
281
+ soku seo-hosting status
282
+ ```
283
+
284
+ `status` shows each connected domain, whether it is `live`, and which sections it
285
+ serves. If no domain is live, do not publish yet; connect or fix a domain first.
286
+ When hosting is live:
287
+
288
+ ```bash
289
+ soku seo-hosting pages list --section blog --status draft
290
+ soku seo-hosting pages put --section blog --slug how-to --title "How to ..." --html-file page.html
291
+ soku seo-hosting pages publish --section blog --slug how-to
292
+ soku seo-hosting pages unpublish --section blog --slug how-to
293
+ soku seo-hosting pages delete --section blog --slug how-to --confirm
294
+ soku seo-hosting pages upload-asset --path blog/how-to/hero.png --file ./hero.png
295
+ ```
296
+
297
+ `put` creates or overwrites a page as a **draft** and requires `--section`,
298
+ `--slug`, `--title`, and exactly one HTML source: `--html`, `--html-file`, or
299
+ `--html-stdin`. Optional metadata flags are `--description`, `--template`, and
300
+ `--seo '<json object>'`. Reference images / CSS / fonts by the absolute URL
301
+ returned from `pages upload-asset` (no custom JavaScript — HTML + CSS only).
302
+
303
+ `publish` runs the validation gate (no `<script>` / inline JS) and
304
+ makes the page live once a domain serves its section; it also prints advisory
305
+ `Link warnings` for dead internal links (these do not block publishing — fix the
306
+ links and re-publish). `unpublish` reverts it to draft. Writes run immediately
307
+ (no-review), so confirm intent with the user before publishing or deleting.
308
+
309
+ ### Domain connections
310
+
311
+ Connection commands:
312
+
313
+ ```bash
314
+ soku seo-hosting connections list
315
+ soku seo-hosting connections connect-cname --hostname blog.example.com
316
+ soku seo-hosting connections verify <connection_id>
317
+ soku seo-hosting connections disconnect <connection_id> --confirm
318
+ ```
319
+
320
+ Cloudflare Worker reverse proxy setup runs a probe before provisioning. Use it
321
+ when the customer's root or existing hostname is already on Cloudflare and SEO
322
+ Hosting needs to mount sections such as `/blog`, `/use-cases`, or
323
+ `/alternatives`:
324
+
325
+ ```bash
326
+ soku seo-hosting connections probe --hostname example.com --sections blog,use-cases
327
+ soku seo-hosting connections connect-worker --hostname example.com \
328
+ --sections blog,use-cases --cf-token-env CLOUDFLARE_API_TOKEN
329
+ printf %s "$CLOUDFLARE_API_TOKEN" | soku seo-hosting connections connect-worker \
330
+ --hostname example.com --sections blog --cf-token-stdin
331
+ ```
332
+
333
+ Allowed sections are `blog`, `use-cases`, and `alternatives`; omitted sections
334
+ default to `blog`. If the probe reports existing mounted content, add
335
+ `--accept-conflicts` only after the user confirms SEO Hosting may shadow those
336
+ paths. If the hostname serves its own Next.js assets, add
337
+ `--accept-next-assets-warning` only after confirming `/_next/static/*` may route
338
+ through the Worker.
339
+
340
+ Do not pass Cloudflare API tokens as literal argv values or print them. Use
341
+ `--cf-token-env <ENV_NAME>` or `--cf-token-stdin` exactly once. Vercel OAuth
342
+ domain connections are not exposed in the CLI yet; use the Studio web settings
343
+ for Vercel-backed domains.
344
+
127
345
  ## Write actions (human approval required)
128
346
 
129
347
  Some actions mutate state (e.g. conversion-group writes) and are **review-gated**.
@@ -180,18 +398,25 @@ returned verbatim on stdout.
180
398
  ## Installing / updating the skill
181
399
 
182
400
  ```bash
183
- soku update-check # check whether the CLI itself needs updating
401
+ soku update status # show CLI + installed skill update status
402
+ soku update skills # refresh this meta-skill and installed business skills
403
+ soku update cli # install the latest CLI from npm
184
404
  soku skill install # this meta-skill into .claude / .codex / .cursor (project)
185
405
  soku skill install --global # into ~/.claude, ~/.codex, ~/.cursor
186
406
  soku skill install --agent claude --global
187
407
  ```
188
408
 
189
- If `soku update-check` reports an available CLI update, ask the user before
190
- running:
409
+ Normal `soku` commands schedule a background refresh for installed Soku-managed
410
+ skills at most once every 24 hours. Set `SOKU_NO_SKILL_AUTO_UPDATE=1` to disable
411
+ skill auto updates, or `SOKU_UPDATE_INTERVAL_HOURS=<n>` to change the interval.
191
412
 
192
- ```bash
193
- npm i -g @soku-ai/cli
194
- ```
413
+ The CLI binary itself is advisory by default. To opt into automatic npm CLI
414
+ updates, set `SOKU_AUTO_UPDATE_CLI=1`; otherwise run `soku update cli` when
415
+ `soku update status` shows a newer version.
416
+
417
+ A global `npm i -g @soku-ai/cli` refreshes this already-installed global
418
+ meta-skill after npm finishes installing. It does not install new skills and it
419
+ does not update project-local skills.
195
420
 
196
421
  ## Installing business skills (account audits, Google Ads, reports, …)
197
422
 
@@ -205,10 +430,21 @@ soku skill list # browse the catalog
205
430
  soku skill install account-audit # install one (into soku-account-audit/)
206
431
  soku skill install ads-report google-ads
207
432
  soku skill install --all # install everything
208
- soku skill installed # what's installed locally
433
+ soku skill status # what's installed locally
434
+ soku skill list-installed # same as status
209
435
  soku skill remove account-audit
210
436
  ```
211
437
 
438
+ Catalog slugs are used for install/remove commands (`ads-report`). Installed AI
439
+ client skill names are Soku-prefixed (`soku-ads-report`). When asking an agent to
440
+ run an installed business skill, write `use @soku-ads-report skill`, not
441
+ `@ads-report`.
442
+
443
+ Business skill updates are detected from `.soku-skills.json`: for each installed
444
+ catalog slug, Soku compares local `version`, `sha256`, and `source` against the
445
+ latest catalog `index.json`. A changed version, changed hash, or old source is
446
+ treated as an update; missing catalog entries are reported but not deleted.
447
+
212
448
  Each installed skill carries a "Running this skill with the Soku CLI" section
213
449
  (its data actions mapped to `soku call`, its third-party APIs to `soku egress`),
214
450
  so it runs through this same CLI — no in-sandbox tools, no local API keys.
package/README.md DELETED
@@ -1,91 +0,0 @@
1
- # @soku-ai/cli
2
-
3
- Call Soku ads/GA4 data capabilities from any shell or AI agent. It's the
4
- preferred surface for external agents — equivalent to the hosted MCP server, but
5
- works without an MCP host.
6
-
7
- ## Install
8
-
9
- ```bash
10
- npm i -g @soku-ai/cli
11
- ```
12
-
13
- Development builds can be linked from this repo:
14
-
15
- ```bash
16
- pnpm --filter @soku-ai/cli run build
17
- npm link apps/cli
18
- ```
19
-
20
- ## Quick start
21
-
22
- ```bash
23
- soku auth login # device-login in the browser
24
- soku org use <slug|id> # pick a workspace (id, slug, or name)
25
- soku brand use <slug|id>
26
- soku --help # discover namespaces (ads, ga4, …)
27
- soku update-check # check npm for a newer CLI release
28
- soku ads --help # actions in a namespace
29
- soku ads list-ad-accounts --platform google
30
- ```
31
-
32
- Each data capability is a typed sub-command under its namespace; `<command>
33
- --help` shows its flags. `soku call <ns> <action>` is a raw escape hatch for
34
- actions not yet exposed as a typed sub-command.
35
-
36
- ## Authentication
37
-
38
- `soku` uses an org-agnostic, device-login session token (RFC 8628). You log in
39
- once; the org and brand are chosen at runtime and sent per request.
40
-
41
- - **Human:** `soku auth login` opens the browser and waits for approval.
42
- - **Agent (non-blocking):** `soku auth login --no-wait` returns the verification
43
- URL immediately; resume with `soku auth login --device-code <code>` after the
44
- user approves.
45
- - **CI / headless:** set `SOKU_TOKEN` to a pre-issued token to skip interactive
46
- auth (and the OS keychain).
47
-
48
- Token storage: OS keychain when available, else `~/.soku/credentials.json`
49
- (0600). Set `SOKU_NO_KEYCHAIN=1` to always use the file. Behind a proxy, set
50
- `ALL_PROXY`.
51
-
52
- ## Output
53
-
54
- stdout is JSON (`{"ok":true,"data":...}` when piped; pretty when a TTY).
55
- Errors go to stderr as `{"ok":false,"error":{type,message,hint}}` with a
56
- semantic exit code (0 ok / 1 usage / 2 auth / 4 not-found / 5 runtime).
57
-
58
- ## Use from an AI agent
59
-
60
- For a fresh agent, point it at the hosted installer guide:
61
-
62
- ```text
63
- Read https://soku.ai/cli/skill.md and install the Soku CLI.
64
- ```
65
-
66
- Install the bundled skill so Claude Code / Codex / Cursor know how to drive the
67
- CLI:
68
-
69
- ```bash
70
- soku skill install --global # all detected agents
71
- soku skill install --agent claude # one agent, into the project
72
- ```
73
-
74
- ## Updates
75
-
76
- `soku update-check` queries the npm registry for `@soku-ai/cli@latest` and tells
77
- the user whether `npm i -g @soku-ai/cli` should be re-run. The CLI also performs a
78
- TTY-only advisory check at most once every 24 hours, cached in
79
- `~/.soku/update-check.json`. Set `SOKU_NO_UPDATE_CHECK=1` to disable the
80
- background notice.
81
-
82
- ## Environment variables
83
-
84
- | Variable | Purpose |
85
- |----------|---------|
86
- | `SOKU_TOKEN` | Pre-issued session token (overrides stored credentials) |
87
- | `SOKU_API_BASE` | API base URL override |
88
- | `SOKU_ORG_ID` / `SOKU_BRAND_ID` | One-off workspace override |
89
- | `SOKU_NO_KEYCHAIN` | Skip the OS keychain; use the 0600 file |
90
- | `SOKU_NO_UPDATE_CHECK` | Disable the TTY-only update notice |
91
- | `ALL_PROXY` | Proxy for outbound HTTPS |