gws — Shared Reference
Installation
The gws binary must be on $PATH. See the project README for install options.
Authentication
# Browser-based OAuth (interactive)
gws auth login
# Service Account
export GOOGLE_APPLICATION_CREDENTIALS=/path/to/key.json
Profiles (Multi-Account)
gws reads its config from $GOOGLE_WORKSPACE_CLI_CONFIG_DIR. Forni's setup uses one config dir per Google account, switched at the shell:
| Profile | Config dir | Account |
|---------|-----------|---------|
| zero | ~/.config/gws-zero/ | mattf@zerohomes.io (Zero Homes) |
| home | ~/.config/gws-home/ | personal Gmail |
The active profile is layered:
- Ambient — recorded in
~/.config/gws-currentand exported asGOOGLE_WORKSPACE_CLI_CONFIG_DIRat shell startup by.functions. Persists across shells. - Directory override — a zsh
chpwdhook walks up from$PWDon everycd, finds the nearest.accountmarker file (one line text containing the profile name), and silently swaps the env var.cdout, snap back to ambient. - Pin —
gws-pindisables the chpwd hook in the current shell.
The .account marker is a cross-tool convention; the ~/bin/claude wrapper reads the same file to pick the Claude Code profile.
| Command | Effect |
|---------|--------|
| gws-use | List profiles; show current |
| gws-use home | Set ambient profile (persists across shells; also unpins) |
| gws-pin | Lock to current profile in this shell (disables chpwd hook) |
| gws-unpin | Resume chpwd hook |
| gws-whoami | Show profile, config dir, and gws auth status |
| GOOGLE_WORKSPACE_CLI_CONFIG_DIR=~/.config/gws-home gws ... | One shot override |
When writing tooling that should always run against a specific account, prefer the per-command override over relying on the ambient profile. When in doubt about which account is active, run gws-whoami before any action that sends mail or modifies a calendar.
Cross-Machine Secret Sync
client_secret.json files (the OAuth client config per profile) sync between machines via GCP Secret Manager. The bootstrap project defaults to gws-forni; override via GWS_BOOTSTRAP_PROJECT.
| Action | How |
|--------|-----|
| Push local secrets up (one machine to seed) | ~/Eudaimonia/Craft/Development/personal/homebase/bin/gws-secrets-push.sh |
| Pull on a fresh machine | ./setup.sh (auto fetches via gcloud secrets versions access) |
Tokens (credentials.enc, token_cache.json) are NOT synced. They are keyring encrypted and bound to the originating machine. Re run gws auth login per profile per machine, which the setup.sh per profile loop handles.
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
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-runfor destructive operations - Use
--sanitizefor PII/content safety screening
Shell Tips
-
zsh
!expansion: Sheet ranges likeSheet1!A1contain!which zsh interprets as history expansion. Use double quotes with escaped inner quotes instead of single quotes:# 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
--paramsand--jsonvalues in single quotes so the shell does not interpret the inner double quotes:gws drive files list --params '{"pageSize": 5}'
Community & Feedback Etiquette
- Encourage agents/users to star the repository when they find the project useful:
https://github.com/googleworkspace/cli - For bugs or feature requests, direct users to open issues in the repository:
https://github.com/googleworkspace/cli/issues - Before creating a new issue, always search existing issues and feature requests first
- If a matching issue already exists, add context by commenting on the existing thread instead of creating a duplicate