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

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.
@@ -7,7 +7,7 @@
7
7
  * (stripped) root. Pure — returns a relpath→bytes map without touching disk, so
8
8
  * it is unit-testable and the caller decides where to write. */
9
9
  import { unzipSync } from 'fflate';
10
- const ALLOWED_EXTENSIONS = new Set(['.md', '.json', '.txt', '.yaml', '.yml', '.csv']);
10
+ const ALLOWED_EXTENSIONS = new Set(['.md', '.py', '.json', '.txt', '.yaml', '.yml', '.csv']);
11
11
  const MAX_FILE_COUNT = 100;
12
12
  const MAX_SINGLE_FILE_BYTES = 10 * 1024 * 1024;
13
13
  const MAX_TOTAL_BYTES = 50 * 1024 * 1024;
@@ -1 +1 @@
1
- {"version":3,"file":"unzip.js","sourceRoot":"","sources":["../../src/skills/unzip.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"unzip.js","sourceRoot":"","sources":["../../src/skills/unzip.ts"],"names":[],"mappings":"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"}
package/dist/version.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  export declare const CLI_PACKAGE_NAME = "@soku-ai/cli";
2
- export declare const CLI_VERSION = "0.1.0-alpha.13";
2
+ export declare const CLI_VERSION = "0.1.0-alpha.15";
3
3
  //# sourceMappingURL=version.d.ts.map
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.13';
2
+ export const CLI_VERSION = '0.1.0-alpha.15';
3
3
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,17 +1,16 @@
1
1
  {
2
2
  "name": "@soku-ai/cli",
3
- "version": "0.1.0-alpha.13",
3
+ "version": "0.1.0-alpha.15",
4
4
  "description": "Soku CLI — call Soku ads/GA4/PostHog data capabilities from any AI agent or shell.",
5
- "license": "Proprietary",
6
- "author": "Soku",
5
+ "license": "MIT",
6
+ "author": "About Intelligence",
7
7
  "homepage": "https://soku.ai/cli",
8
8
  "bugs": {
9
- "url": "https://github.com/About-Intelligence/nex-studio/issues"
9
+ "url": "https://github.com/About-Intelligence/soku-cli/issues"
10
10
  },
11
11
  "repository": {
12
12
  "type": "git",
13
- "url": "git+https://github.com/About-Intelligence/nex-studio.git",
14
- "directory": "apps/cli"
13
+ "url": "git+https://github.com/About-Intelligence/soku-cli.git"
15
14
  },
16
15
  "keywords": [
17
16
  "soku",
@@ -34,6 +33,7 @@
34
33
  "engines": {
35
34
  "node": ">=20"
36
35
  },
36
+ "packageManager": "pnpm@10.28.0",
37
37
  "publishConfig": {
38
38
  "access": "public",
39
39
  "registry": "https://registry.npmjs.org/"
@@ -42,7 +42,6 @@
42
42
  "build": "tsc && mkdir -p dist/generated && cp src/generated/capabilities.json dist/generated/capabilities.json",
43
43
  "typecheck": "tsc --noEmit",
44
44
  "test": "tsc -p tsconfig.test.json && find .test-build -name '*.test.js' -print | sort | xargs node --test",
45
- "gen:capabilities": "uv run --project ../.. python ../../scripts/gen_cli_capabilities.py",
46
45
  "clean": "rm -rf dist .test-build",
47
46
  "postinstall": "node postinstall.cjs",
48
47
  "prepublishOnly": "pnpm run clean && pnpm run build"
@@ -3,11 +3,12 @@ name: soku
3
3
  description: >-
4
4
  Use when calling Soku CLI capabilities from a shell: auth, workspace
5
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.
8
- license: Proprietary
6
+ automations, Context Hub files, migrating context or project files from
7
+ Claude, temporary file publishing, brand skills, third-party egress,
8
+ review-gated writes, skill installation, or CLI updates.
9
+ license: MIT
9
10
  metadata:
10
- author: nex-ad
11
+ author: About Intelligence
11
12
  version: "0.4"
12
13
  ---
13
14
 
@@ -26,10 +27,11 @@ Read only the reference files needed for the user's task:
26
27
  | --- | --- |
27
28
  | First-time setup, expired token, workspace selection, org/brand ambiguity | `references/auth-workspace.md` |
28
29
  | 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
+ | Meta/Google/ChatGPT Ads writes, uploads, bulk create, review-gated approval | `references/ads-write.md` |
30
31
  | SEO Hosting, automations, Context Hub files, temporary public file URLs | `references/seo-automation-files.md` |
31
32
  | Third-party APIs through server-side credential injection; security rules | `references/egress-security.md` |
32
33
  | Installing, updating, or removing Soku-managed local skills | `references/skills-updates.md` |
34
+ | Migrate context, project files, or workspaces from Claude into Soku | Run `soku skill install migrate-from-claude`, then read the installed `soku-migrate-from-claude` skill. |
33
35
 
34
36
  For an installed business skill such as `soku-ads-report`, read that skill too.
35
37
  Business skills carry their own "Running this skill with the Soku CLI" section.
@@ -73,8 +75,14 @@ soku <namespace> <action> --help
73
75
  - Never ask the user to paste third-party provider keys for covered providers.
74
76
  - Do not fail just because an upstream provider key env var is unset. Use
75
77
  `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
+ - A human must authorize every review-gated write but don't force a
79
+ copy-paste. If your harness prompts for explicit human confirmation before
80
+ each shell command (e.g. Claude Code's permission prompt), you MAY run
81
+ `soku review approve <id>` yourself after showing the user the diff/summary;
82
+ that confirmation prompt is the human gate. Never allowlist or auto-approve
83
+ `soku review approve`/`deny`, and never approve a write the user has not seen.
84
+ If your harness runs commands without per-command human confirmation, do NOT
85
+ self-approve — surface the `review_id` for the user to run.
78
86
  - Pass user values as separate argv elements. Do not build a shell command by
79
87
  string-concatenating untrusted values.
80
88
  - Do not scan local repo files, `AGENTS.md`, or `context/` folders for Soku
@@ -1,8 +1,8 @@
1
1
  # Ads Writes
2
2
 
3
- Meta and Google write commands use typed CLI surfaces where available. Most
4
- delivery-changing writes are review-gated: the command creates a pending review
5
- and does not execute until a human approves.
3
+ Meta, Google, and ChatGPT Ads write commands use typed CLI surfaces where
4
+ available. Most delivery-changing writes are review-gated: the command creates a
5
+ pending review and does not execute until a human approves.
6
6
 
7
7
  ## Prerequisites
8
8
 
@@ -19,10 +19,25 @@ delivery-changing write still returns a pending review for a human to approve.
19
19
 
20
20
  ```bash
21
21
  soku ads meta account pages --account-id <meta_account_id>
22
+ soku ads meta account instagram --account-id <meta_account_id>
22
23
  soku ads meta campaign get --account-id <meta_account_id> --campaign-id <campaign_id>
23
24
  soku ads meta ad get --account-id <meta_account_id> --ad-id <ad_id>
24
25
  ```
25
26
 
27
+ ### Instagram identity (required for IG placements)
28
+
29
+ Before creating any creative that runs on Instagram, resolve the
30
+ **ad-account-connected** IG identity. The public IG `@handle` or the Facebook
31
+ Page id is rejected by the ads API — you must use the id returned by:
32
+
33
+ ```bash
34
+ soku ads meta account instagram --account-id <meta_account_id>
35
+ ```
36
+
37
+ Pass that `data[].id` as `instagram_user_id` (e.g. `-p instagram_user_id=<id>`)
38
+ when building the creative. An empty result means no IG account is connected to
39
+ the ad account — connect it in Business Manager first.
40
+
26
41
  ## Meta Assets
27
42
 
28
43
  Image upload mutates the Meta asset library but does not change delivery, so it
@@ -82,6 +97,23 @@ soku ads meta ad create \
82
97
  --summary "Create paused Meta ad Hero image ad"
83
98
  ```
84
99
 
100
+ Dynamic creative (Advantage+ creative) uses `--asset-feed-spec` instead of a
101
+ single asset — Meta auto-combines the arrays. It is a primary media source, so
102
+ it is mutually exclusive with `--image-hash` / `--video-id` /
103
+ `--child-attachments`; the spec needs at least one of `images`/`videos` plus
104
+ `ad_formats`, and CTA / lead-form wiring goes inside the spec
105
+ (`call_to_action_types`), not as top-level flags. The ad set must be
106
+ dynamic-creative-enabled (`soku ads meta adset create ... -p is_dynamic_creative=true`).
107
+
108
+ ```bash
109
+ soku ads meta creative create \
110
+ --account-id <meta_account_id> \
111
+ --name "Dynamic creative" \
112
+ --page-id <page_id> \
113
+ --asset-feed-spec '{"images":[{"hash":"<hash1>"},{"hash":"<hash2>"}],"bodies":[{"text":"Primary text A"},{"text":"Primary text B"}],"titles":[{"text":"Headline A"}],"link_urls":[{"website_url":"https://example.com"}],"call_to_action_types":["LEARN_MORE"],"ad_formats":["SINGLE_IMAGE"]}' \
114
+ --summary "Create Meta dynamic creative"
115
+ ```
116
+
85
117
  Status controls exist at delivery levels:
86
118
 
87
119
  ```bash
@@ -123,6 +155,35 @@ soku ads google keyword --help
123
155
  The command path determines platform. Do not add `--platform`; the CLI injects
124
156
  `platform=google`.
125
157
 
158
+ ## ChatGPT Ads Writes
159
+
160
+ ChatGPT Ads uses the generic `ads` action surface. The platform object model is
161
+ ad unit first, campaign second:
162
+
163
+ 1. Create one or more ad units with `ads/create_ad_unit`.
164
+ 2. Create the campaign with `ads/create_campaign`, `platform=chatgpt_ads`, and a
165
+ non-empty `ad_unit_ids` list.
166
+ 3. Keep new campaigns paused. The backend forces create to paused; do not submit
167
+ `update_campaign(status=active)` unless the user explicitly asks for
168
+ activation and approves that exact review.
169
+
170
+ Use `soku call` when a typed command is not obvious:
171
+
172
+ ```bash
173
+ soku call ads create_ad_unit \
174
+ --payload '{"platform":"chatgpt_ads","account_id":"<account_id>","platform_extras":{"description":"Ad unit description","landing_page":"https://example.com/?utm_source=chatgpt_ads","static_ad_text":"Primary text","static_cta":"Learn more"}}' \
175
+ --summary "Create paused ChatGPT Ads ad unit input"
176
+
177
+ soku call ads create_campaign \
178
+ --payload '{"platform":"chatgpt_ads","account_id":"<account_id>","name":"Launch Test","budget_daily_micros":300000000,"platform_extras":{"landing_page":"https://example.com/?utm_source=chatgpt_ads","campaign_objective":"clicks","ad_unit_ids":["<ad_unit_id>"]}}' \
179
+ --summary "Create paused ChatGPT Ads campaign Launch Test"
180
+ ```
181
+
182
+ Available ChatGPT Ads write actions: `create_ad_unit`, `create_campaign`,
183
+ `generate_ad_units`, `add_campaign_ad_units`, `replace_campaign_ad_units`,
184
+ `update_campaign`, and `archive_ad_unit`. Treat `archive_ad_unit` as a toggle:
185
+ verify current state before using it.
186
+
126
187
  ## Review Gate
127
188
 
128
189
  Review-gated commands return a review id:
@@ -132,6 +193,10 @@ soku review list
132
193
  soku review show <review_id>
133
194
  ```
134
195
 
135
- As an agent, show the review id and summary to the user. Do not approve on the
136
- user's behalf. Approval is single-use; failed approval is terminal, so create a
137
- fresh review for retry.
196
+ As an agent, always show the review id and summary to the user first a human
197
+ must authorize the write. If your harness prompts for explicit human
198
+ confirmation before each shell command (e.g. Claude Code's permission prompt),
199
+ you MAY then run `soku review approve <id>` yourself: that prompt is the human
200
+ gate, so never allowlist or auto-approve it. If your harness auto-runs commands
201
+ without confirmation, do not self-approve — let the user run it. Approval is
202
+ single-use; failed approval is terminal, so create a fresh review for retry.
@@ -5,20 +5,36 @@ selected separately and sent on each workspace-scoped request.
5
5
 
6
6
  ## Agent Login: Non-Blocking Split Flow
7
7
 
8
+ In a shell/container agent environment, prefix every `soku auth login` call —
9
+ including the `--device-code` resume command below — with
10
+ `SOKU_NO_KEYCHAIN=1`. The token is only written on the resume/poll step, so if
11
+ each command runs in a fresh process (e.g. a new turn), an `export` on the
12
+ first call alone will not cover it. The CLI's OS-keychain lookup can hang
13
+ indefinitely with no output on boxes without a working keychain/D-Bus session
14
+ — that hang never times out or errors, so there is nothing to catch and retry
15
+ once it happens. The flag skips the OS keychain and stores the token in
16
+ `~/.soku/credentials.json` (0600) instead; this has no downside for an agent
17
+ session.
18
+
8
19
  Do not block a turn waiting for browser approval. Start login with:
9
20
 
10
21
  ```bash
11
- soku auth login --no-wait
22
+ SOKU_NO_KEYCHAIN=1 soku auth login --no-wait
12
23
  ```
13
24
 
14
25
  Return the exact `verification_uri` and `user_code` to the user, then stop. Do
15
26
  not edit, re-encode, or reconstruct the URL. After the user approves, resume
16
- with the exact `next` command returned by the CLI:
27
+ with the exact `next` command returned by the CLI, prefixed the same way:
17
28
 
18
29
  ```bash
19
- soku auth login --device-code <device_code>
30
+ SOKU_NO_KEYCHAIN=1 soku auth login --device-code <device_code>
20
31
  ```
21
32
 
33
+ If the browser approval page shows no workspace options (for example, a
34
+ platform admin with no org memberships), the user can approve directly without
35
+ selecting a workspace. Select a brand after login with
36
+ `soku workspace use-brand`.
37
+
22
38
  For CI or headless contexts, use `SOKU_TOKEN`; do not echo it.
23
39
 
24
40
  ## Resources
@@ -54,6 +70,15 @@ soku brand list
54
70
  soku brand use <slug-or-id>
55
71
  ```
56
72
 
73
+ ## Platform Admins
74
+
75
+ `soku auth status` reports `is_platform_admin`, which is `true` only for an
76
+ active platform admin. An active platform admin can work across every active
77
+ org without holding an org membership: `soku workspace use-brand`,
78
+ `soku workspace resolve`, `soku org list`, and `soku brand list` cover the
79
+ full set of active orgs and brands. Everyone else stays scoped to the orgs
80
+ where they have a membership.
81
+
57
82
  ## Session State
58
83
 
59
84
  ```bash
@@ -43,13 +43,35 @@ soku ads query-single-dimension \
43
43
  --date-end 2026-05-07
44
44
  ```
45
45
 
46
- ChatGPT Ads is synced reporting only — no campaign/ad write actions, and
47
- `query-multi-dimension` does not support it (use `query-single-dimension`
48
- instead).
46
+ For reporting, ChatGPT Ads is still cached-first. `query-multi-dimension` does
47
+ not support it (use `query-single-dimension` instead). Campaign/ad-unit writes
48
+ now exist as review-gated `ads` actions; use `ads-write.md` for the write flow.
49
49
 
50
50
  ## Google Ads GAQL Fallback
51
51
 
52
- Use GAQL only when cached actions cannot answer the request:
52
+ For common account, campaign, ad, keyword, search-term, and bidding-strategy
53
+ reports, prefer the predefined report command over ad-hoc GAQL. It selects a
54
+ stable set of columns and uses the last 30 days when dates are omitted:
55
+
56
+ ```bash
57
+ soku ads get-google-ads-report \
58
+ --platform google \
59
+ --account-id <account_id> \
60
+ --report-type campaign \
61
+ --start-date 2026-06-01 \
62
+ --end-date 2026-06-30
63
+ ```
64
+
65
+ Supported report types are `account`, `campaign`, `ad`, `keyword`,
66
+ `search_term`, and `bidding_strategy`.
67
+
68
+ Use GAQL only when cached actions cannot answer the request.
69
+
70
+ `get-resource-metadata` needs a native Google credential; accounts connected
71
+ through a proxy credential (Pipedream / Composio) fail with
72
+ `field_metadata_unavailable` (400). In that case skip field discovery and run
73
+ `gaql-search` directly — an unknown field fails with `gaql_invalid_query`
74
+ naming the offending field.
53
75
 
54
76
  ```bash
55
77
  soku ads get-resource-metadata --platform google --account-id <account_id> --resource-name campaign
@@ -43,7 +43,10 @@ success envelope. Soku-level failures use the normal CLI error envelope.
43
43
 
44
44
  - Never print the Soku access token.
45
45
  - Prefer `SOKU_TOKEN` for CI and headless agents.
46
- - Do not approve review-gated writes on behalf of the user.
46
+ - Never approve a review-gated write the user has not seen, and never allowlist
47
+ or auto-approve `soku review approve`. Self-approving is allowed only when the
48
+ harness prompts for explicit human confirmation before each command (see the
49
+ review-gate rule in `references/ads-write.md`).
47
50
  - Avoid literal secret argv values. For Cloudflare Worker setup use
48
51
  `--cf-token-env` or `--cf-token-stdin`.
49
52
  - Pass user-provided values as separate argv elements.