---
schema_version: "1"
id: c1745b336026c90a8e1282a940e048fe73d9bde83a624c6bcb5c6f7b7f13a9fa
title: Development Environment Setup
collection: developer
version: current
locale: en-us
portal_url: https://docs.salesforce.com/developer/current/en-us/commerce-cloud/b2c-commerce/guides/commerce-apps/development-environment.md
canonical_url: https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/guide/development-environment.html
source_site: developer.salesforce.com
content_type: documentation
content_hash: 7ab1690382ad51cec2133709f24e567bc4aca7d2637801b4a3a30628cc010e43
products:
  - Composable Storefront
  - Salesforce APIs
---
# Development Environment Setup

Set up your local development environment for building Commerce Apps.

## Prerequisites

Before building a Commerce App, ensure you have:

- A Commerce Cloud sandbox instance with Storefront Next enabled
- The [B2C CLI](https://developer.salesforce.com/docs/commerce/pwa-kit-managed-runtime/b2c-developer-tooling.md#run-the-b2c-cli) installed and configured with your instance credentials
- **ISVs only:** Access to the [Commerce App Registry](https://github.com/SalesforceCommerceCloud/commerce-apps). SIs building a merchant-specific app do not need the registry. See [Develop a Private Commerce App](/docs/commerce/b2c-commerce/guide/private-commerce-apps.md).
- Node.js and npm for Storefront Next development
- A code editor with JavaScript/TypeScript and React support
- Familiarity with Commerce Cloud cartridge development, IMPEX, and the SCAPI/OCAPI model

## Claude Code Skills

If you use Claude Code, the Commerce Apps repository provides skills that automate many manual steps:

| Skill                              | Description                                                   |
| :--------------------------------- | :------------------------------------------------------------ |
| `/scaffold-app`                    | Generate a complete app directory structure with templates    |
| `/package-app`                     | Package an app into a registry-ready ZIP                      |
| `/validate-app`                    | Comprehensive validation (structure, manifest, SHA256, IMPEX) |
| `/validate-impex`                  | Deep IMPEX validation for syntax and common errors            |
| `/generate-service-impex`          | Generate service credential, profile, and definition IMPEX    |
| `/generate-site-preferences-impex` | Generate site preference IMPEX                                |
| `/generate-custom-object-impex`    | Generate custom object type IMPEX                             |
| `/extract-app`                     | Extract a commerce app ZIP for development or modification    |
| `/diff-versions`                   | Compare two app versions for changelogs                       |
| `/submit-pr`                       | Guide through the PR submission process                       |

These skills complement the B2C CLI commands below. Use Claude Code skills for app scaffolding, IMPEX generation, and validation. Use the B2C CLI for installation, uninstallation, and sandbox testing.

## CLI Authentication Setup

The `cap install`, `cap uninstall`, `cap list` (without `--local`), `cap tasks`, and `cap pull` commands require OAuth credentials and OCAPI permissions on your target instance. These remote commands also require WebDAV access for package upload or download. The `cap validate`, `cap package`, and `cap list --local` commands are local-only and require no authentication.

For full details on B2C CLI authentication, see the [B2C CLI Authentication Guide](https://salesforcecommercecloud.github.io/b2c-developer-tooling/guide/authentication.html).

### OCAPI Configuration

For remote commands (`install`, `uninstall`, `list`, `tasks`, `pull`), configure the Data API permissions for system jobs and related queries. Your API client must grant the standard B2C CLI job-execution permissions on `/jobs/*/executions`, `/jobs/*/executions/*`, and `/job_execution_search`. If `cap list` or `cap pull` must discover sites because `--site-id` is omitted, also grant `GET` access to `/sites`. Configure these in Business Manager under **Administration** > **Site Development** > **Open Commerce API Settings** > **Data API**.

For the exact JSON resource block, see [Required OCAPI Permissions](/docs/commerce/b2c-commerce/guide/reference.md#required-ocapi-permissions). For broader B2C CLI authentication setup, see the [B2C CLI Authentication Guide](https://salesforcecommercecloud.github.io/b2c-developer-tooling/guide/authentication.html#ocapi-configuration).

### WebDAV Access

`cap install` uploads the CAP archive to the instance via WebDAV before triggering the installation job. SCAPI isn't a substitute for WebDAV upload — there is no SCAPI endpoint that uploads CAP archives. Authenticate WebDAV using one of these methods:

- **Business Manager credentials:** Set your BM username and WebDAV access key via `SFCC_USERNAME` and `SFCC_PASSWORD` environment variables, or use `--user-auth` to authenticate interactively via the browser.
- **Account Manager OAuth client:** Configure an OAuth client with **WebDAV Client Permissions** for the `/impex` path, in addition to the job-execution permissions described above. See the [B2C CLI WebDAV Access guide](https://salesforcecommercecloud.github.io/b2c-developer-tooling/guide/authentication.html#webdav-access) for details.

## CLI Commands

The B2C CLI provides commands for Commerce App development under the `cap` topic:

### b2c cap validate

Performs local validation of basic manifest fields, folder structure, and required files. It doesn't validate IMPEX content or perform registry submission checks. Accepts a path to a CAP directory or a `.zip` file.

```bash
b2c cap validate <path>
```

**Examples:**

```bash
# Validate a CAP directory
b2c cap validate ./commerce-avalara-tax-app-v0.2.5

# Validate a packaged CAP zip
b2c cap validate ./commerce-avalara-tax-app-v0.2.5.zip
```

### b2c cap package

Packages your project directory into a distributable `.zip` CAP file. ISVs must still complete the App Registry validation and submission workflow.

```bash
b2c cap package <path> [--output, -o <dir-or-file>] [--json]
```

**Examples:**

```bash
# Package to the current directory
b2c cap package ./commerce-avalara-tax-app-v0.2.5

# Package to a specific output directory
b2c cap package ./commerce-avalara-tax-app-v0.2.5 --output ./dist

# Package to a specific filename
b2c cap package ./commerce-avalara-tax-app-v0.2.5 --output ./dist/my-app.zip
```

> **Tip:** Add `--json` to any `cap` command for machine-readable JSON output, useful for scripting and CI pipelines.

### b2c cap install

Installs a CAP on a target instance. Accepts a local directory or `.zip` file. The CLI automatically uploads the archive to WebDAV and triggers the server-side installation job. See [CLI Authentication Setup](#cli-authentication-setup) for required credentials.

```bash
b2c cap install <path> --site-id <site-id> [--clean-archive] [--timeout <seconds>] [--skip-validate] [--create-pr] [--force] [--json]
```

**Flags:**

| Flag              | Description                                                                                              |
| ----------------- | -------------------------------------------------------------------------------------------------------- |
| `--site-id`, `-s` | **(Required)** Site ID to install the Commerce App on. Alias: `--site`                                   |
| `--clean-archive` | Delete the uploaded zip from the instance after install. By default the archive is kept on the instance. |
| `--timeout`, `-t` | Timeout in seconds for the installation job                                                              |
| `--skip-validate` | Skip CAP structure validation before install                                                             |
| `--create-pr`     | Request a pull request for Storefront Next extensions or cartridges                                      |
| `--force`, `-f`   | Skip the confirmation prompt shown for non-Salesforce applications                                       |
| `--json`          | Output results as JSON                                                                                   |

**Examples:**

```bash
# Install from a directory
b2c cap install ./commerce-avalara-tax-app-v0.2.5 --site-id RefArch

# Install from a zip file
b2c cap install ./commerce-avalara-tax-app-v0.2.5.zip --site-id RefArch

# Install and skip pre-validation
b2c cap install ./commerce-avalara-tax-app-v0.2.5 --site-id RefArch --skip-validate

# Install and clean up the archive from the instance afterward
b2c cap install ./commerce-avalara-tax-app-v0.2.5 --site-id RefArch --clean-archive
```

### b2c cap uninstall

Uninstalls a Commerce App from a target instance by app ID. The CLI automatically discovers the app's domain by querying the installed apps on the instance, so you don't need to specify it.

```bash
b2c cap uninstall <app-id> --site-id <site-id> [--timeout <seconds>] [--json]
```

**Flags:**

| Flag              | Description                                                                |
| ----------------- | -------------------------------------------------------------------------- |
| `--site-id`, `-s` | **(Required)** Site ID to uninstall the Commerce App from. Alias: `--site` |
| `--timeout`, `-t` | Timeout in seconds for the uninstall job                                   |
| `--json`          | Output results as JSON                                                     |

**Examples:**

```bash
b2c cap uninstall avalara-tax --site-id RefArch
```

### b2c cap list

Lists Commerce Apps either locally (from the filesystem) or installed on a remote B2C Commerce instance. When querying a remote instance, requires the same authentication as `cap install`.

```bash
b2c cap list [--local] [--site-id <site-id>[,<site-id>]] [--timeout <seconds>] [--json]
```

**Flags:**

| Flag              | Description                                                                             |
| ----------------- | --------------------------------------------------------------------------------------- |
| `--local`, `-l`   | List Commerce Apps found in local directories instead of querying a remote instance     |
| `--site-id`, `-s` | Site ID(s) to query. Accepts comma-separated values for multiple sites. Alias: `--site` |
| `--timeout`, `-t` | Timeout in seconds for the remote query                                                 |
| `--json`          | Output results as JSON                                                                  |

**Examples:**

```bash
# List apps installed on a remote instance
b2c cap list --site-id RefArch

# List apps across multiple sites
b2c cap list --site-id RefArch,SiteGenesis

# List locally available Commerce App directories
b2c cap list --local
```

### b2c cap tasks

Lists configuration tasks for an installed Commerce App. Tasks include Business Manager deep links for completing post-install configuration such as entering service credentials or setting site preferences.

```bash
b2c cap tasks <app-name> --site-id <site-id> [--timeout <seconds>] [--json]
```

**Flags:**

| Flag              | Description                                                        |
| ----------------- | ------------------------------------------------------------------ |
| `--site-id`, `-s` | **(Required)** Site ID where the app is installed. Alias: `--site` |
| `--timeout`, `-t` | Timeout in seconds for the remote query                            |
| `--json`          | Output results as JSON                                             |

**Examples:**

```bash
# View configuration tasks for an installed app
b2c cap tasks avalara-tax --site-id RefArch
```

### b2c cap pull

Downloads installed Commerce App packages from a B2C Commerce instance to a local directory. If no app name is specified, pulls all registry-sourced apps installed on the instance.

This command is particularly useful for merchants who install Commerce Apps from Business Manager and want to integrate the app's code into their projects using their existing development workflows, rather than relying on the automated pull request flow. After pulling, the `storefront-next/` extensions and `cartridges/` from the downloaded package can be reviewed, customized if needed, and integrated into the merchant's storefront and cartridge projects through their standard source control and deployment processes.

```bash
b2c cap pull [app-name] [--site-id <site-id>] [--output, -o <dir>] [--timeout <seconds>] [--json]
```

**Flags:**

| Flag              | Description                                                          |
| ----------------- | -------------------------------------------------------------------- |
| `--site-id`, `-s` | Site ID to query for installed apps. Alias: `--site`                 |
| `--output`, `-o`  | Output directory for downloaded packages. Default: `./commerce-apps` |
| `--timeout`, `-t` | Timeout in seconds for the download                                  |
| `--json`          | Output results as JSON                                               |

**Examples:**

```bash
# Pull a specific app
b2c cap pull avalara-tax --site-id RefArch

# Pull all installed registry apps to a custom directory
b2c cap pull --site-id RefArch --output ./downloaded-apps
```

## End-to-End Development Lifecycle (ISV and SI)

From the perspective of an ISV building a Commerce App for the registry, or an SI building a private app for a specific merchant, the full lifecycle spans four stages — each backed by a combination of Claude Code skills and B2C CLI commands:

| Stage           | Goal                                                                                              | Primary tooling                                                                                                 |
| :-------------- | :------------------------------------------------------------------------------------------------ | :-------------------------------------------------------------------------------------------------------------- |
| **Scaffold**    | Generate a CAP directory structure and starter manifests                                          | `/scaffold-app`, `/generate-service-impex`, `/generate-site-preferences-impex`, `/generate-custom-object-impex` |
| **Develop**     | Implement cartridge hooks, Storefront Next extensions, and IMPEX                                  | Your editor + cartridge dev tooling; `/validate-impex` for incremental IMPEX checks                             |
| **Test**        | Validate, package, install on a sandbox, and exercise end-to-end                                  | `b2c cap validate`, `b2c cap package`, `b2c cap install`, `b2c cap tasks`, `b2c cap list`                       |
| **Submit/Ship** | Publish to the registry or deliver a private `.zip`                                            | ISV: `/diff-versions`, `/submit-pr`. SI: deliver the CAP; merchant or SI runs `b2c cap install`.                        |

ISVs publish through the [Commerce App Registry](https://github.com/SalesforceCommerceCloud/commerce-apps). SIs deliver the CAP and install it with `b2c cap install` (WebDAV). Private apps are not listed in the Cart & Checkout Hub catalog, so merchants cannot click-to-install them. The same packaging, validation, and installation tooling applies in both cases. See [Develop a Private Commerce App](/docs/commerce/b2c-commerce/guide/private-commerce-apps.md).

### Inner Development Loop (Test Stage)

Within the Test stage of the lifecycle above, the recommended sandbox iteration loop is:

1. Develop your code locally (cartridges, scripts, Storefront Next extensions)

2. Organize your project into the CAP directory structure (see [CAP Structure](/docs/commerce/b2c-commerce/guide/architecture.md#commerce-app-package-cap-structure))

3. Validate your CAP structure:

   ```bash
   b2c cap validate ./my-commerce-app
   ```

4. Package into a `.zip` file:

   ```bash
   b2c cap package ./my-commerce-app --output ./dist
   ```

5. Install on your sandbox (the CLI handles the WebDAV upload and job execution automatically):

   ```bash
   b2c cap install ./dist/my-commerce-app-v1.0.0.zip --site-id RefArch
   ```

6. View and complete configuration tasks:

   ```bash
   b2c cap tasks my-commerce-app --site-id RefArch
   ```

   Follow the Business Manager links provided to configure service credentials and site preferences.

7. Test end-to-end on your sandbox storefront

8. Verify installation status:

   ```bash
   b2c cap list --site-id RefArch
   ```

9. Iterate: make changes, re-validate, re-package, re-install

> **Tip:** During rapid development, install directly from the source directory (skipping the separate package step). The CLI packages and uploads for you:
>
> ```bash
> b2c cap install ./my-commerce-app --site-id RefArch
> ```

## Iterating Across Sandbox Environments

Most ISVs and SIs maintain more than one sandbox: a personal dev sandbox, a shared QA sandbox, and (for ISVs) a partner staging sandbox. The B2C CLI supports per-environment configuration through named instances in `dw.json` and the `--instance` flag. See [Multiple Instances](https://salesforcecommercecloud.github.io/b2c-developer-tooling/guide/configuration.html#multiple-instances).

Practical patterns:

- **Switch instances by environment variable.** Set `SFCC_HOSTNAME`, `SFCC_USERNAME`, and `SFCC_PASSWORD` per shell session (or use a `.env` loader) to point `b2c cap install` at a different sandbox without changing your project.
- **Reuse the same CAP across environments.** Package once, install many times. The same `.zip` produced by `b2c cap package` is valid on any compatible sandbox.
- **Reset between iterations.** Use `b2c cap uninstall <app-id> --site-id <site-id>` to remove an app cleanly before installing a new build. This exercises your uninstall IMPEX as part of the dev loop.
- **Retrieve an available source package.** Use `b2c cap pull <app-name> --site-id <site-id>` to download the retained WebDAV archive when it has a persisted version and is still available. Registry apps can fall back to the registry package. This command doesn't reconstruct the deployed state.

## Inspecting Installed App State

When an installation misbehaves, use the CLI to inspect what the platform actually recorded on the instance:

- **List installed apps:** `b2c cap list --site-id <site-id>` returns the apps registered against a site, including their version and lifecycle state. Use `--json` to pipe into `jq` for scripted checks.
- **View configuration tasks:** `b2c cap tasks <app-name> --site-id <site-id>` returns the merchant task list with deep links to Business Manager. If a task is unexpectedly incomplete, the deep link points directly at the BM page that needs attention.
- **Pull the live package:** `b2c cap pull <app-name> --site-id <site-id>` downloads the CAP exactly as the platform unpacked it. Diff the result against your source build.
- **Check the job log:** Lifecycle errors (`INSTALL_FAILED`, `CONFIGURATION_FAILED`, `UNINSTALL_FAILED`) write detailed step-by-step output to **Administration** > **Operations** > **Job Schedules** in Business Manager.
- **Read `CommerceFeatureState` directly:** The system object's `InstallationMetadata` JSON field contains the job execution ID, deployed cartridge names, and any error details. See [Monitoring and Support](/docs/commerce/b2c-commerce/guide/post-publication.md#monitoring-and-support).

## CI/CD Pipeline Integration

The `cap validate` and `cap package` commands are local-only and require no instance credentials, which makes them well-suited to CI. A typical pipeline:

1. **On pull request:** Run `b2c cap validate <path> --json` to fail the build on basic manifest or CAP structure errors. Pair with `/validate-impex` (Claude Code) or your own IMPEX linter to validate IMPEX content.
2. **On merge to a release branch:** Run `b2c cap package <path> --output ./dist --json` to produce the release `.zip`. Capture the file (and its SHA-256) as a build artifact.
3. **On promotion to a partner sandbox:** Run `b2c cap install ./dist/<app>.zip --site-id <site-id> --json` against a dedicated CI sandbox. Configure `SFCC_SERVER`, `SFCC_CLIENT_ID`, an OAuth credential such as `SFCC_CLIENT_SECRET`, and WebDAV authorization through client permissions or `SFCC_USERNAME`/`SFCC_PASSWORD`. Store credentials in the CI platform's encrypted, masked, environment-scoped secret store; prefer a dedicated least-privilege OAuth client, and never commit secrets to `dw.json` or source control. Follow with `b2c cap list --site-id <site-id> --json` to confirm the install succeeded. See [CLI Authentication Setup](#cli-authentication-setup) for the credential model.
4. **On registry publish (ISVs only):** Diff against the previous version (`/diff-versions`) to generate a changelog, then open a PR against the registry that updates the `version`, `zip`, and `sha256` fields. Do not edit `catalog.json` manually — registry CI handles version tracking.

> **Tip:** All `cap` commands accept `--json`. Prefer JSON output in CI to parse exit codes and structured error messages instead of scraping logs.

## Feature Toggles and Prerequisites

Enable every feature toggle that your app requires before installation. When the supplied app ID and domain match a registry entry, the installer checks its `requiredFeatureToggle`, when present, and fails if that toggle is disabled. The installer doesn't enable prerequisite toggles for you.

Verify that the top-level `CommerceAppsEnabled` toggle is enabled on your instance. The install and uninstall jobs need this toggle to execute. This toggle is enabled by default on sandboxes provisioned for Commerce Apps development. If your install job returns an error about Commerce Apps not being enabled, contact your administrator.

## Troubleshooting Development Issues

- **Install job returns `INSTALL_FAILED`:** Check the job execution log in Business Manager (**Administration** > **Operations** > **Job Schedules**). Common causes: missing OCAPI permissions, WebDAV access issues, or IMPEX validation errors.
- **App appears installed but hooks don't fire:** Verify the site's cartridge path includes your app's cartridges. For tax apps, verify `TaxAppHooksEnabled` is `true` in the feature toggles. Also confirm that SiteGenesis or SFRA cartridges aren't on the cartridge path — see [Storefront compatibility](/docs/commerce/b2c-commerce/guide/reference.md#storefront-compatibility) for details.
- **Re-install after code version switch:** If you switch the active code version, cartridges may be missing. Re-running the install job re-copies cartridges without re-running IMPEX (idempotency behavior).
- **IMPEX placeholder not replaced:** Ensure your file extension is one of the supported text types (`.xml`, `.csv`, `.txt`, `.json`, `.properties`, `.js`). Binary files are copied without placeholder replacement.
