@stackable-labs/cli-app-extension
v1.102.0
Published
CLI for scaffolding Stackable extension projects.
Downloads
10,291
Readme
@stackable-labs/cli-app-extension
CLI for scaffolding new Stackable App Extension projects.
Quick Start
pnpm --config.dlx-cache-max-age=0 dlx @stackable-labs/cli-app-extension@latest create my-extensionOr run interactively with no arguments:
pnpm --config.dlx-cache-max-age=0 dlx @stackable-labs/cli-app-extension@latest createImportant: Always include
@latestto ensure you get the most recent version. Bothnpxandpnpm dlxaggressively cache packages.
Interactive Mode
When run without all required flags, the CLI guides you through a step-by-step prompt flow:
| Step | Prompt | Description |
|---|---|---|
| 1 | App | Select the App you are building an Extension for (fetched live from the API) |
| 2 | Name | Display name for your Extension (e.g. My Commerce Extension) |
| 3 | Template | Choose a template flavor: Minimal (hello-world), Starter (common patterns), or Kitchen Sink (every component/capability) |
| 4 | Targets | Multiselect from the Surface targets/slots exposed by the selected app (skipped for Minimal and Kitchen Sink) |
| 5 | Extension Port | Dev server port for the Extension (default: 6543) |
| 6 | Preview Port | Dev server port for the Preview host (default: 6544) |
| 7 | Directory | Output directory path (default: kebab-case of name) |
| 8 | Confirm | Review all selections (including template) before scaffolding |
Commands
create [name]
Create a new Extension project from a template.
Usage: stackable-app-extension create [name] [options]
Arguments:
name Extension project name (prompted if omitted)
Options:
--app-id <id> Skip App selection
--project-id <id> Studio project ID (fetches files/manifest from Studio)
--template <flavor> Template flavor: minimal, starter, kitchen-sink
--extension-port <port> Extension dev server port (default: 6543)
--preview-port <port> Preview dev server port
--skip-install Skip package manager install
--skip-git Skip git initializationscaffold [extensionId]
Scaffold a local project from an existing Extension registered in the platform.
Usage: stackable-app-extension scaffold [extensionId] [options]
Arguments:
extensionId Extension ID to scaffold from (prompted if omitted)
Options:
--app-id <id> App ID (auto-resolved from extensionId if omitted)
--project-id <id> Studio project ID (fetches files/manifest from Studio)
--template <flavor> Template flavor: minimal, starter, kitchen-sink
--extension-port <port> Extension dev server port (default: 6543)
--preview-port <port> Preview dev server port
--skip-install Skip package manager install
--skip-git Skip git initializationWhen extensionId is provided without --app-id, the CLI automatically resolves which App owns the extension by checking all your registered apps. When scaffolding a newly created extension (no existing local project), the template picker is shown unless --template or --project-id is provided.
update [extensionId]
Update an existing Extension's metadata (name, targets, bundle URL, version, enabled state).
Usage: stackable-app-extension update [extensionId] [options]
Arguments:
extensionId Extension ID to update (prompted if omitted)
Options:
--app-id <id> App ID (auto-resolved from extensionId if omitted)
--name <name> New Extension name
--targets <targets> Comma-separated target slots (validated against app)
--bundle-url <url> New bundle URL
--enabled <bool> Enable/disable Extension
--set-version <version> Explicit version (skips auto-compute)
--dir <path> Project root (default: cwd)When extensionId is provided without --app-id, the CLI automatically resolves which App owns the extension by checking all your registered apps. If --app-id is also provided, it takes precedence.
auth
Manage CLI authentication.
stackable-app-extension auth login # Authenticate via browser
stackable-app-extension auth logout # Clear stored credentials
stackable-app-extension auth status # Show current auth statusLocal Development
To run the CLI locally from source against the live API:
pnpm build
pnpm cliOr pass flags directly:
pnpm cli -- --skip-install --skip-gitScaffolded Project Structure
my-extension/
├── packages/
│ ├── extension/ ← Extension source (Vite + React)
│ │ ├── src/
│ │ │ ├── index.tsx ← Extension entry point
│ │ │ └── surfaces/ ← One component per selected target slot
│ │ ├── manifest.json ← Extension manifest (id, targets, permissions)
│ │ └── .env ← EXTENSION_PORT, PREVIEW_PORT
│ └── preview/ ← Preview host app (Vite + React)
│ └── src/
│ └── App.tsx ← Host app wiring up the extension
├── turbo.json
└── package.jsondev Command
Start local dev servers with a public Cloudflare tunnel for testing:
pnpm previewUsage: stackable-app-extension dev [options]
Options:
--dir <path> Project root (default: cwd)
--extension-port <port> Override Extension port
--preview-port <port> Override Preview port
--no-tunnel Skip tunnel, just run vite dev
-h, --help Display helpThe dev command:
- Reads
.env.stackablefor cached App/Extension context (prompts if missing) - Starts Cloudflare tunnels for both extension and preview servers
- Starts Vite dev servers with hot-reload
- Displays a Host App Query Param you can append to your host app URL to test against the real deployed host
Host App Override
The dashboard displays a query param like:
?_stackable_dev=ext-123%3Ahttps%3A%2F%2Fabc.trycloudflare.comAppend this to your deployed host app URL to override the extension's bundleUrl in your browser session only. The @stackable-labs/embeddables SDK detects this param and loads from your tunnel instead of the production bundle. No DB changes, no shared state — each developer gets isolated overrides.
Multiple Extensions
To override multiple extensions at once, use either syntax:
Comma-separated (single param):
?_stackable_dev=ext-123:https://abc.trycloudflare.com,ext-456:https://def.trycloudflare.comRepeated params:
?_stackable_dev=ext-123:https://abc.trycloudflare.com&_stackable_dev=ext-456:https://def.trycloudflare.comNote: The
devcommand never updates thebundleUrlin the database. It is purely local.
Development Workflow
cd my-extension
pnpm install # if --skip-install was used
pnpm dev # starts both Extension + Preview with hot-reloadThe preview host runs at the configured preview port and hot-reloads whenever the Extension changes.
Troubleshooting
Stale CLI version after update
Both npx and pnpm dlx cache downloaded packages. If you're seeing an older version after a new release:
npx — Always use @latest and clear the cache if needed:
pnpm --config.dlx-cache-max-age=0 dlx @stackable-labs/cli-app-extension@latest createpnpm dlx — Bypass the 24-hour dlx cache:
pnpm --config.dlx-cache-max-age=0 dlx @stackable-labs/cli-app-extension@latest createNote: After a new version is published to npm, there may be a brief delay (up to ~15 minutes) before the npm CDN propagates the update.
Requirements
- Node 20+
- pnpm (recommended) or npm/yarn
