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 --cask vaughnbosu/tap/cws
GitHub

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

Using an AI client? Add the optional MCP server.

V2
API Version
10
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 directly on the current Chrome Web Store API.

Interactive Setup

cws init --global 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 --global

Interactive wizard that stores OAuth2 credentials, refresh token, and Publisher ID in your global config.

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

Use cws from your AI client

The optional cws-mcp server uses the same credentials, project config, validation, and Chrome Web Store API service as the CLI.

1

Install the server

brew install --cask
vaughnbosu/tap/cws-mcp

Run cws init --global first if you have not configured shared credentials yet.

2

Connect your client

For Codex, add this to ~/.codex/config.toml and replace the workspace path:

[mcp_servers.chrome-web-store]
command = "cws-mcp"
default_tools_approval_mode = "writes"

[mcp_servers.chrome-web-store.env]
CWS_WORKSPACE = "/absolute/path/to/extension"
Guarded store operations

Upload, publish, rollout, and cancellation tools require an explicit confirm: true. Source and output paths stay inside CWS_WORKSPACE.

Setup for Claude, Cursor, VS Code, and Windsurf

Commands

Everything available in cws help

Command Description
cws init [--global]Interactive credential setup wizard (browser sign-in)
cws loginRe-acquire a refresh token via browser sign-in
cws validate [source]Pre-flight validation (manifest, version, icons, size, policy flags)
cws pack [source]Zip an extension directory without uploading
cws upload [source]Validate, zip, and upload a package
cws publishPublish the latest uploaded version
cws statusCheck extension status, policy warnings, and takedowns
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, icon files, package size, version > published and submitted revisions, no pending submission, and policy warnings/takedowns. 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

# Attempt to skip review (only some changes are eligible)
cws publish --skip-review

# Fail if the store reports validation warnings
cws publish --block-on-warnings

# Publish with an initial partial rollout
cws publish --deploy-percentage 10

Non-blocking store warnings are printed after every publish.

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
# Recommended: keep credentials outside the project
cws init --global

# Optional: write a local config containing credentials
cws init

Interactive wizard that guides you through configuring OAuth2 Client ID, Client Secret, Refresh Token, and Publisher ID. Secrets are read without echoing, credentials are validated before saving, and a local cws.toml is added to .gitignore. Use cws login later to refresh an expired token.

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 --global writes credentials to ~/.config/cws/cws.toml. Keep only extension and packaging settings in the project:

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

Running cws init without --global writes credentials to ./cws.toml. That file contains secrets and must not be committed.

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 Action

# .github/workflows/publish.yml
- name: Upload and publish extension
  uses: vaughnbosu/cws-cli@v1.3.1
  with:
    version: v1.3.1
    args: upload ./dist --publish
    client-id: ${{ secrets.CWS_CLIENT_ID }}
    client-secret: ${{ secrets.CWS_CLIENT_SECRET }}
    refresh-token: ${{ secrets.CWS_REFRESH_TOKEN }}
    publisher-id: ${{ secrets.CWS_PUBLISHER_ID }}
    extension-id: ${{ vars.EXTENSION_ID }}

The Action supports Linux and macOS runners on amd64 or arm64. Standalone Windows binaries are available from GitHub Releases.

Any other CI

- name: Install cws
  run: curl -fsSL https://vaughnbosu.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 --json

Installation

Multiple ways to install — pick what works for you.

Homebrew (macOS & Linux)

brew install --cask vaughnbosu/tap/cws

Quick install (macOS & Linux)

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

From source

go install github.com/vaughnbosu/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/vaughnbosu/cws-cli/releases/latest/download/cws_windows_amd64.zip -OutFile cws.zip
Expand-Archive cws.zip -DestinationPath .
Move-Item cws.exe C:\Windows\System32\