---
name: gws-shared
version: 1.0.0
description: "gws CLI: Shared patterns for authentication, global flags, and output formatting."
metadata:
  openclaw:
    category: "productivity"
    requires:
      bins: ["gws"]
---

# gws — Shared Reference

> **Mode:** This CLI is **power-user / local (nomos-mac) mode only**, where Google is
> reached through the local `gws` CLI. In **hosted mode** there is no local CLI: the
> user connects Google entirely in the app at **Settings → Integrations → Google**
> (server-side OAuth). Never tell a hosted user to run a terminal command.

## Installation

`gws` ships as the `@googleworkspace/cli` npm dependency and is invoked as
`npx @googleworkspace/cli …` (the bare `gws` command is not assumed to be on `$PATH`).
If it is missing, install it in the project with `pnpm add @googleworkspace/cli` and
verify with `npx @googleworkspace/cli --version`.

## Authentication

The product path is the Nomos Settings UI at **Integrations → Google**
(`/integrations/google`): it captures the OAuth Client ID / Secret / GCP project and
finalizes the account. The terminal path below is a fallback for when credentials are
already configured in `~/.config/gws/`.

```bash
# First time only: bootstrap OAuth credentials (requires gcloud)
npx @googleworkspace/cli auth setup

# Browser-based OAuth (interactive)
npx @googleworkspace/cli auth login
```

Never tell the user to open "Claude Code" settings (this product is Nomos), and never
suggest `npx gws auth login` (the npm package is `@googleworkspace/cli`, not `gws`).

> Advanced: a service account can be used instead by setting
> `GOOGLE_APPLICATION_CREDENTIALS=/path/to/key.json`. This is not how the standard local
> deployment connects Google; prefer `auth login`.

## Global Flags

| Flag                    | Description                                             |
| ----------------------- | ------------------------------------------------------- |
| `--format <FORMAT>`     | Output format: `json` (default), `table`, `yaml`, `csv` |
| `--dry-run`             | Validate locally without calling the API                |
| `--sanitize <TEMPLATE>` | Screen responses through Model Armor                    |

## CLI Syntax

```bash
gws <service> <resource> [sub-resource] <method> [flags]
```

### Method Flags

| Flag                        | Description                                   |
| --------------------------- | --------------------------------------------- |
| `--params '{"key": "val"}'` | URL/query parameters                          |
| `--json '{"key": "val"}'`   | Request body                                  |
| `-o, --output <PATH>`       | Save binary responses to file                 |
| `--upload <PATH>`           | Upload file content (multipart)               |
| `--page-all`                | Auto-paginate (NDJSON output)                 |
| `--page-limit <N>`          | Max pages when using --page-all (default: 10) |
| `--page-delay <MS>`         | Delay between pages in ms (default: 100)      |

## Security Rules

- **Never** output secrets (API keys, tokens) directly
- **Always** confirm with user before executing write/delete commands
- Prefer `--dry-run` for destructive operations
- Use `--sanitize` for PII/content safety screening

## Shell Tips

- **zsh `!` expansion:** Sheet ranges like `Sheet1!A1` contain `!` which zsh interprets as history expansion. Use double quotes with escaped inner quotes instead of single quotes:

  ```bash
  # WRONG (zsh will mangle the !)
  gws sheets +read --spreadsheet ID --range 'Sheet1!A1:D10'

  # CORRECT
  gws sheets +read --spreadsheet ID --range "Sheet1!A1:D10"
  ```

- **JSON with double quotes:** Wrap `--params` and `--json` values in single quotes so the shell does not interpret the inner double quotes:
  ```bash
  gws drive files list --params '{"pageSize": 5}'
  ```
