Chrome Web Store
from your Terminal

Upload, publish, rollout, and manage Chrome extensions — a fast, lightweight, CLI powered by the latest V2 API.

brew install null3000/tap/cws
GitHub

or curl -fsSL https://null3000.github.io/cws-cli/install.sh | bash

V2
API Version
8
Commands
1
Binary
0
Dependencies

Why cws?

Everything you need to manage Chrome Web Store extensions, nothing you don't.

Single Binary

No runtime, no npm install, no dependencies. Download and run.

V2 API

Built on the latest Chrome Web Store API — not the deprecated V1 that other tools still use.

Interactive Setup

cws init walks you through OAuth config — no more copy-pasting env vars from docs.

Full Lifecycle

Upload, publish, status, staged rollouts, and submission cancellation — all from one tool.

CI/CD Ready

Env vars, meaningful exit codes, and zero dependencies means it drops into any pipeline.

Flexible Config

TOML file, env vars, CLI flags — use any combination. Local or global config, your choice.

Quick Start

Three steps to publish your extension.

1

Set up credentials

cws init

Interactive wizard that configures OAuth2 credentials, refresh token, and Publisher ID. Writes a cws.toml config file.

2

Upload your extension

cws upload ./dist

Zips the directory (excluding .git/, node_modules/, etc.) and uploads it.

3

Publish

cws publish
Prerequisites

Before using cws, set up API access in the Google Cloud Console. Follow the official Chrome Web Store API guide:

  1. Create a project in the Google Cloud Console
  2. Enable the Chrome Web Store API
  3. Create an OAuth consent screen
  4. Create OAuth2 credentials (Desktop app type)
  5. Generate a refresh token via the OAuth Playground

Commands

Everything available in cws help

Command Description
cws initInteractive credential setup wizard
cws validate [source]Pre-flight validation (manifest, version, size)
cws upload [source]Validate, zip, and upload a package
cws publishPublish the latest uploaded version
cws statusCheck extension status
cws rollout <pct>Set deploy percentage (10k+ users required)
cws cancelCancel a pending submission
cws versionPrint CLI version
cws validate
# Full validation (local + remote checks)
cws validate ./dist

# Local checks only (no credentials needed)
cws validate ./dist --local

# Validate a pre-built zip
cws validate extension.zip

Checks: manifest.json validity, required fields, version format, package size, version > published, no pending submission. Also runs automatically before every cws upload.

cws upload
# Upload a directory (zips automatically)
cws upload ./dist

# Upload a pre-built zip
cws upload extension.zip

# Upload and publish in one step
cws upload ./dist --publish

# Specify extension ID
cws upload ./dist -e abcdefghijklmnopabcdefghijklmnop

# Don't wait for processing
cws upload ./dist --wait=false

# Skip pre-upload validation
cws upload ./dist --skip-validate
cws publish
# Publish immediately after review
cws publish

# Stage for review without auto-publishing
cws publish --staged
cws status
# Human-readable output
cws status

# Raw JSON (for scripting)
cws status --json
cws rollout
# Set to 50% rollout
cws rollout 50

# Full rollout
cws rollout 100
cws cancel
# Cancel a pending submission under review
cws cancel

# Cancel for a specific extension
cws cancel -e abcdefghijklmnopabcdefghijklmnop
cws init
# Set up credentials in current directory
cws init

# Save credentials globally (~/.config/cws/cws.toml)
cws init --global

Interactive wizard that guides you through configuring OAuth2 Client ID, Client Secret, Refresh Token, and Publisher ID. Validates credentials before saving.

Exit Code Meaning
0Success
1Error (API error, validation failure, invalid config, timeout, etc.)

Configuration

TOML file, env vars, and CLI flags — use any combination.

Config file

cws init writes credentials to ./cws.toml. This file contains secrets — do not commit it.

publisher_id = "abc1234567890"

[auth]
client_id = "xxxxxxxxxxxx.apps.googleusercontent.com"
client_secret = "GOCSPX-xxxxxxxxxxxx"
refresh_token = "1//xxxxxxxxxxxx"

[extensions.default]
id = "abcdefghijklmnopabcdefghijklmnop"
source = "./dist"

Use cws init --global to write credentials to ~/.config/cws/cws.toml instead, keeping secrets out of your project. Then create a minimal per-project config (safe to commit):

[extensions.default]
id = "abcdefghijklmnopabcdefghijklmnop"
source = "./dist"

Environment variables

Variable Description
CWS_CLIENT_IDOAuth2 Client ID
CWS_CLIENT_SECRETOAuth2 Client Secret
CWS_REFRESH_TOKENOAuth2 Refresh Token
CWS_PUBLISHER_IDPublisher ID
CWS_EXTENSION_IDDefault Extension ID

Priority order

  1. CLI flags (--extension-id, etc.)
  2. Environment variables (CWS_*)
  3. Local cws.toml (current directory)
  4. Global ~/.config/cws/cws.toml

CI/CD

Drop the binary into any pipeline — zero dependencies.

GitHub Actions

# .github/workflows/publish.yml
- name: Install cws
  run: curl -fsSL https://null3000.github.io/cws-cli/install.sh | bash

- name: Upload and publish extension
  env:
    CWS_CLIENT_ID: ${{ secrets.CWS_CLIENT_ID }}
    CWS_CLIENT_SECRET: ${{ secrets.CWS_CLIENT_SECRET }}
    CWS_REFRESH_TOKEN: ${{ secrets.CWS_REFRESH_TOKEN }}
    CWS_PUBLISHER_ID: ${{ secrets.CWS_PUBLISHER_ID }}
  run: cws upload ./dist -e ${{ vars.EXTENSION_ID }} --publish

cws vs chrome-webstore-upload-cli

The go-to tool has been chrome-webstore-upload-cli. Here's how they compare.

cws chrome-webstore-upload-cli
Runtime Single binary — no dependencies Requires Node.js + npm
API V2 V1
Setup Interactive wizard Manual env var config
Commands validate, upload, publish, status, rollout, cancel upload, publish
Config TOML + env vars + CLI flags Env vars only
Pre-upload validation Built-in — manifest, version, size checks before upload None
CI/CD Drop in a binary Requires Node.js in CI image

Installation

Multiple ways to install — pick what works for you.

Homebrew (macOS & Linux)

brew install null3000/tap/cws

Quick install (macOS & Linux)

curl -fsSL https://null3000.github.io/cws-cli/install.sh | bash

From source

go install github.com/null3000/cws-cli/cmd/cws@latest

Make sure $GOPATH/bin is in your PATH.

GitHub releases

Download the latest binary for your platform from Releases.

Windows (PowerShell)

Invoke-WebRequest -Uri https://github.com/null3000/cws-cli/releases/latest/download/cws_windows_amd64.zip -OutFile cws.zip
Expand-Archive cws.zip -DestinationPath .
Move-Item cws.exe C:\Windows\System32\