gws doesn’t ship a static list of commands. Instead, it reads Google’s own Discovery Service at runtime and builds its entire command surface dynamically. When Google Workspace adds an API endpoint or method, gws picks it up automatically — no code changes or releases required.
This approach means zero static command definitions exist in the codebase. Every command you see in --help is generated from a Discovery Document fetched at runtime.
Discovery Documents are fetched over HTTPS and cached locally with a 24-hour TTL to minimize network latency:
Copy
Ask AI
// From src/discovery.rs:186-240pub async fn fetch_discovery_document( service: &str, version: &str,) -> anyhow::Result<RestDescription> { let cache_dir = dirs::config_dir() .unwrap_or_else(|| std::path::PathBuf::from(".")) .join("gws") .join("cache"); std::fs::create_dir_all(&cache_dir)?; let cache_file = cache_dir.join(format!("{service}_{version}.json")); // Check cache (24hr TTL) if cache_file.exists() { if let Ok(metadata) = std::fs::metadata(&cache_file) { if let Ok(modified) = metadata.modified() { if modified.elapsed().unwrap_or_default() < std::time::Duration::from_secs(86400) { let data = std::fs::read_to_string(&cache_file)?; let doc: RestDescription = serde_json::from_str(&data)?; return Ok(doc); } } } } let url = format!("https://www.googleapis.com/discovery/v1/apis/{service}/{version}/rest"); let client = crate::client::build_client()?; let resp = client.get(&url).send().await?; let body = if resp.status().is_success() { resp.text().await? } else { // Try the $discovery/rest URL pattern used by newer APIs (Forms, Keep, Meet, etc.) let alt_url = format!("https://{service}.googleapis.com/$discovery/rest?version={version}"); let alt_resp = client.get(&alt_url).send().await?; if !alt_resp.status().is_success() { anyhow::bail!( "Failed to fetch Discovery Document for {service}/{version}: HTTP {} (tried both standard and $discovery URLs)", alt_resp.status() ); } alt_resp.text().await? }; // Write to cache if let Err(e) = std::fs::write(&cache_file, &body) { let _ = e; // Non-fatal } let doc: RestDescription = serde_json::from_str(&body)?; Ok(doc)}
You can inspect any method’s schema without executing it:
Copy
Ask AI
# View request/response schemas for a methodgws schema drive.files.list# Resolve all $ref pointers for deep inspectiongws schema drive.files.create --resolve-refs