`gws`: The Google Workspace CLI That Builds Itself From Google’s API Catalog

A runtime-discovered command tree, schema validation, auto-pagination, and agent skills make `gws` feel less like a wrapper and more like a compiler for Workspace operations.

9 min read • View on GitHub • More from googleworkspace

A wide black-ink editorial scene shows a Discovery Document scroll feeding a mechanical drafting machine. On one side the machine breaks into a branching terminal command tree for Workspace services, and on the other it resolves into a neat shell interface. The image explains that the CLI is derived from Google’s own API catalog instead of being hand-written command by command.
`gws` treats Google’s Discovery Documents like source material. The command tree is assembled from the API catalog, not frozen into a static wrapper.
Key Takeaways

The first thing to understand about `gws` is that it is not trying to be a prettier `curl` wrapper. It is trying to be a compiler for Google Workspace operations. It reads Google’s Discovery Documents, turns them into a live command tree, and uses that same schema to validate input, build requests, and stream results.

A CLI That Compiles Its Own Command Tree

The key move is not a wrapper around fixed commands. It is a translation layer that turns API metadata into commands, validation, and output behavior.

In the repo, the core idea is simple to describe and unusually hard to get right. `commands.rs` walks a `RestDescription`, maps resources to nested subcommands, and maps methods to executable leaf commands. That is why `gws drive files list` is not just a nice mnemonic. It is the visible end of a machine that has already read the API’s shape.

// Conceptual shape of the dynamic command builder
fn build_cli(doc: &RestDescription) -> Command {
    // resources become subcommands
    // methods become leaf commands
    // schemas drive validation and help text
    // the tree is assembled from Discovery metadata
    todo!()
}

Why Runtime Discovery Changes the Maintenance Model

Axis`gws`Static CLIs
Command modelDerived at runtime from Discovery DocumentsHard-coded and versioned in releases
API updatesCan absorb new methods without rewriting every commandRequires manual code and release work
ValidationUses schema metadata from the same sourceOften partial or hand-maintained
Agent readinessSkills and structured output are first-classUsually added later, if at all
Primary tradeoffMore dynamic, more moving partsSimpler to reason about, slower to evolve

This is the real maintenance shift. When Google adds or changes an endpoint, `gws` does not need to be rebuilt around a frozen command list. It still caches discovery data for speed, but the source of truth is upstream. That makes the CLI feel less like a product release and more like a live projection of the API surface.

built for humans and agents

Addy Osmani, Google Cloud Director · Google Workspace CLI: A New Era for Agentic AI

The Execution Engine Turns Flags Into Validated Requests

A close-up black-ink machine-room scene shows structured JSON entering a validation gate, moving through a request builder, and splitting into a pagination fan-out. A token-shaped loop routes response pages back into the fetch cycle while output streams downward as a paper-like data flow. The image explains how flags become validated API calls and how pagination is automated.
`gws` does not stop at command generation. It carries the same schema knowledge into validation, request building, and pagination.

This is where the architecture stops sounding clever and starts sounding useful. The executor takes `params` and body JSON, validates them against Discovery schemas, builds the HTTP request with `reqwest`, and then handles pagination automatically when the user asks for all pages. The point is that the command tree and the request engine are not separate systems. They are two views of the same metadata.

// Execution flow, simplified
1. Parse CLI flags
2. Validate params/body against Discovery schema
3. Build reqwest request
4. Send request
5. If page-all is enabled, follow nextPageToken
6. Stream results as NDJSON

That matters because validation happens before the network round trip. If the JSON is wrong, `gws` can tell you locally. If the response is paginated, `gws` can keep going without making the user hand-roll loops. The runtime-discovered command tree is only half the story. The other half is that execution remains schema-aware all the way through.

The Other Big Idea: `gws` Is Built for Agents, Not Just Humans

The CLI no longer writes a fallback .encryption_key text file on macOS and Windows when securely storing credentials. Instead, it strictly uses the native OS keychain

Justin Poehnelt, Key Contributor · Release v0.21.0 · googleworkspace/cli

The agent layer is not a side quest. It is part of the product shape. The repository includes a `skills/` directory and a `.agent/` workflow, which tells you the CLI is meant to be legible to models, not just convenient for people. `generate-skills` turns commands into structured instructions that an LLM can read and chain.

InterfaceWhat it optimizes forWhy it matters
Raw CLI commandsPower users and scriptsCompact, precise, and familiar
Skills filesLLM planning and tool useGives agents a readable action model
Structured JSON outputMachine consumptionReduces prompt fragility and parsing guesswork
`.agent/` workflowsVerification and orchestrationMakes the tool easier to embed in agent loops

That is a subtle but important move. Most CLIs assume the operator already knows the tool. `gws` assumes the operator may be a model that needs a clean contract. In that sense, the tool is not just a shell interface. It is a physical interface for a reasoning system.

Auth Is the Boring Problem `gws` Decided to Solve Well

Good infrastructure tools win or lose on setup. `gws` leans into that by automating the ugly parts of OAuth, project creation, and credential storage. It uses `aes-gcm` and keyring integration so secrets are handled with the kind of care that makes a terminal tool trustworthy enough to sit near real accounts.

That choice also changes adoption. A powerful CLI that is hard to authenticate becomes a demo. A powerful CLI that can guide users through auth becomes a habit. This is the sort of engineering that rarely gets a headline, but often decides whether a tool survives contact with real teams.

Why Rust Fits This Problem

Rust is not decorative here. `gws` deals with large discovery payloads, dynamic schema handling, concurrent network calls, and credential storage. Rust gives the project performance, type discipline, and a safer default for the parts that matter most when a CLI starts behaving like infrastructure.

NeedWhy Rust helps
Parsing and command assemblyFast enough to handle discovery-driven trees without feeling heavy
Schema handlingTypes help tame loosely structured API metadata
Credential safetyMemory safety pairs well with encrypted secret handling
CLI ergonomicsThe ecosystem already has strong primitives for terminal apps and async networking

The language choice is not the story by itself. It is the enabler. A dynamic CLI with validation, pagination, agent skills, and secure auth needs a runtime that can keep the moving parts contained.

How `gws` Compares to GAM, clasp, Nylas CLI, and CLI for Microsoft 365

ToolCategoryCommand modelAudienceAgent readiness
`gws`Workspace CLIRuntime-discovered from Google Discovery DocsHumans and agentsBuilt in
GAMAdmin utilityMostly static and admin-focusedWorkspace administratorsLimited
claspApps Script toolStatic, code-project orientedDevelopers writing Apps ScriptNot the focus
Nylas CLIMulti-provider CLIProvider-driven static surfaceTeams wanting one abstractionModest
CLI for Microsoft 365Microsoft ecosystem CLIStatic command setMicrosoft admins and developersSecondary

The comparison is less about winners and losers than about category. GAM is the long-standing admin workhorse. clasp is for managing Apps Script projects. Nylas aims for multi-provider simplicity. CLI for Microsoft 365 covers a similar ecosystem with a static command set. `gws` is different because it is runtime-discovered, Rust-based, Workspace-native, and explicitly shaped for agent use.

That combination is the point. `gws` does not merely expose Workspace APIs. It tries to stay aligned with them as they change, then package that alignment into a terminal interface that both people and models can actually use.