gws
**One CLI for all of Google Workspace — built for humans and AI agents.**
Drive, Gmail, Calendar, and every Workspace API. Zero boilerplate. Structured JSON output. 40+ agent skills included.
> [!IMPORTANT]
> Temporarily disabling non-collaborator pull requests. See this discussion, https://github.com/googleworkspace/cli/discussions/249.
> [!NOTE]
> This is **not** an officially supported Google product.
```bash
npm install -g @googleworkspace/cli
```
`gws` doesn't ship a static list of commands. It reads Google's own [Discovery Service](https://developers.google.com/discovery) at runtime and builds its entire command surface dynamically. When Google Workspace adds an API endpoint or method, `gws` picks it up automatically.
> [!IMPORTANT]
> This project is under active development. Expect breaking changes as we march toward v1.0.
## Contents
- [Prerequisites](#prerequisites)
- [Installation](#installation)
- [Quick Start](#quick-start)
- [Why gws?](#why-gws)
- [Authentication](#authentication)
- [AI Agent Skills](#ai-agent-skills)
- [Advanced Usage](#advanced-usage)
- [Environment Variables](#environment-variables)
- [Architecture](#architecture)
- [Troubleshooting](#troubleshooting)
- [Development](#development)
## Prerequisites
- **Node.js 18+** — for `npm install` (or download a pre-built binary from [GitHub Releases](https://github.com/googleworkspace/cli/releases))
- **A Google Cloud project** — required for OAuth credentials. You can create one via the [Google Cloud Console](https://console.cloud.google.com/) or with the [`gcloud` CLI](https://cloud.google.com/sdk/docs/install) or with the `gws auth setup` command.
- **A Google account** with access to Google Workspace
## Installation
```bash
npm install -g @googleworkspace/cli
```
> The npm package bundles pre-built native binaries for your OS and architecture.
> No Rust toolchain required.
Pre-built binaries are also available on the [GitHub Releases](https://github.com/googleworkspace/cli/releases) page.
Or build from source:
```bash
cargo install --git https://github.com/googleworkspace/cli --locked
```
A Nix flake is also available at `github:googleworkspace/cli`
```bash
nix run github:googleworkspace/cli
```
## Quick Start
```bash
gws auth setup # walks you through Google Cloud project config
gws auth login # subsequent OAuth login
gws drive files list --params '{"pageSize": 5}'
```
## Why gws?
**For humans** — stop writing `curl` calls against REST docs. `gws` gives you `--help` on every resource, `--dry-run` to preview requests, and auto‑pagination.
**For AI agents** — every response is structured JSON. Pair it with the included agent skills and your LLM can manage Workspace without custom tooling.
```bash
# List the 10 most recent files
gws drive files list --params '{"pageSize": 10}'
# Create a spreadsheet
gws sheets spreadsheets create --json '{"properties": {"title": "Q1 Budget"}}'
# Send a Chat message
gws chat spaces messages create \
--params '{"parent": "spaces/xyz"}' \
--json '{"text": "Deploy complete."}' \
--dry-run
# Introspect any method's request/response schema
gws schema drive.files.list
# Stream paginated results as NDJSON
gws drive files list --params '{"pageSize": 100}' --page-all | jq -r '.files[].name'
```
## Authentication
The CLI supports multiple auth workflows so it works on your laptop, in CI, and on a server.
### Which setup should I use?
| I have… | Use |
|---|---|
| `gcloud` installed and authenticated | [`gws auth setup`](#interactive-local-desktop) (fastest) |
| A GCP project but no `gcloud` | [Manual OAuth setup](#manual-oauth-setup-google-cloud-console) |
| An existing OAuth access token | [`GOOGLE_WORKSPACE_CLI_TOKEN`](#pre-obtained-access-token) |
| Existing Credentials | [`GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE`](#service-account-server-to-server) |
### Interactive (local desktop)
Credentials are encrypted at rest (AES-256-GCM) with the key stored in your OS keyring.
```bash
gws auth setup # one-time: creates a Cloud project, enables APIs, logs you in
gws auth login # subsequent scope selection and login
```
> `gws auth setup` requires the [`gcloud` CLI](https://cloud.google.com/sdk/docs/install). If you don't have `gcloud`, use the [manual setup](#manual-oauth-setup-google-cloud-console) below instead.
> [!WARNING]
> **Scope limits in testing mode:** If your OAuth app is unverified (testing mode),
> Google limits consent to ~25 scopes. The `recommended` scope preset includes 85+
> scopes and **will fail** for unverified apps (especially for `@gmail.com` accounts).
> Choose individual services instead to filter the scope picker:
> ```bash
> gws auth login -s drive,gmail,sheets
> ```
### Manual OAuth setup (Google Cloud Console)
Use this when `gws auth setup` cannot automate project/client creation, or when you want explicit control.
1. Open Google Cloud Console in the target project:
- OAuth consent screen: `https://console.cloud.google.com/apis/credentials/consent?project=`
- Credentials: `https://console.cloud.google.com/apis/credentials?project=`
2. Configure OAuth branding/audience if prompted:
- App type: **External** (testing mode is fine)
3. Add your account under **Test users**
4. Create an OAuth client:
- Type: **Desktop app**
5. Download the client JSON and save it to:
- `~/.config/gws/client_secret.json`
> [!IMPORTANT]
> **You must add yourself as a test user.** In the OAuth consent screen, click
> **Test users → Add users** and enter your Google account email. Without this,
> login will fail with a generic "Access blocked" error.
Then run:
```bash
gws auth login
```
### Browser-assisted auth (human or agent)
You can complete OAuth either manually or with browser automation.
- **Human flow**: run `gws auth login`, open the printed URL, approve scopes.
- **Agent-assisted flow**: the agent opens the URL, selects account, handles consent prompts, and returns control once the localhost callback succeeds.
If consent shows **"Google hasn't verified this app"** (testing mode), click **Continue**.
If scope checkboxes appear, select required scopes (or **Select all**) before continuing.
### Headless / CI (export flow)
1. Complete interactive auth on a machine with a browser.
2. Export credentials:
```bash
gws auth export --unmasked > credentials.json
```
3. On the headless machine:
```bash
export GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE=/path/to/credentials.json
gws drive files list # just works
```
### Service Account (server-to-server)
Point to your key file; no login needed.
```bash
export GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE=/path/to/service-account.json
gws drive files list
```
### Pre-obtained Access Token
Useful when another tool (e.g. `gcloud`) already mints tokens for your environment.
```bash
export GOOGLE_WORKSPACE_CLI_TOKEN=$(gcloud auth print-access-token)
```
### Precedence
| Priority | Source | Set via |
| -------- | ---------------------- | --------------------------------------- |
| 1 | Access token | `GOOGLE_WORKSPACE_CLI_TOKEN` |
| 2 | Credentials file | `GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE` |
| 3 | Encrypted credentials | `gws auth login` |
| 4 | Plaintext credentials | `~/.config/gws/credentials.json` |
Environment variables can also live in a `.env` file.
## AI Agent Skills
The repo ships 100+ Agent Skills (`SKILL.md` files) — one for every supported API, plus higher-level helpers for common workflows and 50 curated recipes for Gmail, Drive, Docs, Calendar, and Sheets. See the full [Skills Index](docs/skills.md) for the complete list.
```bash
# Install all skills at once
npx skills add https://github.com/googleworkspace/cli
# Or pick only what you need
npx skills add https://github.com/googleworkspace/cli/tree/main/skills/gws-drive
npx skills add https://github.com/googleworkspace/cli/tree/main/skills/gws-gmail
```
OpenClaw setup
```bash
# Symlink all skills (stays in sync with repo)
ln -s $(pwd)/skills/gws-* ~/.openclaw/skills/
# Or copy specific skills
cp -r skills/gws-drive skills/gws-gmail ~/.openclaw/skills/
```
The `gws-shared` skill includes an `install` block so OpenClaw auto-installs the CLI via `npm` if `gws` isn't on PATH.
## Gemini CLI Extension
1. Authenticate the CLI first:
```bash
gws auth setup
```
2. Install the extension into the Gemini CLI:
```bash
gemini extensions install https://github.com/googleworkspace/cli
```
Installing this extension gives your Gemini CLI agent direct access to all `gws` commands and Google Workspace agent skills. Because `gws` handles its own authentication securely, you simply need to authenticate your terminal once prior to using the agent, and the extension will automatically inherit your credentials.
## Advanced Usage
### Multipart Uploads
```bash
gws drive files create --json '{"name": "report.pdf"}' --upload ./report.pdf
```
### Pagination
| Flag | Description | Default |
| ------------------- | ---------------------------------------------- | ------- |
| `--page-all` | Auto-paginate, one JSON line per page (NDJSON) | off |
| `--page-limit ` | Max pages to fetch | 10 |
| `--page-delay ` | Delay between pages | 100 ms |
### Google Sheets — Shell Escaping
Sheets ranges use `!` which bash interprets as history expansion. Always wrap values in **single quotes**:
```bash
# Read cells A1:C10 from "Sheet1"
gws sheets spreadsheets values get \
--params '{"spreadsheetId": "SPREADSHEET_ID", "range": "Sheet1!A1:C10"}'
# Append rows
gws sheets spreadsheets values append \
--params '{"spreadsheetId": "ID", "range": "Sheet1!A1", "valueInputOption": "USER_ENTERED"}' \
--json '{"values": [["Name", "Score"], ["Alice", 95]]}'
```
### Model Armor (Response Sanitization)
Integrate [Google Cloud Model Armor](https://cloud.google.com/security/products/model-armor) to scan API responses for prompt injection before they reach your agent.
```bash
gws gmail users messages get --params '...' \
--sanitize "projects/P/locations/L/templates/T"
```
| Variable | Description |
| ---------------------------------------- | ---------------------------- |
| `GOOGLE_WORKSPACE_CLI_SANITIZE_TEMPLATE` | Default Model Armor template |
| `GOOGLE_WORKSPACE_CLI_SANITIZE_MODE` | `warn` (default) or `block` |
## Environment Variables
All variables are optional. See [`.env.example`](.env.example) for a copy-paste template.
| Variable | Description |
|---|---|
| `GOOGLE_WORKSPACE_CLI_TOKEN` | Pre-obtained OAuth2 access token (highest priority) |
| `GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE` | Path to OAuth credentials JSON (user or service account) |
| `GOOGLE_WORKSPACE_CLI_CLIENT_ID` | OAuth client ID (alternative to `client_secret.json`) |
| `GOOGLE_WORKSPACE_CLI_CLIENT_SECRET` | OAuth client secret (paired with `CLIENT_ID`) |
| `GOOGLE_WORKSPACE_CLI_CONFIG_DIR` | Override config directory (default: `~/.config/gws`) |
| `GOOGLE_WORKSPACE_CLI_SANITIZE_TEMPLATE` | Default Model Armor template |
| `GOOGLE_WORKSPACE_CLI_SANITIZE_MODE` | `warn` (default) or `block` |
| `GOOGLE_WORKSPACE_PROJECT_ID` | GCP project ID fallback for helper commands |
Environment variables can also be set in a `.env` file (loaded via [dotenvy](https://crates.io/crates/dotenvy)).
## Architecture
`gws` uses a **two-phase parsing** strategy:
1. Read `argv[1]` to identify the service (e.g. `drive`)
2. Fetch the service's Discovery Document (cached 24 h)
3. Build a `clap::Command` tree from the document's resources and methods
4. Re-parse the remaining arguments
5. Authenticate, build the HTTP request, execute
All output — success, errors, download metadata — is structured JSON.
## Troubleshooting
### "Access blocked" or 403 during login
Your OAuth app is in **testing mode** and your account is not listed as a test user.
**Fix:** Open the [OAuth consent screen](https://console.cloud.google.com/apis/credentials/consent) in your GCP project → **Test users** → **Add users** → enter your Google account email. Then retry `gws auth login`.
### "Google hasn't verified this app"
Expected when your app is in testing mode. Click **Advanced** → **Go to \ (unsafe)** to proceed. This is safe for personal use; verification is only required to publish the app to other users.
### Too many scopes / consent screen error
Unverified (testing mode) apps are limited to ~25 OAuth scopes. The `recommended` scope preset includes many scopes and will exceed this limit.
**Fix:** Select only the scopes you need:
```bash
gws auth login --scopes drive,gmail,calendar
```
### `gcloud` CLI not found
`gws auth setup` requires the `gcloud` CLI to automate project creation. You have three options:
1. [Install gcloud](https://cloud.google.com/sdk/docs/install) and use `gcloud` directly.
2. Re-run `gws auth setup` which wraps `gcloud` calls.
3. Skip `gcloud` entirely — set up OAuth credentials manually in the [Cloud Console](#manual-oauth-setup-google-cloud-console)
### `redirect_uri_mismatch`
The OAuth client was not created as a **Desktop app** type. In the [Credentials](https://console.cloud.google.com/apis/credentials) page, delete the existing client, create a new one with type **Desktop app**, and download the new JSON.
### API not enabled — `accessNotConfigured`
If a required Google API is not enabled for your GCP project, you will see a
403 error with reason `accessNotConfigured`:
```json
{
"error": {
"code": 403,
"message": "Gmail API has not been used in project 549352339482 ...",
"reason": "accessNotConfigured",
"enable_url": "https://console.developers.google.com/apis/api/gmail.googleapis.com/overview?project=549352339482"
}
}
```
`gws` also prints an actionable hint to **stderr**:
```
💡 API not enabled for your GCP project.
Enable it at: https://console.developers.google.com/apis/api/gmail.googleapis.com/overview?project=549352339482
After enabling, wait a few seconds and retry your command.
```
**Steps to fix:**
1. Click the `enable_url` link (or copy it from the `enable_url` JSON field).
2. In the GCP Console, click **Enable**.
3. Wait ~10 seconds, then retry your `gws` command.
> [!TIP]
> You can also run `gws auth setup` which walks you through enabling all required
> APIs for your project automatically.
## Development
```bash
cargo build # dev build
cargo clippy -- -D warnings # lint
cargo test # unit tests
./scripts/coverage.sh # HTML coverage report → target/llvm-cov/html/
```
## License
Apache-2.0
## Disclaimer
> [!CAUTION]
> This is **not** an officially supported Google product.