If you’ve ever written a quick script against Google Drive or Gmail, you know the setup takes longer than the script: create a Cloud project, enable the API, sort out OAuth, install a client library, then finally make the one call you needed. The Google Workspace CLI, gws, skips most of that. It gives you terminal commands for the Workspace APIs, returns JSON, and handles auth for you.
This guide covers what gws is, how to install and authenticate it, the command patterns worth learning, and where it fits compared with the Admin console and client libraries. Commands here are taken from the project’s GitHub README. Check it for the latest syntax, because the tool is changing fast.
What gws is (and isn’t)
A few facts worth knowing up front:
- It’s written in Rust and ships as a single binary.
- Commands are generated from Google’s Discovery Service at runtime. There’s no hand-maintained list of commands. If an API is in the Discovery Service,
gwscan call it, and new API methods show up without a CLI update. - Everything outputs structured JSON, which makes it easy to pipe into
jqor other tools. - It’s not an officially supported Google product. The README says so directly. It lives under the
googleworkspaceGitHub organisation, but you shouldn’t treat it like a supported enterprise tool with an SLA.
Installing it
There are several options. Pick whichever matches your setup:
# Homebrew (macOS/Linux)
brew install googleworkspace-cli
# npm
npm install -g @googleworkspace/cli
# From source with Cargo
cargo install --git https://github.com/googleworkspace/cli --locked
You can also download a prebuilt binary from the GitHub releases page and put it on your PATH. Note that it isn’t a Python package, so some older tutorials that suggest pip install are wrong.
Authentication: the part that trips people up
The smoothest route uses the gcloud CLI to create the OAuth setup for you:
gws auth setup
gws auth login
If you’d rather create the OAuth client yourself, download the client JSON from Google Cloud Console, save it as ~/.config/gws/client_secret.json, and run gws auth login.
One step people often miss: if your OAuth consent screen is in testing mode, you have to add your own account as a test user, or login fails with a confusing error.
For automation there are non-interactive options:
GOOGLE_WORKSPACE_CLI_TOKENtakes an access token directly.GOOGLE_WORKSPACE_CLI_CREDENTIALS_FILEpoints to an OAuth credentials file or a service account key.
For CI, the README describes authenticating on a normal machine, exporting the credentials and importing them on the headless system. Treat those files like passwords. They should live in your CI secret store, never in the repository.
The command pattern
Once you see the pattern, the whole API surface becomes predictable:
gws <service> <resource> <method> [--params JSON] [--json JSON]
It mirrors the REST API. --params holds query or path parameters, and --json holds the request body. So the Drive API’s files.list becomes:
gws drive files list --params '{"pageSize": 5}'
And creating a spreadsheet, which is spreadsheets.create with a body, looks like this:
gws sheets spreadsheets create --json '{"properties": {"title": "Q1 Budget"}}'
If you already know the REST API reference for a service, you already know the CLI.
Recipes you’ll actually use
Find spreadsheets modified since a date
Drive search queries contain single quotes, which clash with shell quoting. Building the JSON with jq avoids the escaping mess:
Q="mimeType='application/vnd.google-apps.spreadsheet' and modifiedTime > '2026-09-01T00:00:00'"
gws drive files list --params "$(jq -n --arg q "$Q" '{q: $q, pageSize: 20}')"
Pull just the file names out of the JSON
gws drive files list --params '{"pageSize": 50}' | jq -r '.files[].name'
Search Gmail
Gmail’s API is scoped to a user, so the path includes userId. The query uses the same syntax as the Gmail search box:
gws gmail users messages list --params '{"userId": "me", "q": "from:billing@example.com is:unread"}'
Use the helper commands
Raw API calls can be long-winded for common tasks, so gws includes helper commands prefixed with +:
gws gmail +send --to alice@example.com --subject "Build finished" --body "All tests passed."
gws calendar +agenda --timezone Asia/Karachi
Upload a file
gws drive files create --json '{"name": "report.pdf"}' --upload ./report.pdf
Flags worth knowing
--dry-runshows the request that would be sent without sending it. Use it before anything that changes or deletes data.--page-allfollows pagination for you and streams results as newline-delimited JSON, which is handy for large exports.
Admin tasks
Because commands come from the Discovery Service, Admin SDK APIs such as the Directory API are reachable too, provided your account has admin rights and the right OAuth scopes. The exact service and resource names follow the API’s discovery document, so run gws --help and drill down rather than guessing. For bulk admin changes, always start with --dry-run and a small test organisational unit.
Using gws with AI agents
The repository ships a large set of “Agent Skills”, one per API plus workflow recipes, so coding agents can use gws as a tool. There’s also an extension for Gemini CLI. The README describes installing them like this:
npx skills add https://github.com/googleworkspace/cli
gemini extensions install https://github.com/googleworkspace/cli
This is genuinely useful. An agent that can list your unread email or build a spreadsheet through a well-defined CLI is easier to control than one improvising HTTP calls. But it also means the agent acts with your Google credentials. Give it an account or OAuth client with only the scopes it needs, and review what it does before letting it send mail or delete files on its own. The project also mentions integration with Google’s Model Armor for sanitising responses, which is aimed at reducing prompt-injection risk from content the agent reads.
Security checklist
- Least privilege: request only the OAuth scopes a script needs. A report script doesn’t need permission to delete Drive files.
- Separate identities for automation: use a dedicated account or service account for scheduled jobs, not your personal admin account.
- Protect credential files: keep
~/.config/gwsreadable only by your user, and keep tokens out of shell history and repositories. - Dry-run destructive commands. It takes a second and saves you from a very bad afternoon.
- Remember the support status. For business-critical automation, pin a version and test upgrades before rolling them out.
When to use something else
gws is great for ad-hoc queries, shell scripts, cron jobs and giving agents a clean tool. For a long-lived application with complex logic, retries and tests, the official client libraries in Python, Node or Go are still the better foundation. For one-off admin changes, the Admin console is often quicker. The CLI fills the gap between those two, and it fills it well.