npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@drip-apex/apex-cli

v0.19.1

Published

Apex CLI for managing experiments, approved roadmap ideas, and draft workspaces.

Readme

Apex CLI

Choosing a workflow

The default loop for agents building or editing a test is apex experiments pull, edit supported files, apex experiments plan, apex experiments apply, then apex experiments qa status.

| Workflow | Use when | What it writes | Do not use when | | --- | --- | --- | --- | | apex push | Syncing config-as-code goals, targeting, and flags by slug. | Server configuration declared in .drip.config.ts. | Editing one test's variation files or QA state. | | apex experiments pull/plan/apply | An agent is building or editing a test. This is the default. | Supported experiment files and server draft state after review of the plan. | You need a live operator code workbench. | | apex workspace | An operator needs a live-preview draft for one variation. | Workspace draft files and published draft variation code. | You need the default full-experiment agent loop. | | apex harness | An external ab-harness project needs build and QA integration. | External harness project artifacts and QA sessions. | Apex owns the experiment files directly. |

Purchase-capture verification

The CLI exposes a read-only, publication-anchored purchase verification battery:

apex shops doctor --check purchase_capture
apex tracking verify --event-type goal,conversion,purchase,checkout_completed,order_created --minutes 10080
apex install check --shop-id "$APEX_SHOP_ID"

purchase_capture reports OK, DARK, or NO_DATA; a young window or unknown historical cadence is NO_DATA, never a healthy result. Tracking verification renders compact event-property previews in human mode and preserves complete properties in --json. Install checks report the served dataLayerTriggers count and whether an enabled revenue trigger exists. --shop-id selects the shop for every install-check API request. A definite install-check or doctor failure exits 6; install-check JSON lists error.details.failed_checks.

Authentication and context

Run apex login once to authenticate your account. Interactive login opens the browser and then lets you select an organization and shop. Inspect the credential and every accessible context with apex whoami, and switch the stored default with apex use <org>[/<shop>] or apex use --org <org> --shop <shop> (IDs and unambiguous name prefixes are accepted). When authentication comes only from an environment key, apex use returns context_not_persistable with the DRIP_ORG and DRIP_SHOP values to export instead of writing a credential file.

Every command also accepts --org <id> and --shop <id>. Their precedence is command flag, then DRIP_ORG / DRIP_SHOP, then the context saved by apex use. Falling back to the stored apex use context emits one warning on stderr so scripts can see the implicit selection without corrupting JSON stdout. Flags and environment variables are explicit choices and stay silent. JSON envelopes echo the effective org, shop, and credential kind.

Automation should continue injecting a narrow shop key per process with APEX_API_KEY; it takes precedence over a stored user credential and does not change the stored login. Use apex login --api-key apx_uk_... for a headless account login or apex login --api-key apx_... to store a shop key. The old apex login --user spelling is a deprecated alias for apex login.

Command-line tools for Apex experiments, draft workspaces, GitOps pushes, QA evidence, tracking checks, and agent handoffs.

Install

npm install -g @drip-apex/apex-cli

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.

Authenticate

apex login
apex whoami

apex login opens the default browser OAuth flow at Apex /cli/login. For headless environments, use an existing API key:

apex login --api-key apx_your_key_here
APEX_API_KEY=apx_your_key_here apex experiments list --json

Common usage

apex experiments list
apex experiments list --include-archived
apex experiments create --name "Redirect test" --type redirect \
  --source-url "https://shop.example/products/source" \
  --destination "https://landing.example/products/treatment"
apex experiments pull <id-or-slug> --out ./my-test
apex experiments plan ./my-test --json
apex experiments apply ./my-test --json
apex experiments qa status ./my-test --json
apex experiments qa evidence ./my-test --file ./desktop.png --device desktop
apex experiments qa evidence <id-or-slug> --job <screenshot-job-id>
apex experiments screenshots <id-or-slug> --out ./screenshots

apex workspace checkout <experimentId> --variation <variationId> --out ./workspace
apex workspace dev ./workspace --no-open
apex workspace publish ./workspace

apex push --dry-run
apex schema --json

Use apex as the canonical command name. drip is a compatibility alias.

apex experiments list returns code-free summaries by default, including targeting_urls and variation_count, without targeting objects, variations, or goals. Use --full --json for full details, including code. --full keeps the default table unchanged. Use --fields id,test_key,name,status --json to select top-level keys (JSON always keeps id), or --fields status,name to print exactly those table columns in order. --fields and --full can combine; invalid fields return the allowed keys. Existing CR-011 filters still narrow the set; these flags only select row content. The direct API retains its full default view; the CLI requests view=summary. Summary timestamps include created_at and archived_at; experiments have no updated_at field.

apex experiments list hides archived experiments by default. Pass --include-archived to include them; archived rows display their archive date when the API provides archived_at.

JSON output contract

With --json, or whenever stdout is piped, stdout carries exactly one JSON document and nothing else. Spinners, progress, prompts, warnings, human text and child-process output go to stderr, so apex ... --json | jq always parses.

{ "ok": true, "version": "0.13.0", "command": "apex flags get", "data": {}, "context": {} }
  • data is the API response body exactly as the API returned it for every command backed by one API request. Lists keep the API's { "data": [...], "pagination": {...} } shape, so rows are at .data.data[]; single resources are at .data directly.
  • apex experiments get adds one CLI-derived key, dashboard_url, beside the experiment fields.
  • Commands that combine several requests or local files (experiments create, pull, plan, apply, qa approve, triggers, project-code, harness, workspace, doctor, whoami, push, analytics urls, flags status, goals test) print a documented CLI-composed data object.
  • Failures print { "ok": false, "version", "command", "error", "context" }. error.code is the CLI exit code, error.details carries retry hints and server details, and error.api is { "status", "body" } with the API error envelope verbatim whenever an API response caused the failure.
  • deprecated appears on the envelope only when a deprecated flag was used.

Breaking in 0.13.0. Earlier releases re-nested or renamed API bodies. Update scripts: .data.experiments[] becomes .data.data[]; experiments get .data.experiment.id becomes .data.id; .data.flag, .data.goal, .data.funnel, .data.signal, .data.backlog_item, .data.personalization, .data.exclusion_group, .data.asset, .data.landing_page, .data.webhook, .data.targeting and .data.verification wrappers are gone (read the fields at .data); experiments results reads at .data instead of .data.results, funnels run at .data instead of .data.run, and brand at .data.data instead of .data.brandContext; lifecycle and delete commands return the API's body instead of a CLI summary.

Command index

Use apex schema --json to emit the complete machine-readable command surface, including every subcommand, argument, option, and alias.

Authentication and account

  • apex login — authenticate with a shop or user API key.
  • apex logout — remove stored credentials.
  • apex whoami — inspect the current credential and its validity.
  • apex use — select the current organization and shop context.
  • apex upgrade — install the latest Apex CLI; --dry-run prints the command.
  • apex account — manage the current user profile.
  • apex keys — manage shop API keys.
  • apex org — inspect and manage the organization.
  • apex team — manage shop-scoped members and invitations.

Experiments and delivery

  • apex consent — manage consent gating.

  • apex project-code — inspect and safely change shop project code.

  • apex project-code get — read complete code and its opaque version.

  • apex project-code diff — preview a partial JSON change without writing.

  • apex project-code set — create a backup before a version-checked write.

  • apex triggers — manage data-layer triggers and temporary setup capture.

  • apex triggers get --shop <domain-or-id> — read the identified shop's runtime triggers.

  • apex triggers set — replace the shop's runtime triggers from a JSON file.

  • apex triggers propose — propose candidate triggers from a discovery report.

  • apex triggers apply-recipe — apply a server-owned trigger recipe.

  • apex triggers enable-capture — enable temporary setup capture.

  • apex triggers disable-capture — disable setup capture and clear its expiry.

  • apex domains — manage install domains, and landing-page domains (claim, register, status, unclaim; registering asks for a price confirmation).

  • apex handover — manage cross-domain identity handover.

  • apex install — check storefront installation and generate a client guide.

  • apex install kit — print a ready-to-send installation guide as Markdown or JSON.

  • apex install check — verify the snippet, served config, and recent tracking.

  • apex install steps — show each installation step with when Apex first and last saw it (--live also checks the page and firewall access).

  • apex funnels — manage analytics funnels.

  • apex webhooks — manage shop webhooks.

  • apex simulate — simulate data-layer triggers without emitting events.

  • apex experiments status [folder-or-id] — read context, file versions, QA, and handover next steps without writing. Defaults to the current pulled folder.

  • apex experiments — create, inspect, operate, and synchronize experiments.

  • apex results — inspect, preview, and import historical CSV or JSON test results. Use apex experiments screenshots <id-or-slug> to force-assign every capture, including control, to its variation server-side for deterministic screenshots. Resume a job that outlives the CLI timeout with --job <id>; polling continues without creating another job, and the stored job's devices and variations win, so --devices/--variations are ignored (the CLI warns). The command attaches terminal jobs to the QA run by default; use --no-attach-qa to opt out. Choose devices with --devices, filter treatments with --variations, and use --json for the signed result payload. Use apex experiments qa evidence with --job, repeatable --file, or --records to write QA evidence directly.

  • apex commerce — look up Shopify products, live prices and costs for commerce drafts.

  • apex push — synchronize .drip.config.ts with Apex.

  • apex preview — open a variation QA preview; --proxy returns a qa_run receipt. Its automated_evidence_count counts the normalized evidenceRecords across all evidence kinds, matching the list shown by apex experiments qa status.

  • apex roadmap — consume approved roadmap ideas and handoffs.

  • apex harness — develop AB Test Harness projects with live QA sessions.

  • apex workspace — check out, preview, and publish draft workspace files.

  • 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.

  • apex flags — manage feature flags.

  • apex surveys — list, get, create, update, start, pause, complete, duplicate, and delete surveys. Use apex surveys list --status live to filter, and apex surveys create @survey.json or apex surveys update <id> <body> with inline JSON, @file, or a file path. Both create and update also accept --file survey.json instead of a positional body; providing both is an error. Their --help pages include the example and field defaults below. --json returns the server body unchanged under data; publication warnings go to stderr. Deleting a live or paused survey returns conflict exit code 5. Complete it before deleting.

    Example survey.json for apex surveys create --file survey.json or apex surveys update <id> --file survey.json:

    {
      "name": "Product feedback",
      "questions": [{
        "type": "single_choice",
        "prompt": "What would help you decide?",
        "options": [{"label": "More details"}, {"label": "Reviews"}, {"label": "Delivery info"}]
      }],
      "targeting": {"url": [{"type": "simple", "pattern": "/products/", "matchType": "contains"}]},
      "sampling_rate": 0.5,
      "frequency_cap": "once_per_visitor",
      "card_style": "quiet",
      "answer_goal": 100
    }

    On create, name is required. Server defaults: questions: [] (each question's required: true), targeting: null (all pages/visitors), sampling_rate: 1, frequency_cap: "once_per_visitor", card_style: "quiet", answer_goal: null, environment_key: "production", placement: "sdk_page", active_from: null, and active_to: null. Update accepts a partial body and keeps omitted fields unchanged.

  • apex personalizations — manage personalization deliveries.

  • apex backlog — manage experiment backlog items.

  • apex signals — inspect research and opportunity signals.

Analytics, targeting, and tracking

  • apex tracking — diagnose storefront tracking.
  • apex events — export raw tracking events.
  • apex events export — export all raw events in a fixed ISO 8601 window with automatic pagination.
  • apex environments — inspect delivery environments.
  • apex analytics — read shop analytics.
  • apex pages — manage page targeting resources. Body keys are listed in apex pages create --help (and update --help); the CLI refuses a url_pattern or rule pattern whose shape contradicts match_type (match_type_mismatch) unless --literal is passed. apex schema --json carries the body schema.
  • apex segments — manage audience segments.
  • apex exclusion-groups — manage mutually exclusive experiment groups.
  • apex targeting — inspect targeting evaluation and coverage.
  • apex audit-log — inspect auditable account activity.
  • apex inbox — use the operator inbox.

Shop configuration and operations

  • apex external-pixels — manage external pixel snippets.
  • apex assets — manage uploaded assets. Upload returns delivery_url; embed that permanent URL in variation code. public_url expires after 300 seconds. Delivery is anonymous once the referencing experiment or snippet is published, and resolves through the owning shop's dashboard session or a QA preview before that. Only the absolute https form is recognized as an owned reference; protocol-relative or http forms are not granted at publication.
  • apex landing-pages — build landing pages with your own tools, then apply, preview, deploy and roll them back.
  • apex brand — manage brand context.
  • apex shops — manage shops and active-shop context.
  • apex skills — inspect agent skill guidance.
  • apex schema — emit the machine-readable CLI schema.
  • apex discover — read observed tracking shapes or mine a public GTM container.

Platform-administrator shop commands are intentionally outside the public command inventory:

| Command | Purpose | | --- | --- | | apex admin customers move-stores | Platform admin: --to <org-id> --shop <shop-id> (repeatable), --reason <text>, optional --keep-grants. Returns a dry-run plan by default; --confirm performs the audited move. Supports --json. | | apex admin customers set-category <org-id> | Change an existing account to internal, demo, dogfood or customer with a platform user key. Requires an 8 to 500 character --reason and --confirm. | | apex admin customers create | Create internal, demo or dogfood accounts with a platform user key. Requires --name, --category, an 8 to 500 character --reason, and --confirm. | | apex admin shops archive <shopId> | Archive a shop and disable Apex delivery; use --force in non-interactive environments. | | apex admin shops restore <shopId> | Restore an archived shop while leaving its runtime kill switch unchanged. | | apex admin shops settings list --shop <uuid-or-domain> | Read every registered per-shop setting, value, override and group with a platform user API key. | | apex admin shops settings get --shop <uuid-or-domain> --key <key> | Read one setting; unknown keys list the available registry keys. | | 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. |

Landing pages built outside Apex

A landing page is built in a checkout folder by any tool (Claude Code, Codex, a static-site build); Apex keeps its versions, goals and deploys.

apex landing-pages create --name "Fall sale" --out ./fall-sale   # or: pull <id> --out ./fall-sale
# edit ./fall-sale/index.html and its assets; context/ holds brand, catalog, offers and reviews
apex landing-pages plan ./fall-sale             # what would change
apex landing-pages apply ./fall-sale --yes      # new version + signed preview link (24 hours)
apex landing-pages deploy ./fall-sale           # live on <shop>.apex-page.com, or the host in apex-landing-page.json
apex landing-pages rollback ./fall-sale --version 1
apex landing-pages experiment ./fall-sale --control 1 --variant 2   # draft split; start it in the dashboard

The folder holds the page files (index.html at the root, at most 300 files and 100 MB; html, css, js, json, svg, images, fonts, txt, xml, webmanifest, mp4 and webm), apex-landing-page.json and the context/ folder (each pull replaces its JSON files with the server's current set). Build with relative asset URLs (Vite base: "./"). apex-landing-page.json sets the name, slug, an optional host, a domain claimed with apex domains claim <host> (without one, or --host, a deploy goes to the shop's own instant host <shop>.apex-page.com), the path (default /<slug>), whether Apex injects the shop snippet (snippet, on by default), the shop_hosts that receive the visitor's identity on outbound links (default: the shop's install domains), the goals (key, name, type click, pageview or custom) and an optional experiment (control and variant version numbers). Apply refuses to run without --yes when no terminal can confirm, and refuses with exit 5 when the page changed since the pull (--force replaces it anyway). Pull refuses to overwrite a checkout with changes that are not applied, or a folder's own files that are not a checkout (exit 5; --force discards or replaces them). A deploy makes the page's goals match apex-landing-page.json, so a goal edited in the dashboard is reset. A deploy or rollback while an experiment splits the page keeps serving the experiment's two arms and leaves its goals as they are (new manifest goals are added); the deployed version serves when the experiment ends, and its goal changes apply at the next deploy after that.

Which local format am I in?

Inspect the marker under .apex/: experiment-filesystem.json means the folder belongs to apex experiments pull/plan/apply, landing-page.json means an apex landing-pages checkout, while session.json means it is an apex workspace checkout/status/publish workspace. Keep the two formats in different folders; when the wrong command is run, Apex points to the matching status command.

Page targeting: URL rules and Pages

Page targeting has two supported authoring paths, and both stay supported.

| Key in targeting | What it is | | --- | --- | | url | An array of URL rules: { "type": "simple" \| "regex", "pattern": "/products/*", "include": true, "matchType": "exact" \| "contains" \| "wildcard" \| "regex" }. | | authorUrl | Read-only, and present on every pull. The subset of url that an author wrote, recorded by the server; an empty array means no author-written rules. An apply ignores it and the server recomputes it. | | pages | An array of { "id": "<page id>", "include": true } references to saved Pages. | | pageRules | Read-only. The server's expanded copy of each referenced Page, including its name and its own URL rules. | | pageMatchMode | "any" (default) or "all" when more than one Page is referenced. |

URL rules work without a saved Page. apex experiments create --source-url and a hand-written url array in targeting.json are complete targeting on their own. Nothing rejects them, and no Page is required.

An included Page decides where the test runs. At runtime the URL gate and the page-rules gate must BOTH match, but the URL gate is an OR over the whole expanded url list, and a Page referenced with "include": true copies that Page's own include rules into url. A visitor on the Page therefore passes the URL gate through the derived copy even when no authored include rule matches, so while an included Page is referenced your authored INCLUDE rules add no pages. A Page referenced with "include": false contributes only an exclude rule, so it can only veto and your authored INCLUDE rules still provide the positive match. Authored EXCLUDE rules always apply, and detaching an included Page gives the authored rules the decision back.

apex experiments get prints the result of those two rules as one Targeting: line, in the same words the dashboard Setup tab uses, for example 2 URL rules (no saved Page) or Cart page and 1 URL rule.

In a pulled targeting.json, url is the expanded rule set and authorUrl is the authored subset, always present. Edit url and pages; treat authorUrl and pageRules as output.

Push config format

Run apex push -c <config> to load a JavaScript or TypeScript config. The module's default export may be an experiment array, an object with an experiments array, or one experiment object. TypeScript (.ts or .tsx) is compiled and bundled on the fly with esbuild into a temporary ESM module; JavaScript (.js, .mjs, or .cjs) is imported directly.

Each experiment accepts these fields:

| Field | Format and mapping | | --- | --- | | slug | Required string and unique within the config; identifies the upsert. | | name | String sent as the experiment name. | | id | Optional string accepted in the config; it is not sent by push. | | trafficAllocation | Optional number sent as traffic_allocation; defaults to 1. | | targeting | Optional value sent as targeting; defaults to null. | | variations | Array of variation objects described below. | | goals | Optional array of { id: string }, mapped to goal_ids. | | description | Optional string; defaults to null. | | storeUrl / store_url | Optional string aliases sent as store_url; camelCase wins when both are present. |

Each variation accepts:

| Field | Format and mapping | | --- | --- | | id | Optional string, used as the fallback slug and name. | | slug | Optional string; falls back to id. | | name | Optional string; falls back to id, then "Unnamed". | | weight | Number sent as the variation weight. | | isControl / is_control | Optional boolean aliases; defaults to false. | | mutations | Optional array; defaults to []. | | css / custom_css | Optional string aliases sent as custom_css; defaults to null. | | js / custom_js | Optional string aliases sent as custom_js; defaults to null. | | resetJs / reset_js | Optional string aliases sent as reset_js; defaults to null. | | antiFlickerSelectors / anti_flicker_selectors | Optional string-array aliases; defaults to []. |

Push validates only that every experiment has a truthy slug, that slugs are not duplicated within the loaded config, and that the top-level export has one of the accepted shapes. It does not runtime-validate the other field types, required TypeScript fields (name, variations, or variation weight), nested goal/variation shapes, value ranges, or API-level constraints. The command upserts each experiment by slug with PUT /api/v1/experiments/by-slug/:slug; an existing slug is updated and a new slug is created.

Full documentation

Read the CLI reference on the docs site:

  • https://docs.drip-apex.com/cli/install-auth
  • https://docs.drip-apex.com/cli/commands-output

Maintainers: see the CLI release runbook.

Project code

apex project-code get --shop example.com --json
apex project-code diff --file project-code.json --shop example.com --json
apex project-code set --file project-code.json --shop example.com --backup previous-code.json --json

The input is a partial projectCode object, for example { "css": "body { color: red; }" }. Supported fields are enabled (boolean) and css, helperJs, and js (strings or null). Each code field permits at most 20,000 characters. Omitted fields remain unchanged. Null or blank code clears that field. Unknown fields and empty objects are rejected.

GET returns complete code, shop identity, and an opaque version. DIFF returns effective before/after values and changed fields without writing. SET creates a new backup file with complete previous code, identity, capture time, and the exact version before PATCH. It never replaces an existing backup. Backup failures prevent the write. An effective no-op returns unchanged, without a PATCH or backup file.

The backed-up version becomes expectedVersion unchanged. A conflict returns exit 5, keeps the backup, and does not retry. Read the latest state and preview it before a new attempt with a new backup path. Authentication uses exit 2; invalid input uses exit 3. A successful write returns saved, its diff, backup path, current version, writtenVersion, and precompile result. A failed precompile is a saved-write warning. All warnings remain in JSON and are also written to stderr. User keys resolve domains or pin UUID context; shop keys must match the requested identity before any backup or write.

Classification uses --counting-type standard|setup_test|aa_test|non_program on apex experiments create (default standard) and apex experiments update. Classification writes are draft-only. In pulled experiment.json, experimentType and countingType equal delivery_type and counting_type from apex experiments get --json. Omitting or setting countingType to null preserves the stored value. Classification edits invalidate QA approval; paused and running experiments reject these metadata changes.

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.

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.

Filesystem apply preserves authored local bytes by default. Use apex experiments apply <folder> --sync to refresh them from stored server bytes. The receipt's files includes per-file normalizations and submitted_sha256 (null for unsubmitted files), alongside SHA-256 digests for every stored pull path; synced reports whether a full refresh succeeded. Server-owned QA and launch files are healed. JSON bodies and checkout JSON files accept a leading UTF-8 BOM, including PowerShell-written files. Create/get return dashboard_url; apply returns dashboardUrl. These links switch the signed-in dashboard user's active shop before opening the experiment.

Filesystem apply caches uploaded asset URLs by byte SHA-256 in .apex/experiment-filesystem.json, so unchanged images reuse their URL across applies without rewriting authored files.

--instructions cannot be combined with --out (or its legacy alias --output); file exports always contain the full JSON contract.

Roadmap handoff JSON identifies itself as apex.roadmap_handoff.v1; backlog get/list items identify themselves as apex.backlog_item.v1, both with schema_version: 1. The handoff embeds the same closed item projection that backlog responses serve alongside their existing raw fields. Published schemas and fixtures live in docs/contracts/experiment-os. Breaking changes require a new v2 contract; the backlog version is a separate optimistic concurrency token.

| Key | Source | | --- | --- | | approval | Roadmap decision status (proposed without a decision), item stage, and decision's nullable decided_at. Top-level status remains the item lifecycle status. | | goals | apex_goal_id is the linked experiment goal or null. |

QA status creates a run only when none exists. Reading an existing run never writes to it: updatedAt is its last stored mutation time, while computedAt is the ISO timestamp when the current checklist and summary were computed.

Decision latency

apex tracking latency <experiment-id-or-key> [--days <1..30>] [--qa-session <id>] [--json] compares forced-preview and natural decision latency before launch. The default window is seven days. The table shows sample counts, decision p50/p95/p99, config-fetch p50/p95 (milliseconds), and inline/cache/network/none counts. JSON output includes the API body in the standard envelope and assignment-ready percentiles. Fewer than five measured samples have null percentiles. Natural loads are shop-wide non-QA loads without forced IDs; a QA-session bucket can overlap forced loads. Analytics failures return errors. The API position is runtime_inline_no_change.

The runtime remains unchanged. Natural runtime decides within tens of milliseconds of SDK start when config ships inline with the snippet (measured p50 12 ms / p95 54 ms on a large storefront). QA previews, screenshot-mode previews and cookie-forced sessions take the QA config lane and fetch fresh config over the network (measured p50 1.3 s / p95 7 s); they are not representative of launch behaviour. URL-forced sessions without a qa parameter keep the inline or cached config, so these measurements do not describe them. No config preload or anti-flicker hold is planned.

Connection troubleshooting

Connection errors retain the underlying failure. JSON output exposes error.details.reason and, when available, error.details.code; the numeric error.code remains the CLI exit code.

| Reason | Meaning and usual fix | | --- | --- | | dns | The host could not be resolved. Check APEX_BASE_URL (or DRIP_BASE_URL), DNS, and whether your sandbox permits network access. | | refused | The host rejected the connection. Check the base URL, port, and whether the server is running. | | reset | The connection was interrupted. Check network stability and proxy settings before retrying. | | tls | Certificate or TLS validation failed. Check expired certificates and your corporate TLS proxy's trusted CA configuration. | | timeout | The request was aborted or exceeded its deadline. Check server availability and network access. | | unknown | Another network failure occurred. Use the included cause message to diagnose network or sandbox restrictions. |

Read-only order journey

apex analytics order-journey --platform shopware --order-id <id> --environment production --from <iso> --to <iso> --json

Requires analytics:read through a secret or authorized user key. Supply exactly one of --order-id or --order-number, an explicit environment and an ISO interval of at most 31 days. --include-qa includes QA eligibility; bots remain excluded. The sanitized report includes all represented assignments and discloses incomplete coverage. Source failures and historical consent/fingerprint gaps remain unknown. Exit 0 means the report was fetched, not that the journey passed. eligible_for_attributed_goal_read uses only attributed_goal_counts; finalStatisticalContribution is always not_evaluated. Nothing is repaired or saved locally.

Order journey diagnostics report current, stale, or unknown freshness for each retained receipt and assignment. Present attributed-goal reads identify their evaluated snapshot; they do not establish historical contribution or repair missing producer evidence.

Error recovery and update notices

JSON errors keep the numeric error.code exit code and add error.reason, error.next_steps (an array of { command, why }), and optional error.request_id. The request ID comes from x-request-id, falling back to x-vercel-id (the Apex app) and then cf-ray; include it when reporting an API failure. API-provided reason codes are preserved verbatim. Otherwise reasons are auth_required, auth_forbidden, shop_context_required, shop_context_mismatch, install_check_failed, validation_failed, confirmation_required, conflict, not_found, rate_limited, network_timeout, network_connect_timeout, network_dns, network_refused, network_reset, network_tls, network_unknown, local_file_error, or internal_error.

Inspect next_steps for login, key permissions, shop selection, network settings, folder validation, or rate-limit recovery. Steps are suggestions, never automatic approval to retry a write. Confirmation errors retain error.details.retry. Human output prints recovery steps as Next: lines on stderr and request IDs on the error line. Trigger commands now follow the same exit codes as every other command: authentication failures exit 2 (previously 4), invalid local input exits 3 (previously 2), and other API failures follow their HTTP status (validation 3, conflict 5, anything else 1). The TRIGGERS_AUTH, TRIGGERS_CONFIG_ABSENT and TRIGGERS_NO_DATA verdict prefixes are unchanged, so scripts can key on them instead of exit codes.

Every JSON envelope may carry update and warnings. The update object includes current, latest, optional minimum, required, breaking, command, and notes_url; warnings use { code, message }. The exact install command is npm install -g @drip-apex/apex-cli@latest, and apex upgrade runs it (--dry-run only prints it). Set APEX_NPM_BIN to choose the npm binary.

The npm latest version is cached for 24 hours (failed lookups for one hour). Server latest/minimum policy is cached for seven days, so offline commands still enforce a known floor. APEX_NO_UPDATE_CHECK=1 disables the npm lookup and optional update notice, but never hides a required server-floor upgrade.

Windows: UTF-8 arguments

A Windows console or launcher can decode UTF-8 as Windows-1252, turning A – B · C into A – B · C. On Windows, Apex automatically repairs reversible argument values at startup and writes a note to stderr. Set APEX_ARGV_ENCODING=off to keep arguments unchanged, or APEX_ARGV_ENCODING=repair to enable repair on another platform.

Use UTF-8 in PowerShell:

[Console]::InputEncoding = [Console]::OutputEncoding = [Text.Encoding]::UTF8

For Git Bash, set LANG=C.UTF-8 and run chcp 65001.

A replacement character (�, U+FFFD) means the shell already lost a character. Apex sends that value as given and warns on stderr. It also warns when stored experiment names, descriptions, variation names, or goal names contain U+FFFD. These notes leave JSON stdout unchanged.

Usage telemetry

Authenticated invocations send a process invocation ID, full command path, explicitly set option names (never values), JSON/TTY modes, credential kind, organization/shop IDs, CLI/Node versions, platform, exit code, error class and code, API response count, the first failed response's status/code/request ID and normalized route, and total duration. Up to the first 25 API calls include their method, normalized route, status, duration, and bounded Server-Timing header. Requests whose path contains an experiment or landing-page UUID also send that UUID and its entity type; slugs are not captured.

Help commands are named (help) <full command path>. Parse failures are named (parse) and send the known command path plus only a mistyped subcommand as attempted. Potential credentials, URLs, paths, long keys, and other sensitive-looking attempted tokens are redacted; positional argument values are never sent.

Agent hosts can be reported as a fixed label such as claude-code, codex, or terminal, never as an environment value. Set APEX_AGENT_HOST to one of claude-code, codex, cursor, grok, gemini, copilot, or other to override automatic detection. APEX_SESSION_ID may supply a 1–128 character identifier containing letters, digits, dots, underscores, colons, or hyphens; choose a non-secret value. When that variable is absent or invalid, supported agent session IDs are SHA-256 hashed locally and only the h_-prefixed first 32 hexadecimal characters are sent.

No argument or option values, file contents or paths, prompts, selectors, URLs, error text, environment values, raw agent session IDs, or secrets are sent. Login/logout, tests, the mock transport, and runs with no resolvable credentials (neither stored nor environment) skip telemetry. Environment-credential runs (APEX_API_KEY or DRIP_API_KEY) are recorded with credential kind env unless APEX_TELEMETRY=0. Set APEX_TELEMETRY=0 to disable the beacon. The best-effort request has an 800 ms timeout and never changes command output or exit status.

MP4 (video/mp4) and WebM (video/webm) videos are hosted directly by Apex. Each version holds at most 300 files and 100 MB; each video is limited to 50 MB, and other files to 3 MB. apply automatically obtains a 15-minute upload grant for videos above 3 MB and sends resumable 8 MB parts straight to the Worker, retrying failed parts with progress output. The Worker verifies the declared size and SHA-256 before apply records the file. Pull and signed previews also fetch large videos directly from the Worker. Video supports byte ranges, including Safari's bytes=0-1 probe; rollback preserves the older bytes.

Engineering account creation uses apex login --user credentials with admin:write and a live platform role with onboarding write permission. Real customer accounts are created in Admin, Links.

apex admin customers create --name "Demo workspace" --category demo --reason "Workshop demo account" --confirm --json
apex admin customers create --name "Dogfood store" --category dogfood --domain dogfood.example.com --platform woo --owner [email protected] --reason "Engineering dogfood account" --confirm
apex admin customers set-category 22222222-2222-4222-8222-222222222222 --category internal --reason "Engineering dev store" --confirm --json

--type defaults to company (company|agency); --plan defaults to self_managed (self_managed|apex_managed|drip_managed). Managed plans require --consultant <platform_access UUID> and --consultant-title <text>. An optional first store uses --domain <host> --platform <shopify|shopware|woo|other> or --claim-shop <UUID>, exclusively. woo maps to woocommerce and other to custom. --owner <email> sends an owner invitation and requires a store; accounts without a store have no invitations. Output includes the organization ID, store ID (or null), invitation results and partial delivery status.

Import past results

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.

Tracking health

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.