@drip-apex/apex-cli 0.19.1 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/AGENTS.md CHANGED
@@ -89,7 +89,8 @@ the first writes: `apex experiments create`, `apex goals create`,
89
89
  - Edit experiment files, variation code, metrics, and targeting only through supported paths.
90
90
  - Do not bypass the variation artifact persistence path with direct API writes.
91
91
  - Keep generated evidence outside `qa.json`; attach it through QA commands.
92
- - Author commerce drafts in `commerce/price.json`, `commerce/shipping.json`, `commerce/offer.json`, or `commerce/post-purchase.json`; never edit their `serverOwned` sections.
92
+ - Author commerce drafts in `commerce/price.json`, `commerce/shipping.json`, `commerce/offer.json`, `commerce/discount-codes.json`, or `commerce/post-purchase.json`; never edit their `serverOwned` sections.
93
+ - Checkout messages use `{ "action": "checkoutBlock", "checkoutBlock": { "heading": "Free returns for 30 days" } }`: one per A/B arm, flat mutations only (`variations/<slug>/mutations.json` or workspace `src/mutations.json`), never URL blocks or a test with post-purchase. Money copy is refused. Run each message arm's QA checkout from its `apex preview <id> <variation-id>` link or the dashboard, then launch in the dashboard.
93
94
 
94
95
  ## Project code
95
96
 
package/README.md CHANGED
@@ -1,4 +1,46 @@
1
- # Apex CLI
1
+ # Apex CLI: run A/B tests on your online shop from the terminal or an AI coding agent
2
+
3
+ Apex by DRIP is an A/B testing platform for online shops that predicts which tests will win before they go live, built on one of the largest A/B test databases in e-commerce.
4
+
5
+ This package is the `apex` command line. Developers and AI coding agents (Claude Code, Codex, Cursor) use it to build and run Apex A/B tests as code: list tests and read results, pull a test into local files, edit the variation, review a plan and apply it, open preview links for QA, check tracking, and push goals, targeting and feature flags from a config file. Launching a test to live traffic happens in the Apex app.
6
+
7
+ - Website: https://www.drip-apex.com
8
+ - Docs: https://docs.drip-apex.com
9
+ - CLI install and sign-in: https://docs.drip-apex.com/docs/cli/install-auth
10
+ - Command reference: https://docs.drip-apex.com/docs/cli/commands-output
11
+
12
+ Want Apex inside ChatGPT, Claude or Cursor without a terminal? Connect the hosted MCP server at `https://app.drip-apex.com/api/mcp` (OAuth). Setup: https://docs.drip-apex.com/docs/mcp/install-configure and the [`@drip-apex/mcp-server`](https://www.npmjs.com/package/@drip-apex/mcp-server) package.
13
+
14
+ ## Quick start
15
+
16
+ ```bash
17
+ npm install -g @drip-apex/apex-cli
18
+ apex login
19
+ apex experiments list
20
+ ```
21
+
22
+ ## Install
23
+
24
+ ```bash
25
+ npm install -g @drip-apex/apex-cli
26
+ ```
27
+
28
+ Install the CLI once, then call `apex` directly. `apex --help` and `apex schema --json` answer without network access. Do not run `npx @drip-apex/apex-cli@latest` for every command: npx asks the npm registry for the package before the CLI starts, so it prints nothing and hangs when the registry is slow or blocked, which is common in agent sandboxes. Update with `npm install -g @drip-apex/apex-cli@latest`.
29
+
30
+ ## Authenticate
31
+
32
+ ```bash
33
+ apex login
34
+ apex whoami
35
+ ```
36
+
37
+ `apex login` opens the default browser OAuth flow at Apex `/cli/login`. For
38
+ headless environments, use an existing API key:
39
+
40
+ ```bash
41
+ apex login --api-key apx_your_key_here
42
+ APEX_API_KEY=apx_your_key_here apex experiments list --json
43
+ ```
2
44
 
3
45
  ## Choosing a workflow
4
46
 
@@ -50,32 +92,6 @@ change the stored login. Use `apex login --api-key apx_uk_...` for a headless
50
92
  account login or `apex login --api-key apx_...` to store a shop key. The old
51
93
  `apex login --user` spelling is a deprecated alias for `apex login`.
52
94
 
53
- Command-line tools for Apex experiments, draft workspaces, GitOps pushes, QA
54
- evidence, tracking checks, and agent handoffs.
55
-
56
- ## Install
57
-
58
- ```bash
59
- npm install -g @drip-apex/apex-cli
60
- ```
61
-
62
- Install the CLI once, then call `apex` directly. `apex --help` and `apex schema --json` answer without network access. Do not run `npx @drip-apex/apex-cli@latest` for every command: npx asks the npm registry for the package before the CLI starts, so it prints nothing and hangs when the registry is slow or blocked, which is common in agent sandboxes. Update with `npm install -g @drip-apex/apex-cli@latest`.
63
-
64
- ## Authenticate
65
-
66
- ```bash
67
- apex login
68
- apex whoami
69
- ```
70
-
71
- `apex login` opens the default browser OAuth flow at Apex `/cli/login`. For
72
- headless environments, use an existing API key:
73
-
74
- ```bash
75
- apex login --api-key apx_your_key_here
76
- APEX_API_KEY=apx_your_key_here apex experiments list --json
77
- ```
78
-
79
95
  ## Common usage
80
96
 
81
97
  ```bash
@@ -168,6 +184,7 @@ including every subcommand, argument, option, and alias.
168
184
  - `apex keys` — manage shop API keys.
169
185
  - `apex org` — inspect and manage the organization.
170
186
  - `apex team` — manage shop-scoped members and invitations.
187
+ - `apex notifications` — choose Ready to launch email recipients and toggle ready messages on an existing Slack destination.
171
188
 
172
189
  ### Experiments and delivery
173
190
 
@@ -204,6 +221,8 @@ including every subcommand, argument, option, and alias.
204
221
  - `apex workspace` — check out, preview, and publish draft workspace files.
205
222
  - `apex goals` — manage conversion and revenue goals. Create/update accept `--page-id <id>` (UUID only, no lookup) or `--page <id-or-key>` (keys need `pages:read` for lookup); use one option.
206
223
  - `apex flags` — manage feature flags.
224
+ - `apex forms` — track storefront forms and read form and checkout analytics: list, add, remove,
225
+ summary, fields, field, errors, sessions, label, merge, unmerge and detect. Needs the shop's form analytics switch.
207
226
  - `apex surveys` — list, get, create, update, start, pause, complete, duplicate, and delete surveys.
208
227
  Use `apex surveys list --status live` to filter, and `apex surveys create @survey.json`
209
228
  or `apex surveys update <id> <body>` with inline JSON, `@file`, or a file path.
@@ -279,6 +298,18 @@ command inventory:
279
298
  | `apex admin shops settings get --shop <uuid-or-domain> --key <key>` | Read one setting; unknown keys list the available registry keys. |
280
299
  | `apex admin shops settings set --shop <uuid-or-domain> --key <key> --value <value>` | Resolve and pin the shop, then make an audited write. Booleans accept on/off/true/false; numbers must be finite; null clears nullable settings. Sensitive writes require `--confirm`; optional `--reason` and `--expected-version` preserve audit context and concurrency. |
281
300
 
301
+ ## Consent setup warnings
302
+
303
+ `apex consent get`, `set`, and `off` include setup warnings in JSON output and print
304
+ them on stderr in human output. Custom consent without a getter waits for the site
305
+ to call `Drip.setConsent(true)`. A configured consent provider with consent mode off
306
+ does not gate tracking or storage.
307
+
308
+ `apex shops doctor` runs `unbound_hosts`, `dev_pollution`, `cmp_mismatch`,
309
+ `consent_gate`, `stale_served_config`, `goal_reachability`, `consent_rate`, and
310
+ `purchase_capture`, in that order. `consent_gate` warns about consent setup, passes
311
+ when the API returns no warnings, and skips older servers without warning support.
312
+
282
313
  ## Landing pages built outside Apex
283
314
 
284
315
  A landing page is built in a checkout folder by any tool (Claude Code, Codex,
@@ -323,7 +354,7 @@ folder belongs to `apex experiments pull/plan/apply`, `landing-page.json` means
323
354
  an `apex landing-pages` checkout, while `session.json`
324
355
  means it is an `apex workspace checkout/status/publish` workspace. Keep the two
325
356
  formats in different folders; when the wrong command is run, Apex points to the
326
- matching status command.
357
+ matching status command. In a workspace folder, a checkout message goes in `src/mutations.json`.
327
358
 
328
359
  ## Page targeting: URL rules and Pages
329
360
 
@@ -360,6 +391,39 @@ In a pulled `targeting.json`, `url` is the expanded rule set and `authorUrl` is
360
391
  the authored subset, always present. Edit `url` and `pages`; treat `authorUrl`
361
392
  and `pageRules` as output.
362
393
 
394
+ ## Checkout messages
395
+
396
+ A checkout message adds text to the Apex block in Shopify checkout, as a typed change on an A/B test arm. Add `[{ "action": "checkoutBlock", "checkoutBlock": { "heading": "Free returns for 30 days", "body": "Not the right fit? Send it back for free.", "tone": "info" } }]` to the arm's flat mutations.
397
+
398
+ The required `heading` is trimmed and must contain visible text in 1–120 characters. Optional `eyebrow`, `body` and `disclosure` allow up to 60, 500 and 300 characters. `tone` defaults to `info`; it also accepts `success`, `warning` or `critical`. `placement` accepts only `checkout`, the default. Unknown keys are refused at both levels. Omit deprecated `enabled`; `false` hides the message.
399
+
400
+ Use at most one message per arm (`duplicate_checkout_block`), in `variations/<slug>/mutations.json` for a pulled experiment or `src/mutations.json` for a workspace folder, never `url-blocks.json`. Messages cannot share a test with `commerce/post-purchase.json`, and personalizations refuse them. Omit `surface` and `checkoutBlock` from `targeting.json`; those retired keys return `409 checkout_mode_retired`.
401
+
402
+ Copy cannot state a money amount: a number next to a currency symbol, ISO code or currency word, or a percent next to a discount word such as off, save, sale or Rabatt. Apply returns `422 checkout_copy_states_money` (CLI exit 3). A plain percent only warns at launch.
403
+
404
+ Pause a running test before changing its message, run its QA checkout again, then resume. On paused or running tests, adding the first message to a test with no storefront change or removing the last message is refused (`checkout_exposure_owner_frozen`).
405
+
406
+ Messages may share an arm with DOM mutations, CSS, JS and commerce levers other than post-purchase. Combined tests count visitors on the storefront and show their storefront change only while Apex can confirm the message is live at checkout. Tests whose arms change only messages count visitors at checkout and show messages only to buyers who allow analytics, marketing and sale-of-data processing; QA testers must grant that consent too. Apex recommends a revenue primary goal for these tests. Control may carry a message, but it does not count as treatment work.
407
+
408
+ From nothing to a saved draft:
409
+
410
+ 1. Run `apex login`, then `apex use <org>/<shop>`. Alternatively set `APEX_API_KEY` with `DRIP_ORG`/`DRIP_SHOP` or pass `--org`/`--shop`. With only `APEX_API_KEY`, `apex use` cannot persist context; a shop-scoped key needs no selection.
411
+ 2. Run `apex experiments create --name "Checkout message" --page-url <url> --yes --json` and read `.data.experiment.id`. A fresh draft has `control` and `variation-b` arms.
412
+ 3. Run `apex experiments pull <id> --out <folder> --json`.
413
+ 4. Put the entry above in `<folder>/variations/variation-b/mutations.json`; leave `variations/control/mutations.json` as `[]`.
414
+ 5. Run `apex experiments plan <folder> --json`. Blocking issues return exit 3; plan lists the rules above except apply-only refusals.
415
+ 6. Run `apex experiments apply <folder> --json`. If the test already holds QA approval, add `--accept-qa-invalidation`; without it, exit 4 requests confirmation.
416
+ 7. Apply stores the entry with `"placement": "checkout"` added; run `apex experiments apply <folder> --sync` so the folder matches the stored bytes. `apex experiments status <folder> --json` shows the QA checklist and file state, not launch blockers; the Apex dashboard shows those. The CLI validates file names; the server validates contents. `apex schema --json` prints the contract offline.
417
+
418
+ Before launch:
419
+
420
+ - Use Shopify Plus (development stores with "development" or "plus" in their plan name also pass), with the Apex app connected.
421
+ - Ask your Apex contact at Drip for the Checkout extension tests add-on and to switch on checkout tests for the store. The Apex team sets both.
422
+ - Add the Apex Checkout Experiment block in the Shopify checkout editor, normally at the information step. Apex cannot see placement directly; an unplaced block appears as a missing QA checkout. If the store offers Shop Pay, turn on "Include block in Shop Pay" for the block.
423
+ - Use production or the store's active environment and keep the store's checkout messages within Shopify's size budget.
424
+ - Open each message arm's QA link in a real checkout: `apex preview <id> <variation-id> --json --no-open` prints a signed link (treat it as a secret), or use "Preview links" in the experiment's Check panel. Add a product, go to checkout, allow analytics, marketing and sale-of-data processing if the store asks, and wait for the message. The receipt must match the current message text and test epoch. A customer approval link does not count.
425
+ - Mark QA done and launch in the dashboard. API and CLI launch are unavailable. Apex confirms delivery after launch and pauses the test if it cannot confirm the message within 30 minutes.
426
+
363
427
  ## Push config format
364
428
 
365
429
  Run `apex push -c <config>` to load a JavaScript or TypeScript config. The
@@ -452,7 +516,7 @@ experiments reject these metadata changes.
452
516
 
453
517
  Experiment references accept an ID, slug, or test key (for example `BIO-085`). Test keys resolve within the selected shop; use `--shop <shop-id>` to change it. Bare lowercase references remain slugs.
454
518
 
455
- Price, shipping, offer, and post-purchase drafts use typed `commerce/<kind>.json` files. Each file defines the lever once and maps every variation to values or `sameAsControl`; its `serverOwned` section is informational and read-only.
519
+ Price, shipping, offer, discount-code, and post-purchase drafts use typed `commerce/price.json`, `commerce/shipping.json`, `commerce/offer.json`, `commerce/discount-codes.json`, and `commerce/post-purchase.json` files. Each file defines the lever once and maps every variation to values or `sameAsControl`; its `serverOwned` section is informational and read-only. A checkout message cannot share a test with `commerce/post-purchase.json`.
456
520
 
457
521
  Filesystem apply preserves authored local bytes by default. Use
458
522
  `apex experiments apply <folder> --sync` to refresh them from stored server bytes.
@@ -645,6 +709,57 @@ store ID (or null), invitation results and partial delivery status.
645
709
 
646
710
  Upload CSV or JSON exports with `apex results import --file results.csv --dry-run`. Apex suggests column and outcome-value mappings from the file; use repeated `--map 'Column=field'` and `--outcome-value 'Source value=won|lost|inconclusive'` overrides, then pass `--yes` for non-interactive confirmation. Files are inspected and previewed before any rows are written. `--source <name>` applies to the confirmed rows; the preview shows the uploaded file name.
647
711
 
712
+ ### Read past test results
713
+
714
+ `apex results list [--source import|native|all] [--limit <n>] [--all] [--json]` lists past results for the selected shop (default source `all`, page size 50, maximum 200). Use `--all` to follow every page. The table shows legacy ID (or UUID), title, outcome, metric, lift, sample size, dates, and source. Empty lists print `No test results.`
715
+
716
+ `apex results get <legacy-id-or-id> [--json]` opens a result by legacy ID, test key, or UUID, including its full learning, confidence, dates, page, and device. Missing results exit with code 1 through the existing API failure path. Both commands use shop or user keys with `experiments:read` and verify each row belongs to the selected shop. Imports show their source name and original date range, falling back to import time; native results show source `apex` and creation time.
717
+
718
+ `apex results delete <legacy-id-or-id> [--yes] [--json]` permanently removes one imported result with `experiments:write`. It first reads the result and, outside `--json`, prints its title, outcome, dates, source, and legacy ID; with `--json --yes` it removes without printing a preview, so check the ID first (for example with `apex results get`). Native results are refused locally (exit 3). Confirm the prompt or pass `--yes`; non-TTY callers without `--yes` receive exit 4 with the exact rerun hint. Removed results cannot be restored in Apex; the full record remains in the audit log. JSON output wraps the API `{ data }` response and verifies the echoed shop.
719
+
720
+ JSON uses the standard CLI envelope: its `data` contains `{ data, pagination }` for lists (merged rows and final pagination with `--all`) or `{ data: result }` for a single result. Invalid `--source` or `--limit` exits 3 before an HTTP request.
721
+
648
722
  ### Tracking health
649
723
 
650
724
  `apex tracking health [--json]` reads one tracking-health report for the current shop: every check with pass, warn, fail or unknown, a plain summary and the deciding numbers, plus each running test's first-hour verdict and traffic split overall and per device (`--json` carries visitors per arm per day). Exit code 0 is pass, 1 is warn or fail, 3 is unknown.
725
+
726
+ ### Forms
727
+
728
+ `apex forms list` lists tracked forms and their collection status. Add a storefront form with
729
+ `apex forms add newsletter --url https://shop.example/newsletter --selector '#newsletter' --complete-on-call`.
730
+ Choose exactly one of `--complete-on-goal <goal>`, `--complete-on-page <path>`, or `--complete-on-call`.
731
+ `apex forms remove <key>` soft-removes it. Checkout is tracked automatically on Shopify.
732
+
733
+ Read analytics with `apex forms summary <key>`, `apex forms fields <key>`,
734
+ `apex forms field <key> <identity>`, `apex forms errors <key>`, or `apex forms sessions <key>`.
735
+ Reads accept `--range`, `--split`, `--device`, `--country`, `--include-qa`, and `--include-removed`.
736
+ Sessions also accept `--outcome all|completed|abandoned|in_progress`, `--field`, `--with-replay`, `--limit`, and `--cursor`.
737
+ Fields, errors, and sessions accept `--format csv|json|table`. Every command accepts `--json`.
738
+ Unavailable values print `–` (empty in CSV); `*` marks a denominator below 50.
739
+
740
+ `apex forms label <key> <identity> <text>` attaches a label; `apex forms label <key> <identity> --clear` clears it.
741
+ `apex forms merge <key> <old> <new>` combines an old identity with its replacement;
742
+ `apex forms unmerge <key> <identity>` undoes it. `apex forms detect <url>` scans a shop page without returning values.
743
+ `apex tracking manifest [manifest]` includes the shop's form definitions in a schemaVersion 1 manifest.
744
+
745
+ Flag goals: `apex flags create --key banner --name "Banner" --goal <uuid> --goal <uuid> --primary-goal <uuid>`. The same options work on `flags update <id>`; `--goal` replaces the attached set. `flags get <id>` prints goals and marks the primary goal. JSON input can clear the set with `{"goal_ids":[]}`.
746
+
747
+ ### Ready to launch notifications
748
+
749
+ Use a user API key with `team:read` / `team:write` and the shop permission `members:manage`.
750
+ Every command accepts `--shop <id>` and `--json`; otherwise the selected shop is used.
751
+
752
+ ```sh
753
+ apex notifications ready get --shop <id> --json
754
+ apex notifications ready email set --recipients a@example.com,b@example.com --shop <id>
755
+ apex notifications ready email add --recipients c@example.com --shop <id>
756
+ apex notifications ready email remove --recipients a@example.com --shop <id>
757
+ apex notifications ready email off --shop <id>
758
+ apex notifications ready slack on --shop <id>
759
+ apex notifications ready slack off --shop <id>
760
+ ```
761
+
762
+ Recipients must already be current shop members. Email `off` clears the recipient list.
763
+ Slack `off` removes only `experiment.ready_to_launch` from the existing destination's events.
764
+ Connect or resume Slack in Settings > Integrations; selecting the ready event preserves its pause state.
765
+ There is no master switch. If settings change concurrently, retry the command to read the new version.