| title | Automation |
|---|---|
| description | Use gog safely from scripts, CI, and agents with stable output, exit codes, and runtime policy discovery. |
gog has one command surface for humans and automation. There is no separate
agent mode or agent command namespace.
Root help summarizes the human-facing contract:
gog --help
gog help drive lsgog help <command> and gog <command> --help are equivalent. Once a help
flag is present, trailing arguments are ignored so recovery help remains
available after a malformed command attempt.
The machine-readable contract is:
gog schema --jsonThe schema contains the complete command tree, arguments, flags, stable exit codes, output formats, and effective safety state for that invocation.
Use --json for structured output or --plain for stable TSV. Primary data is
written to stdout; prompts, progress, warnings, and diagnostics are written to
stderr.
gog --json gmail search 'newer_than:7d'
gog --plain calendar events --today--results-only and --select transform JSON and therefore require
--json. Contradictory output flags fail with usage exit code 2 instead of
being silently ignored. Explicit output flags override GOG_JSON and
GOG_PLAIN environment defaults. gog schema always emits JSON and rejects
--plain.
--fields is accepted as an alias for --select output projection on commands
that do not define their own API field-mask --fields; commands with a local
field-mask flag keep that command-specific meaning.
--results-only unwraps the primary result before --select projects it. For
lists, select item-relative fields: --results-only --select id. Dot paths
traverse object keys or numeric array indexes; they do not broadcast through
nested arrays (--select items.id selects nothing). Unmatched object fields
are omitted.
Use --no-input in CI and unattended processes. Use --wrap-untrusted when
Google-hosted free text will be consumed by an LLM or another instruction-aware
system. Chat message and thread listings also wrap flattened sender display
names. Raw Chat JSON responses, including those from gog api call, wrap
formattedText too. Without the flag, ordinary JSON strings remain unchanged.
Use --readonly (or GOG_READONLY=1) as a runtime backstop. It permits GET,
HEAD, OPTIONS, and the small allowlist of Google APIs whose query operations use
POST, while rejecting mutating API requests before network dispatch. This guard
is independent of OAuth scopes and command names, propagates into MCP child
processes, and also blocks Zoom meeting mutations. gog auth add --readonly
continues to request read-only OAuth scopes where Google provides them.
gog --readonly --account you@example.com gmail search 'newer_than:7d'
gog --readonly --account you@example.com calendar freebusy you@example.comInteractive browser commands fail fast under --no-input. Preview
gog auth manage with --dry-run; use gog auth import for unattended token
installation.
Runtime command lists (--enable-commands, --enable-commands-exact, and
--disable-commands, including their environment defaults) reject nonblank
values containing only commas and whitespace with usage exit code 2. Empty
values still clear that runtime list; omit a list or pass an empty value to leave
it unset. Extra commas around actual command names are accepted.
The top-level automation object has three parts:
| Field | Meaning |
|---|---|
output_formats |
Stable machine-output modes supported by the CLI. |
exit_codes |
Named process exit statuses for branching without parsing stderr. |
safety |
Effective runtime flags, command guards, and baked safety profile. |
Example:
gog \
--enable-commands-exact schema,gmail.search \
--gmail-no-send \
--readonly \
--no-input \
--wrap-untrusted \
schema --json |
jq '.automation'The safety snapshot describes the current invocation. Apply the same global flags to the operation:
common_flags=(
--account you@example.com
--enable-commands-exact schema,gmail.search
--gmail-no-send
--readonly
--no-input
--wrap-untrusted
)
gog "${common_flags[@]}" schema --json |
jq -e '
.schema_version == 1 and
.automation.safety.no_input and
.automation.safety.wrap_untrusted and
.automation.safety.gmail_no_send and
.automation.safety.readonly and
(.automation.safety.command_rules.enabled_exact | index("gmail.search"))
'
gog "${common_flags[@]}" gmail search 'newer_than:7d' --jsonSchema output does not validate credentials, refresh OAuth tokens, test Google API access, or attest to a later process. Use:
gog auth list --check --json --no-input
gog auth doctor --check --json --no-inputThese commands treat failed checks as diagnostic results. If they emit the
report successfully, they can exit 0 even when authentication is unhealthy.
For an OAuth-token preflight, require auth doctor top-level status to be
ok before continuing:
doctor_json="$(gog --no-input --json auth doctor --check)" &&
printf '%s\n' "$doctor_json" | jq -se 'length == 1 and .[0].status == "ok"' >/dev/null &&
run_next_commandThe assignment stops the chain if gog fails, while jq -se requires exactly
one result and rejects empty or malformed output and any warn or error
status. For auth list --check, inspect each account's valid and error
fields. A service-account row with valid: true and
error: "service account (not checked)" only confirms local configuration; it
does not prove provider access. Service accounts, Application Default
Credentials, and GOG_ACCESS_TOKEN should instead be validated with a
least-privilege read against the intended service.
Google API rate-limit retries honor Retry-After delays up to 60 seconds per
retry, including numeric seconds and HTTP dates. Cancelling the command also
cancels a pending retry wait. Upload bodies are closed even when a request is
rejected by the circuit breaker or cannot be buffered for retry, so those
failures release the associated file or stream resources.
Command cancellation also stops in-flight YouTube requests, Chat unread-message lookups and sends, and People profile and relation reads.
If sheets append reports missing update metadata, it returns an error without
success output or another append attempt. Inspect the spreadsheet before
retrying: the write may have succeeded despite the incomplete response.
| Code | Name | Meaning |
|---|---|---|
| 0 | ok |
Success |
| 1 | error |
Generic or unclassified failure |
| 2 | usage |
Invalid command syntax, arguments, or flags |
| 3 | empty_results |
Successful query with no results where empty-result signaling applies |
| 4 | auth_required |
Missing, expired, revoked, or unusable authentication |
| 5 | not_found |
Requested resource does not exist |
| 6 | permission_denied |
Authenticated caller lacks permission |
| 7 | rate_limited |
API quota or rate limit reached |
| 8 | retryable |
Transient server, network timeout, or circuit-breaker failure |
| 10 | config |
Required local configuration or credentials are missing |
| 11 | orphaned |
Requested Docs comment is no longer attached to content |
| 130 | cancelled |
Interrupted with Ctrl-C or context cancellation |
Malformed local payloads, such as invalid token-import JSON or timestamps, use
usage (2). Commands that cannot run because their required local setup is
absent or incomplete use config (10).
If Google rejects an OAuth token refresh with invalid_grant, ordinary service
commands exit with auth_required (4) and retain their reauthorization
advice, including in --no-input and --readonly runs. The diagnostic
commands above instead report the failed check in their structured result.
The same classifications apply to direct HTTP integrations such as Photos
Library, Photos Picker, and Places. For example, an expired or deleted Picker
session returns not_found (5) instead of a generic error.
Read the map programmatically:
gog schema --json | jq '.automation.exit_codes'Automation should branch on exit status rather than human error text:
if output=$(gog --no-input --json drive get "$file_id"); then
printf '%s\n' "$output"
else
rc=$?
case $rc in
4) printf '%s\n' "authentication required" >&2 ;;
5) printf '%s\n' "file not found" >&2 ;;
7|8) printf '%s\n' "retry later" >&2 ;;
*) exit "$rc" ;;
esac
fiNew classifications may be added. Keep a generic non-zero fallback.
gog api call and gog api describe share a 24-hour on-disk cache of
Discovery documents under the configured cache directory's discovery
subdirectory. It keeps at most 32 documents and 64 MiB, evicting the oldest
documents; individual documents are limited to 16 MiB. API versions, endpoint
overrides and service-hosted fallback behavior use separate cache keys.
Pass --no-cache to either command to fetch without reading or writing this
cache. Missing, expired or corrupt entries are fetched again. Cache failures
do not prevent network access, and failed fetches are not cached. api list
and actual API responses remain uncached; authorization and command-policy
checks still run on every call.
gog api list --plain emits TSV columns NAME, VERSION, TITLE,
DESCRIPTION, and PREFERRED. Embedded line breaks and terminal controls are
normalized or escaped so each API occupies one row. Default output and --json
preserve the full Discovery catalog response, including its metadata.
MCP uses its standard tools/list request for client-side tool discovery. To
inspect the filtered server surface from a shell before starting it:
gog mcp --list-tools
gog mcp --allow-tool gmail_search,docs_get --list-toolsWrite tools remain hidden unless --allow-write is set and the tool also
matches --allow-tool.
In JSON mode (--json, -j, --machine, or the JSON environment defaults),
a failed command emits one object on stdout with error.code, error.message,
and error.class. The numeric code matches the exit status; the class uses the
stable exit-code names above, such as usage, auth_required, or retryable.
Explicit --json=false also disables automatic JSON selection.
Human diagnostics on stderr remain unchanged. Error envelopes bypass
--results-only and --select so their fields remain available.
If a command has already written output, gog preserves that output and does not
append an error object. This includes an empty list with --fail-empty (exit 3)
and commands that report partial progress before failing. Always check the exit
status, even when stdout contains a normal result.
Paged list envelopes using the common paginator, and Drive file lists, include
count (the number of returned result rows) and has_more (whether
nextPageToken is nonempty). Existing command-specific aggregate values take
precedence. These fields do not represent the total number of matching rows on
the server. --results-only still unwraps the primary result collection and
removes envelope metadata.
Running gog without arguments now shows the executable path, description, and
local auth/config status instead of help. Explicit gog --help still shows the
command overview. JSON environment defaults produce the status object alone,
without the text header. Normal command restrictions also apply to this implicit
status command.