The gws CLI is designed for both human and machine consumption. Every response — success, error, or download metadata — is structured JSON by default. This makes it trivial to pipe output to jq, parse in scripts, or process in AI agent workflows.
Unlike traditional CLIs that mix human-readable text with machine-parseable output, gws guarantees all stdout is valid JSON (or NDJSON for paginated responses).
id name mimeType────────────── ───────────────────── ────────────────────────────────────1a2b3c4d5e6f My Document application/vnd.google-apps.document7g8h9i0j1k2l Spreadsheet Q1 2025 application/vnd.google-apps.spreadsheet
Features:
Automatically extracts array data from list responses
Nested objects are flattened into dot-notation columns (e.g., owner.displayName)
Columns are auto-sized (capped at 60 chars)
Multi-byte UTF-8 characters are handled safely
Implementation in src/formatter.rs:163-271:
Copy
Ask AI
fn format_array_as_table(arr: &[Value], emit_header: bool) -> String { if arr.is_empty() { return "(empty)\n".to_string(); } // Flatten each row so nested objects become dot-notation columns. let flat_rows: Vec<Vec<(String, String)>> = arr .iter() .map(|item| match item { Value::Object(obj) => flatten_object(obj, ""), _ => vec![(String::new(), value_to_cell(item))], }) .collect(); // Collect all unique column names (preserving insertion order). let mut columns: Vec<String> = Vec::new(); for row in &flat_rows { for (key, _) in row { if !columns.contains(key) { columns.push(key.clone()); } } } // ... calculate widths, render table}
When a required API is not enabled for your GCP project, the error includes a direct link to enable it:
Copy
Ask AI
{ "error": { "code": 403, "message": "Gmail API has not been used in project 549352339482 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/gmail.googleapis.com/overview?project=549352339482 then retry.", "reason": "accessNotConfigured", "enable_url": "https://console.developers.google.com/apis/api/gmail.googleapis.com/overview?project=549352339482" }}
A human-readable hint is also printed to stderr (not stdout, so it doesn’t pollute JSON parsing):
Copy
Ask AI
💡 API not enabled for your GCP project. Enable it at: https://console.developers.google.com/apis/api/gmail.googleapis.com/overview?project=549352339482 After enabling, wait a few seconds and retry your command.
When using --page-all with --format csv or --format table, the CLI only emits column headers on the first page. Subsequent pages contain only data rows, so the combined output is machine-parseable:
Copy
Ask AI
gws drive files list --params '{"pageSize": 2}' --page-all --format csv