CLI Setup
The LaunchMyStore CLI (lms) helps you create, develop, test, and deploy apps,
extensions, and functions from the command line. The CLI is a Node 18+ ESM
package that talks to the LaunchMyStore API and signs webhooks locally for
end-to-end development.
@launchmystore/cli@2.0.3 is live. Functions compile to WASM on
your machine using Bytecode Alliance Javy;
the server only validates that uploads are Javy dynamic-mode modules — it
never runs your source through a compiler. lms extension push -t now
accepts the developer-friendly type names emitted by lms extension generate
(theme_block, function_payment, etc.) and maps them to the canonical
upload types automatically.Installation
Requires Node.js 18 or higher. To build functions you’ll also need Javy v3+ on yourPATH
(or pointed to by the JAVY_BIN_PATH environment variable).
The flag is
--cli-version (not --version) so it doesn’t collide with
the subcommand-level --version <semver> flag used by lms app version
and lms app deploy.Authentication
The CLI authenticates with email and password and stores a refreshable credential bundle in~/.lms/credentials.json (override the directory with the
LMS_CONFIG_DIR environment variable).
Project Configuration
After you scaffold an app, the CLI walks up from your current working directory looking for a.lmsrc.json file. This file binds the local project to a
specific app in the developer dashboard so subsequent commands know which app
they’re operating on.
.lmsrc.json
--app flag to
target a specific app explicitly. Without it, they fall back to the appId in
the nearest .lmsrc.json.
Quickstart
Create an app
Pick a template (
node, react, or extension-only). The CLI registers
the app, scaffolds the project, and writes .lmsrc.json + .env.Templates
lms app create can scaffold one of three starter templates. Pass
--no-template to skip scaffolding and only register the app remotely.
| Template | What you get |
|---|---|
node | Node + Express server with /auth/callback and /webhooks routes |
react | Vite + React, wrapped in @launchmystore/app-bridge-react’s AppBridgeProvider |
extension-only | No backend — just an extensions/blocks/example/ skeleton for theme/checkout extensions |
Commands Reference
Auth
| Command | Description |
|---|---|
lms auth login --email <email> --api-base <url> | Email/password login. Writes ~/.lms/credentials.json |
lms auth logout | Clear stored credentials |
lms auth whoami | Show the currently signed-in developer |
App
| Command | Description |
|---|---|
lms app create [--name] [--handle] [--no-template] [--force] | Register an app via POST /apps/developer/create, optionally scaffold a template |
lms app list | List apps you own |
lms app info [appIdOrHandle] | Show details for one app (defaults to the project’s .lmsrc.json) |
lms app dev [--port 3000] [--cmd "npm run dev"] [--watch <dir>] [--no-tunnel] [--no-update-urls] | Run local dev server, open a Cloudflare tunnel, watch extensions/, update redirect URLs |
lms app deploy --version <semver> [--app] [--notes <text>] [--notes-file <path>] [--no-publish] | Wraps version create + version publish in one step |
lms app rollback <installationId> <targetVersion> | Roll a single installation back; pins the install and disables auto-update |
lms app resume-auto-update <installationId> | Re-enable auto-update on a pinned installation |
App Versions
| Command | Description |
|---|---|
lms app version create --version <semver> [--app] [--notes <text>] [--notes-file <path>] | Create a new version |
lms app version publish <version> [--app] | Publish a created version |
lms app version deprecate <version> [--app] | Mark a version as deprecated |
lms app version list [--app] | List all versions |
lms app version stats [--app] | Show install + rollout stats |
Function
| Command | Description |
|---|---|
lms function build -f src/function.js -o dist/function.wasm [--emit-wrapped <dir>] | Compile a JavaScript function to a Javy dynamic-mode .wasm artifact, locally |
lms function test [-f src/function.js | --wasm <path>] [-t <type>] [--input <json>] [--input-file <path>] [--timeout <ms>] | Run a function against the hosted sandbox. Compiles locally first unless --wasm is given |
lms function deploy [--app] [-f src/function.js | --wasm <path>] [-h <handle>] [-t <type>] [--fallback skip|fail] | Build (if needed) then upload a pre-built .wasm artifact and register the handle |
lms function list [--app] | List functions registered for the app |
lms function logs <handle> [--app] [--limit] [--page] | Tail/page execution logs for a function |
Extension
lms extension generate is a local-only scaffolder. Functions are written to
functions/<handle>/ and all other extension types to extensions/<handle>/.
| Command | Description |
|---|---|
lms extension generate [-t <type>] [-h <handle>] [--dir <path>] | Scaffold an extension locally. Types: theme_block, storefront_snippet, checkout_ui, post_purchase, admin_block, function_shipping, function_payment, function_delivery, function_cart_transform, function_order_validation, function_discount |
lms extension list [--app] | List extensions registered to the app |
lms extension push --name --handle --type --target --path [--update] [--app] | Multipart upload of files. Types: app_block, theme_embed, admin_block, checkout_extension, app_script, app_function |
lms extension remove <handle> [--app] | Remove an extension from the app |
Webhook
| Command | Description |
|---|---|
lms webhook list [--limit] [--page] [--status] [--topic] | List webhook deliveries with filtering |
lms webhook retry <deliveryId> | Re-send a single delivery |
lms webhook trigger <topic> [--url <url>] [--port 3000] [--secret] [--payload <json>] [--payload-file <path>] | Generate a sample payload, sign with HMAC-SHA256, POST to a local URL |
Billing
| Command | Description |
|---|---|
lms billing list [--app] [--status] [--limit] [--page] | List subscriptions / charges for the app |
lms billing summary | Aggregate revenue summary across your apps |
lms billing pricing --monthly <amount> --yearly <amount> [--app] [--currency USD] | Set pricing in major units (e.g. 9.99); converted to cents server-side |
Versioning
Use theapp version subgroup to ship releases. The CLI separates
create (uploads the artifact + metadata) from publish (makes it available to
merchants), so you can stage a build and review it before promoting.
lms app deploy --version 1.2.0.
For the full lifecycle — auto-update channels, deprecation policy, rollback —
see App Versioning.
Local Function Compilation
Functions ship as Javy dynamic-mode WASM modules. Your JavaScript is compiled on your machine into a tiny stub (typically 1–4 KB) that links against a shared QuickJS runtime (“provider”) at execution time — so each compiled function only carries your code, not a copy of the runtime. The server never runs your source through a compiler. It receives a pre-built.wasm, validates the import section to confirm it’s a Javy
dynamic-mode build, then stores it.
Build a function
| Flag | Description |
|---|---|
--emit-wrapped <dir> | Write the wrapped source the CLI handed to Javy. Handy for debugging compile errors. |
javy isn’t on your PATH, point at it explicitly:
Test against the sandbox
lms function test either compiles locally first (-f) or uploads a
pre-built artifact (--wasm), then runs it against the hosted sandbox
without persisting anything. The fastest way to iterate.
discount, shipping_rate, payment_customization,
order_validation, cart_transform, delivery_customization.
Deploy to your app
Function source contract
Export arun (or main) function that takes the input object and returns
the output object — the CLI wraps your source with the stdin/stdout bridge
expected by Javy:
module.exports = fn, function main(input) {}, or
exports.default = fn for compatibility with different bundler outputs.
Size limits
| Limit | Default | Override env |
|---|---|---|
| JavaScript source | 64 KB | LMS_FUNCTION_MAX_SOURCE_SIZE |
| Compiled WASM | 256 KB | LMS_FUNCTION_MAX_COMPILED_SIZE |
Local Webhook Testing
The CLI can simulate the production webhook dispatcher locally. It generates a realistic sample payload for the topic, signs it with HMAC-SHA256 using your client secret, and POSTs it to your local URL with the same headers your production server will receive:X-LMS-Topic, X-LMS-Webhook-Id,
X-LMS-Delivery-Attempt, X-LMS-Hmac-SHA256.
Configuration
The CLI reads project config from.lmsrc.json and credentials from
~/.lms/credentials.json. You can override the credentials directory globally
with LMS_CONFIG_DIR — useful for keeping work and personal accounts separate,
or for sandboxing CI.
Environment Variables
| Variable | Description |
|---|---|
LMS_API_BASE | Override the default API base (https://api.launchmystore.io) |
LMS_CONFIG_DIR | Override the credentials directory (default ~/.lms/) |
LMS_CLIENT_SECRET | Fallback HMAC secret used by lms webhook trigger when --secret is omitted |
JAVY_BIN_PATH | Absolute path to the javy binary if it isn’t on your PATH |
LMS_FUNCTION_MAX_SOURCE_SIZE | Override the JavaScript source size cap (default 65536) |
LMS_FUNCTION_MAX_COMPILED_SIZE | Override the compiled WASM size cap (default 262144) |
PORT | Forwarded into npm run dev from lms app dev |
Troubleshooting
'lms' command not found
'lms' command not found
Make sure your npm global On macOS with Homebrew Node, this is usually
bin directory is on your PATH:/opt/homebrew/bin. On
Windows, it’s typically %APPDATA%\npm.Authentication expired or invalid
Authentication expired or invalid
Long-lived sessions can be invalidated by a password change or admin
revoke. Re-authenticate:
`lms app info` / `lms extension *` return 401 Unauthorized
`lms app info` / `lms extension *` return 401 Unauthorized
`lms extension push --type theme_block` rejected as invalid type
`lms extension push --type theme_block` rejected as invalid type
Fixed in
@launchmystore/cli@2.0.3 — the developer-friendly type names
from lms extension generate (theme_block, storefront_snippet,
checkout_ui, post_purchase, and all six function_* variants) now
map automatically to the canonical upload types (app_block,
checkout_extension, app_function). Upgrade with
npm install -g @launchmystore/cli@latest and verify with
lms --cli-version.Tunnel won't start in 'lms app dev'
Tunnel won't start in 'lms app dev'
lms app dev uses the cloudflared package. Make sure port 3000 is free
(or pass --port), and that no firewall is blocking outbound connections
to Cloudflare. To run without a tunnel — for example when your dev server
is already publicly reachable — pass --no-tunnel and --no-update-urls.Commands can't find my app
Commands can't find my app
Most commands resolve the active app from
.lmsrc.json walked up from
cwd. If you’re outside the project directory, pass --app <handle> (or
--app <appId>) explicitly.Javy compiler not found
Javy compiler not found
lms function build calls out to the javy binary. Install it from
the Javy releases page
and either put it on your PATH or set JAVY_BIN_PATH to its absolute
location. Verify with:WASM rejected as 'not a Javy dynamic-mode module'
WASM rejected as 'not a Javy dynamic-mode module'
The upload endpoint checks the WASM import section for the
javy_quickjs_provider marker. Static-mode builds (which embed the
runtime instead of linking against the shared provider) are rejected
because they exceed the size cap by orders of magnitude. Always
compile with javy compile -d — the lms function build command
does this for you automatically.Webhook signature mismatches my server
Webhook signature mismatches my server
lms webhook trigger uses HMAC-SHA256 with the client secret as the key,
over the raw JSON body, and sends the result in the X-LMS-Hmac-SHA256
header (base64-encoded). Verify your server is hashing the raw request
body, not a re-serialized version, and that you’re using the same client
secret the CLI is loading from --secret or LMS_CLIENT_SECRET.Use with Claude Code
If you use Claude Code, install the LaunchMyStore Claude Skill to let Claude route plain-English requests (“build a discount function”, “list my orders”, “add a hero section”) to the right CLI command, MCP tool, App Bridge action, or Aqua snippet./launchmystore I want to build my first app.
Source: github.com/LaunchMyStore/skill
Next Steps
Build Your First App
A complete walkthrough using the
node templateApp Versioning
Release, publish, deprecate, and roll back versions
Functions Overview
Build, test, and deploy custom function logic with the CLI
App Bridge
Embed your app in the LaunchMyStore admin