# ecforce-theme-cli

> CLI tools for ecforce theme development

Latest version **2.0.0** (published 2026-04-26) · ISC license · 0 weekly downloads

## Install

```sh
npm install ecforce-theme-cli
pnpm add ecforce-theme-cli
yarn add ecforce-theme-cli
bun add ecforce-theme-cli
```

Provides the command `ecforce-theme`.

## Health

**Score 50/100 (C)** — status: stable.

Positive: esm support; no vulnerabilities.

Warnings: low downloads; no types.

## Facts

| | |
|---|---|
| Version | 2.0.0 |
| Published | 2026-04-26 |
| First published | 2023-11-20 |
| Weekly downloads | 0 |
| License | ISC |
| TypeScript types | none |
| Module format | ESM |
| Dependencies | 18 |
| Unpacked size | 102.8 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Maintainers | piou |

## Links

- npm: https://www.npmjs.com/package/ecforce-theme-cli
- Homepage: https://github.com/piouc/ecforce-theme-cli
- npm.io page: https://npm.io/package/ecforce-theme-cli

## Dependencies (18)

- [ws](https://npm.io/package/ws.md) ^8.20.0
- [joi](https://npm.io/package/joi.md) ^18.1.1
- [open](https://npm.io/package/open.md) ^11.0.0
- [axios](https://npm.io/package/axios.md) ^1.13.6
- [p-limit](https://npm.io/package/p-limit.md) ^7.3.0
- [archiver](https://npm.io/package/archiver.md) ^7.0.1
- [chokidar](https://npm.io/package/chokidar.md) ^5.0.0
- [readdirp](https://npm.io/package/readdirp.md) ^5.0.0
- [commander](https://npm.io/package/commander.md) ^14.0.3
- [puppeteer](https://npm.io/package/puppeteer.md) ^24.40.0
- [p-debounce](https://npm.io/package/p-debounce.md) ^5.1.0
- [axios-logger](https://npm.io/package/axios-logger.md) ^2.8.1
- [tough-cookie](https://npm.io/package/tough-cookie.md) ^6.0.1
- [unzip-stream](https://npm.io/package/unzip-stream.md) ^0.3.4
- [html-entities](https://npm.io/package/html-entities.md) ^2.6.0
- [package-directory](https://npm.io/package/package-directory.md) ^8.2.0
- [axios-cookiejar-support](https://npm.io/package/axios-cookiejar-support.md) ^6.0.5
- [@commander-js/extra-typings](https://npm.io/package/@commander-js/extra-typings.md) ^14.0.0

## Recent versions

- 2.0.0 (latest) — 2026-04-26
- 1.1.0 — 2026-03-23
- 1.0.3 — 2025-11-06
- 1.0.2 — 2025-10-30
- 1.0.1 — 2025-10-30
- 1.0.0 — 2025-10-29
- 0.0.35 — 2025-02-21
- 0.0.34 — 2025-02-21
- 0.0.33 — 2025-02-21
- 0.0.32 — 2024-12-10
- 0.0.31 — 2024-11-10
- 0.0.30 — 2024-11-06
- 0.0.29 — 2024-11-06
- 0.0.27 — 2024-10-16
- 0.0.26 — 2024-08-25
- … 25 more at https://npm.io/package/ecforce-theme-cli/versions

## README

## Getting started

### Installation
```bash
npm i -D ecforce-theme-cli
```

### Configuration
Put `ecforce.config.json` to project root.
```json
{
  "basicAuthUsername": "BASIC_AUTH_USERNAME",
  "basicAuthPassword": "BASIC_AUTH_PASSWORD",
  "username": "USERNAME",
  "password": "PASSWORD",
  "baseUrl": "https://HOSTNAME/",
  "authType": "legacy",
  "profiles": [
    {
      "type": "theme",
      "name": "THEME_NAME",
      "branch": "BRANCH_NAME",
      "themeId": "THEME_ID",
      "dir": "DIRECTORY_PATH"
    },
    {
      "type": "lp",
      "lpId": "LP_ID",
      "branch": "BRANCH_NAME",
      "dir": "DIRECTORY_PATH"
    },
    {
      "type": "page",
      "branch": "BRANCH_NAME",
      "dir": "DIRECTORY_PATH",
      "pages": [
        { "pageId": "PAGE_ID", "name": "PAGE_NAME" },
        { "pageId": "PAGE_ID" }
      ]
    }
  ]
}
```

#### Authentication Types
- `authType`: (optional, default: `"legacy"`)
  - `"legacy"`: Traditional admin sign-in authentication
  - `"ecforceAccount"`: ecforce Account authentication (uses Puppeteer for login, credentials cached in `ecforce.credentials.json`)

## Commands

### Init
```bash
npx ecforce-theme-cli init
npx ecforce-theme-cli init theme
npx ecforce-theme-cli init lp
npx ecforce-theme-cli init page
```
- `init` — Create config file with authentication settings
- `init theme` — Add a theme profile to existing config
- `init lp` — Add an LP profile to existing config
- `init page` — Add a page profile to existing config

### Sync
```bash
npx ecforce-theme-cli sync
```
#### Options
- -w, --watch  
watch files

### Pull
```bash
npx ecforce-theme-cli pull
```

### Page Pull
```bash
npx ecforce-theme-cli page-pull <name|pageId>
npx ecforce-theme-cli page-pull -a
```
#### Options
- -a, --all
pull all pages

### Page Sync
```bash
npx ecforce-theme-cli page-sync <name|pageId>
npx ecforce-theme-cli page-sync -a
```
#### Options
- -a, --all
sync all pages
- -w, --watch
watch files

### Preview
```bash
npx ecforce-theme-cli
```

### Auto reload script
<details>
  <summary>Code</summary>

  For theme
  ```html
  {% if theme_preview_mode %}
    <script>
      const connectWSServer = () => {
        const ws = new WebSocket('ws://localhost:8080')
        ws.addEventListener('message', message => {
          const data = JSON.parse(message.data)
          if(data.type === 'update'){
            location.reload()
          }
        })
      }

      let localHosted = null
      new MutationObserver((mutations) => {
        for(const mutation of mutations){
          for(const node of mutation.addedNodes){
            if(node.nodeName !== 'SCRIPT') break
            if(node.src.includes('/ec_force/assets/')){
              if(localHosted === null){
                const xhr = new XMLHttpRequest()
                xhr.open('HEAD', 'http://localhost:8088/', false)
                try {
                  xhr.send()
                  if(xhr.readyState === 4){
                    localHosted = true
                    connectWSServer()
                  } else {
                    throw new Error()
                  }
                } catch(err) {
                  localHosted = false
                }
              }
              if(localHosted){
                node.src = node.src.replace(/.*\/ec_force\/assets\//, 'http://localhost:8088/')
              }
            }
            return
          }
        }
      }).observe(document, {childList: true, subtree: true})
      document.addEventListener('DOMContentLoaded', () => {
        document.querySelectorAll('link').forEach(link => {
          if(localHosted === true && link.rel === 'stylesheet' && link.href.includes('/ec_force/assets/')){
            if(localHosted){
              link.href = link.href.replace(/.*\/ec_force\/assets\//, 'http://localhost:8088/')
            }
          }
        })
      })
    </script>
  {% endif %}
  ```

  For LP
  ```html
  {%%}
  <script>
    const connectWSServer = () => {
      const ws = new WebSocket('ws://localhost:8080')
      ws.addEventListener('message', message => {
        const data = JSON.parse(message.data)
        if(data.type === 'update'){
          location.reload()
        }
      })
    }
  </script>
  ```
</details>

---
_Source: https://npm.io/package/ecforce-theme-cli · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
