---
schema_version: "1"
id: 9cbd2e69be3daec25cb2c2ab04e7dded15ecc0b8d1ebc8561a4917594e89e94e
title: Local Development with LWS CLI
collection: developer
version: current
locale: en-us
portal_url: https://docs.salesforce.com/developer/current/en-us/lwc/lightning-components-security/guides/lws/lws-cli-test.md
canonical_url: https://developer.salesforce.com/docs/platform/lightning-components-security/guide/lws-cli-test.html
source_site: developer.salesforce.com
content_type: documentation
content_hash: 4d5428af1408a3fa593062944a68698f2f5709ac2117d782aac1cd1b92369e0a
products:
  - Security for Lightning Components
  - lwc
---
# Local Development with LWS CLI

The Lightning Web Security (LWS) CLI brings the Salesforce LWS runtime directly to your local terminal. Instead of relying on slow deploy-and-test loops, hosted web consoles, or manual copy-pasting, the CLI provides a fast, scriptable, local environment. You can use this environment to test and debug Lightning Web Components (LWC) and JavaScript code.

**important:** LWS CLI shrinks the feedback loop rather than replacing end-to-end testing. Real user interactions, live data, cross-org behavior, and auth flows still require full deployments. However, the CLI catches most LWS issues locally in seconds, preventing problems before deployment and reducing org round trips.

## Install the Package

To install LWS CLI, open a terminal on your development environment and perform these steps.

1. Install the node project dependencies.

   ```
   npm install
   ```

2. Install LWS CLI and the LWS configuration package from [this package location](https://www.npmjs.com/package/@locker/cli).

   ```
   # Globally — `lws` is available everywhere
   npm install -g @locker/cli
   # or:
   yarn global add @locker/cli
   ```

3. Run this command to install at least one Playwright browser binary.

   ```
     # Default: just chromium
     npx playwright install chromium

     # Or all three engines (chromium, firefox, webkit)
     npx playwright install
   ```

4. Verify if LWS CLI is installed.

   ```
   lws --version
   ```

## Key Features

Here are the key features and commands of LWS CLI.

### 1. Fast Code Evaluation

Use `lws eval` to compile and run your code inside a real, sandboxed browser runtime (Chromium). In this example, LWS compiles the code, opens a real browser, starts the production sandbox, and logs `hello from inside the sandbox` within seconds.

```
lws eval "console.log('hello from inside the sandbox')"
```

The `lws eval` command:

- Blocks dangerous operations by enforcing real LWS security policies. In this example, when untrusted code attempts to delete the host page, the sandbox blocks the request with a locker-security error and terminates the process with a non-zero exit code.

  ```
  lws eval "document.body.remove()"`
  ```

  Expected output:

 <pre>
    > (function () {
    > 'use strict';
    >
    > window.evaluateInSandbox('cli', () => {
    > document.body.remove();
    > });
    > })();
    >
    > [browser:pageerror] Lightning Web Security: Cannot remove BODY.
  </pre>

- Enforces multitenant data isolation through the LWS realm boundary and API distortions. Use the `--before` and `--after` flags to run system-mode setup and teardown scripts that plant host-page state (such as setting a session token or Cross-Site Request Forgery (CSRF) credential on `window`). This prevents untrusted sandboxed code from reading this data back.

  ```
    lws eval --before "document.cookie = '_auth_token=SECRET-host-only'" \
         --after "console.log('[host] real cookie jar:', document.cookie)" \
         "document.cookie = 'session=abc'; console.log('[sandbox] reads:', document.cookie)"
  ```

  Expected output:
  <pre> 
  >  (function () {
  >    'use strict';
  
  >   window.evaluateInSandbox('cli', () => {
  >      document.cookie = 'session=abc'; console.log('[sandbox] reads:', document.cookie);
  >      });
  
  >  })();
  
  >  [browser:log] [sandbox] reads: session=abc
  >  [browser:log] [host] real cookie jar: auth_token=SECRET-host-only; LSKey-cli$session=abc </pre>

- Automatically sanitizes untrusted markup at the boundary before it hits the live Document Object Model (DOM), when the untrusted markup is written into the DOM (for example, assigning to `innerHTML`). In this example, the script attempts to inject unsafe elements: a `<script>` HTML tag and a `onerror` event handler. In such cases, LWS removes the dangerous parts while preserving safe HTML tags, such as `<img>` and `<b>`. Instead of returning an error or refusing the input, LWS delivers a safe, sanitized DOM tree without requiring the sandbox to detect the threat.

  ```
  lws eval --after "console.log('[host] sanitized DOM:', document.querySelector('div#sink').outerHTML)" \
          "const d = document.createElement('div'); d.id = 'sink'; document.body.appendChild(d);
          d.innerHTML = '<script>alert(1)</script><img src=data:, onerror=alert(2)><b>kept</b>';"
  ```

  Expected output:

    <pre>
    > (function () {
    >  'use strict';
  
    >  window.evaluateInSandbox('cli', () => {
    >    const d = document.createElement('div'); d.id = 'sink'; document.body.appendChild(d);
    >    d.innerHTML = '&ltscript&gtalert(1)&lt/script&gt&ltimg src=data:, onerror=alert(2)&gt&ltb&gtkept&lt/b&gt';
  
    > });
  
    > })();
  
    > [browser:log][host] sanitized DOM: &ltdiv id="sink"&gt&ltimg src="data:,"&gt&ltb&gtkept&lt/b&gt&lt/div&gt
   </pre>

### 2. Local LWC Rendering

To render local LWC directories instantly by using the production LWC compiler, flags, and sandbox runtime, use the `lws component` command with a directory path. Using this command is faster than running local code through the web console, which requires deploying to a scratch org and waiting for build cycles.
In this example, the `lws component` uses a local component directory. A one-second local feedback loop running the production LWC engine and sandbox runtime instantly:

- Streams browser logs
- Verifies lifecycle callbacks in `parent connected`, `child connected`, and `parent rendered` sequence
- Outputs the full compiled LWC code directly to the terminal for fast debugging

```
lws component ./test/fixtures/c/helloWorld
```

Expected output:

<pre>
>  ((lwc) => {
>  ...

>    /* eslint-disable class-methods-use-this, no-console */
>   class HelloWorld extends (...) {
>      connectedCallback() {
>        console.log('hello-world connected');
>      }
>   ...
>   });

>  [browser:log] hello-world connected
>  [browser:log] wrapped-box connected
>  [browser:log] hello-world rendered
</pre>

The `--headed` flag with the `lws component` command opens a live browser window with Chrome DevTools, which enables complete Shadow DOM inspection, breakpoint debugging, and step-through capabilities without deploying to an org. You can analyze the sources and also view the fully bundled component-compiled code.

### 3. Persistent State

The `lws repl` command preserves state across multiple input lines, so that variables, functions, and array bindings remain persistent in the same sandbox environment. This command offers an interactive JavaScript Read-Eval-Print Loop (REPL) wrapped inside the LWS security membrane.
In this example, `lws repl` opens an interactive, multiline JavaScript shell wrapped in an LWS sandbox. The state persists across lines of code within the sandbox, preserving array bindings and multiline functions until the session ends with `.exit.`

```
lws repl
```

<pre>> lws repl ready (chromium, key="cli"). Type .help for commands, .exit or Ctrl+D to quit.</pre>

`lws> 1 + 2`

<pre>> 3</pre>

`lws> let arr = [1, 2, 3]`

<pre>> [ 1, 2, 3 ]</pre>

`lws> arr`

<pre>> [ 1, 2, 3 ]</pre>

`lws> let double = function(n) { ... return n * 2 ... }`

<pre>> 'function(n) {\n  return n * 2\n}'</pre>

`lws> double(2)`

<pre>>4</pre>

`lws> .exit`

The `lws repl` command also supports `--before` and `--after` flags to run system-level setup, or to remove scripts before and after entering the REPL.

```
lws repl --before "/* pre-setup system code */" --after "/* post-teardown system code */"
```
