diff --git a/.changeset/optimize-demo-gif.md b/.changeset/optimize-demo-gif.md
new file mode 100644
index 0000000..bda765c
--- /dev/null
+++ b/.changeset/optimize-demo-gif.md
@@ -0,0 +1,5 @@
+---
+"@googleworkspace/cli": patch
+---
+
+Optimize demo GIF and improve README
diff --git a/README.md b/README.md
index 16c5736..ae274f3 100644
--- a/README.md
+++ b/README.md
@@ -1,16 +1,21 @@
-# gws — Google Workspace CLI
+# gws
-A CLI that generates its entire command surface dynamically from Google Discovery Service JSON documents. Includes skills for AI agents.
+**One CLI for all of Google Workspace.** Drive, Gmail, Calendar, Sheets, Docs, Chat, Admin — 24 services, 700+ API methods, zero boilerplate.
+
+`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 adds an API endpoint, `gws` picks it up automatically.
> [!IMPORTANT]
-> This project is currently under active development and is not yet ready for production use.
+> This project is under active development and is not yet ready for production use.

-## Install
+## Quick Start
```bash
npm install -g @googleworkspace/cli
+
+gws setup # walks you through Google Cloud project config + OAuth login
+gws drive files list --params '{"pageSize": 5}'
```
Or build from source:
@@ -19,245 +24,188 @@ Or build from source:
cargo install --path .
```
-## AI Agents & Skills
+---
-This repository includes [Agent Skills](https://github.com/vercel-labs/agent-skills) definitions (`SKILL.md`) for every supported Google Workspace API. Skills are prefixed with `gws-` to avoid namespace collisions when installed globally.
+## Why gws?
-You can install these skills directly into your AI agent using `npx`:
+**For humans** — stop writing `curl` calls against REST docs. `gws` gives you tab‑completion, `--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
-# Add all Google Workspace skills to your agent
-npx skills add github:googleworkspace/cli
-```
-
-Or add specific skills by path:
-
-```bash
-# Add the shared skill (authentication, etc.)
-npx skills add https://github.com/googleworkspace/cli/tree/main/skills/gws-shared
-
-# Add only Google Drive and Gmail skills
-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
-
-Clone the repo and copy (or symlink) the skills into your OpenClaw skills directory:
-
-```bash
-# All skills
-cp -r skills/gws-* ~/.openclaw/skills/
-
-# Or symlink for easy updates
-ln -s $(pwd)/skills/gws-* ~/.openclaw/skills/
-```
-
-Or copy only specific skills:
-
-```bash
-cp -r skills/gws-drive skills/gws-gmail ~/.openclaw/skills/
-```
-
-The `gws-shared` skill includes an `install` block so OpenClaw can auto-install the CLI via `npm i -g @googleworkspace/cli` if the `gws` binary isn't found on PATH.
-
-## Usage
-
-```bash
-# List files in Drive
+# List the 10 most recent files
gws drive files list --params '{"pageSize": 10}'
-# Get a file's metadata
-gws drive files get --params '{"fileId": "abc123"}'
-
# Create a spreadsheet
-gws sheets spreadsheets create --json '{"properties": {"title": "My Sheet"}}'
+gws sheets spreadsheets create --json '{"properties": {"title": "Q1 Budget"}}'
-# List Gmail messages
-gws gmail users messages list --params '{"userId": "me"}'
-
-# Introspect a method's schema
-gws schema drive.files.list
-
-# Dynamic help for any resource
-gws drive files --help
-gws drive files list --help
-
-# Preview a request without sending it
+# Send a Chat message
gws chat spaces messages create \
--params '{"parent": "spaces/xyz"}' \
- --json '{"text": "Hello world"}' \
+ --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 three primary authentication workflows depending on your environment.
+The CLI supports multiple auth workflows so it works on your laptop, in CI, and on a server.
-### 1. Interactive Auth (Local Desktop)
+### Interactive (local desktop)
-For interactive use on your personal machine where a web browser is available.
-
-**Security**: By default, credentials and access tokens are encrypted at rest using AES-256-GCM. The encryption key is stored securely in your OS Keyring (Apple Keychain, Secret Service, or Windows Credential Manager). If a keyring is unavailable (e.g., headless Linux), it falls back to a strictly permissioned (`0600`) local key file.
-
-**Google Cloud Setup & Login:**
-The CLI includes a built-in setup wizard to help you configure your Google Cloud Project, enable APIs, and generate the necessary OAuth credentials. Note that this requires the [`gcloud` CLI](https://cloud.google.com/sdk/docs/install) to be installed and authenticated (`gcloud auth login`).
+Credentials are encrypted at rest (AES-256-GCM) with the key stored in your OS keyring.
```bash
-# Run the interactive setup and login wizard
-gws setup
-
-# Or login directly if you already have client_secret.json configured
-gws auth login
-
-# Or login with custom scopes
-gws auth login --scopes "https://www.googleapis.com/auth/drive,https://www.googleapis.com/auth/gmail.readonly"
+gws setup # one-time: creates a Cloud project, enables APIs, logs you in
+gws auth login # subsequent logins
```
-### 2. Headless & CI/CD Auth (Export Flow)
+> Requires the [`gcloud` CLI](https://cloud.google.com/sdk/docs/install) to be installed and authenticated.
-For remote servers, SSH sessions, or CI/CD pipelines where a browser is unavailable, use the export flow.
+### Headless / CI (export flow)
-1. On your **local machine** (with a browser), complete the Interactive Auth steps above.
-2. Export your credentials to a portable JSON format:
+1. Complete interactive auth on a machine with a browser.
+2. Export credentials:
```bash
gws auth export --unmasked > credentials.json
```
-3. On your **headless machine**, securely transfer `credentials.json` and point the CLI to it. The CLI will automatically use this payload to mint fresh access tokens.
+3. On the headless machine:
```bash
export GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE=/path/to/credentials.json
-
- # Commands now work headlessly!
- gws drive files list
+ gws drive files list # just works
```
-*Note: You can also strictly provide a short-lived access token directly via environment variable (e.g. `export GOOGLE_WORKSPACE_CLI_TOKEN=$(gcloud auth print-access-token)`), though this token will naturally expire in ~1 hour.*
+### Service Account (server-to-server)
-### 3. Service Account Auth (Server-to-Server)
-
-For automated programmatic access. Point `GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE` to your service account JSON key file. No login step is required.
+Point to your key file; no login needed.
```bash
export GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE=/path/to/service-account.json
gws drive files list
```
-**Domain-Wide Delegation (Impersonation)**
-If your service account has Domain-Wide Delegation enabled, you can impersonate a Workspace user (e.g., an admin) to perform actions on their behalf.
+For Domain-Wide Delegation, add:
```bash
-export GOOGLE_WORKSPACE_CLI_IMPERSONATED_USER=user@example.com
+export GOOGLE_WORKSPACE_CLI_IMPERSONATED_USER=admin@example.com
```
-### 4. Pre-obtained Access Token (CI/CD or External)
+### Pre-obtained Access Token
-The simplest way to authenticate if you already possess a short-lived access token. This is often used in CI/CD pipelines where another tool (like `gcloud`) mints the token for the environment.
+Useful when another tool (e.g. `gcloud`) already mints tokens for your environment.
```bash
-# Obtain a token using the gcloud CLI
export GOOGLE_WORKSPACE_CLI_TOKEN=$(gcloud auth print-access-token)
-gws drive files list
```
-*(Note: These raw access tokens typically expire in ~1 hour).*
+
+### Precedence
+
+| Priority | Source | Set via |
+|----------|--------|---------|
+| 1 | Access token | `GOOGLE_WORKSPACE_CLI_TOKEN` |
+| 2 | Credentials file | `GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE` |
+| 3 | Encrypted credentials (OS keyring) | `gws auth login` |
+| 4 | Plaintext credentials | `~/.config/gws/credentials.json` |
+
+Environment variables can also live in a `.env` file.
---
-### Auth Precedence Order
+## AI Agent Skills
-The CLI evaluates authentication sources in the following strict order:
+The repo ships 40+ [Agent Skills](https://github.com/vercel-labs/agent-skills) (`SKILL.md` files) — one for every supported API, plus higher-level helpers for common workflows like sending email, triaging a Gmail inbox, or subscribing to calendar events.
-| Priority | Source | How to set |
-|----------|--------|------------|
-| 1 (highest) | Raw access token | `GOOGLE_WORKSPACE_CLI_TOKEN` env var |
-| 2 | Credentials file (user or service account) | `GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILE` env var |
-| 3 | Encrypted credentials & token cache | `~/.config/gws/credentials.enc` and `token_cache.json` (created by `gws auth login`, secured via OS Keyring) |
-| 4 | Plaintext credentials | `~/.config/gws/credentials.json` |
-| — | No auth | Proceeds unauthenticated; shows error if the API rejects |
+```bash
+# Install all skills at once
+npx skills add github:googleworkspace/cli
-*(Note: Environment variables can also be set via a `.env` file in the working directory.)*
+# 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.
+
+
+
+---
+
+## 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 |
+
+### Model Armor (Response Sanitization)
+
+Integrate [Google Cloud Model Armor](https://cloud.google.com/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` |
+
+---
## Architecture
-The CLI uses a **two-phase argument parsing** strategy:
+`gws` uses a **two-phase parsing** strategy:
-1. Extract the service name from `argv[1]`
-2. Fetch the service's Discovery Document (cached for 24h)
-3. Build a dynamic `clap::Command` tree from the document's resources/methods
-4. Re-parse the remaining arguments against the tree
-5. Authenticate, construct the HTTP request, and execute
+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, error, file download metadata) is structured JSON for AI agent consumption. Binary outputs require an `--output` flag.
+All output — success, errors, download metadata — is structured JSON.
-There are a few special behaviors to be aware of that diverge from the Discovery Service API representation:
+---
-### Multipart uploads
-
-For multipart uploads (e.g. Drive file uploads), use the `--upload` flag to specify the path to the file to upload.
+## Development
```bash
-gws drive files create --json '{"name": "My File"}' --upload /path/to/file
+cargo build # dev build
+cargo clippy -- -D warnings # lint
+cargo test # unit tests
+./scripts/coverage.sh # HTML coverage report → target/llvm-cov/html/
```
-### Pagination and NDJSON
+---
-Use `--page-all` to auto-paginate through results. Each page is emitted as a single JSON line (NDJSON), making it easy to stream into tools like `jq`.
-
-| Flag | Description | Default |
-| --- | --- | --- |
-| `--page-all` | Auto-paginate, one JSON line per page | off |
-| `--page-limit ` | Max pages to fetch | 10 |
-| `--page-delay ` | Delay between pages in ms | 100 |
-
-```bash
-# Stream all Drive files as NDJSON
-gws drive files list --params '{"pageSize": 100}' --page-all --page-limit 5
-
-# Pipe to jq to extract file names
-gws drive files list --params '{"pageSize": 100}' --page-all | jq -r '.files[].name'
-```
-
-## Testing & Coverage
-
-Run unit tests:
-```bash
-cargo test
-```
-
-Generate code coverage report (requires `cargo-llvm-cov`):
-```bash
-./scripts/coverage.sh
-```
-The report will be available at `target/llvm-cov/html/index.html`.
-
-## Security & Sanitization (Model Armor)
-
- The CLI integrates with **Google Cloud Model Armor** to sanitize API responses for prompt injection risks before they reach your AI agent.
-
- ```bash
- # Sanitize a specific command
- gws gmail users messages get --params '...' \
- --sanitize "projects/P/locations/L/templates/T"
- ```
-
- This checks the *entire* JSON response against the specified Model Armor template.
-
- ### Configuration
-
- You can set default behavior via environment variables:
-
- | Variable | Description |
- |---|---|
- | `GOOGLE_WORKSPACE_CLI_SANITIZE_TEMPLATE` | Default Model Armor template resource name |
- | `GOOGLE_WORKSPACE_CLI_SANITIZE_MODE` | `warn` (default) or `block`. |
-
- - **Warn mode**: Prints a warning to stderr and annotates the JSON with `_sanitization` details.
- - **Block mode**: Suppresses the output entirely and exits with an error if a match is found.
-
- ### Requirements
-
- Using `--sanitize` requires the `https://www.googleapis.com/auth/cloud-platform` scope.
-
- ## License
+## License
Apache-2.0
diff --git a/demo.gif b/demo.gif
index 00add40..1fba83f 100644
Binary files a/demo.gif and b/demo.gif differ
diff --git a/package.json b/package.json
index c82d5a6..8ab31b5 100644
--- a/package.json
+++ b/package.json
@@ -30,15 +30,23 @@
"packageManager": "pnpm@10.0.0",
"keywords": [
"cli",
- "rust",
"google-workspace",
"google",
- "drive",
- "gmail",
- "sheets",
- "calendar",
+ "google-api",
+ "google-drive",
+ "google-gmail",
+ "google-sheets",
+ "google-calendar",
+ "google-docs",
+ "google-chat",
+ "google-admin",
+ "gsuite",
"discovery-api",
- "skills"
+ "ai-agent",
+ "agent-skills",
+ "automation",
+ "oauth2",
+ "rust"
],
"devDependencies": {
"@changesets/cli": "^2.29.8",