gog
Use gog for Gmail/Calendar/Drive/Contacts/Sheets/Docs. Requires a one-time OAuth setup per user before any command works.
First run — always check auth state first
Before doing anything, run:
gog auth credentials list
gog auth list
- If the first says "No OAuth client credentials stored", jump to "Step 1" below — the user must create an OAuth client in Google Cloud Console. Do not retry
gog auth add; it cannot succeed without credentials. "No tokens stored" from the second command is a symptom of the same problem, not a separate issue. - If the first shows a client but the second says "No tokens stored", jump to "Step 2".
- If both show entries, auth is ready — skip setup.
Step 1 — Create OAuth client credentials (one-time, requires the user)
gog needs its own OAuth client created in the user's Google Cloud project. This step cannot be automated — the user must visit the Google Cloud Console in a browser. Ask the user to:
- Open https://console.cloud.google.com and create or select a project.
- "APIs & Services" → "Enabled APIs & services" → enable the APIs for the services they want (Gmail API, Google Calendar API, Google Drive API, People API, Google Sheets API, Google Docs API, etc.).
- "APIs & Services" → "OAuth consent screen" → External → if the consent screen is in Testing state, add every Google account they want to authorize (including their own) as a Test user. Skipping this causes
access_deniedlater. - "APIs & Services" → "Credentials" → "Create credentials" → "OAuth client ID" → Application type: "Desktop app" → Download the JSON.
- Ask the user to upload or attach the JSON file to the chat. Do not ask them to paste the JSON contents inline — the file is large and pastes mangle line breaks.
Register the downloaded JSON:
gog auth credentials set /path/to/client_secret.json
Confirm with gog auth credentials list.
Step 2 — Authorize each Google account (remote-friendly flow)
The default gog auth add <email> starts a local HTTP listener on 127.0.0.1:<random-port> to catch Google's OAuth redirect. That listener is unreachable from a mobile device or from anywhere outside the container, so for OpenClaw / remote use always use the --remote two-step flow instead:
gog auth add [email protected] --services user --remote --step 1 --force-consent
--services user requests scopes for every service the user opted into on the consent screen. If the user only needs a subset (e.g. only Gmail + Calendar), replace user with a comma-separated list: gmail,calendar,drive,docs,sheets,contacts,tasks,slides,forms,chat,classroom,appscript,ads. Under-requesting now means re-running gog auth add later with more scopes when a new command fails with a 403/insufficient-scope error.
This prints a URL on accounts.google.com. Step 2 must be completed promptly — within a few minutes — because the state token cached by gog for Step 1 is short-lived. Ask the user to:
- Open that URL on any device (phone, laptop — any browser).
- Pick the Google account, approve the requested scopes.
- Google will redirect to a URL starting with
http://127.0.0.1:NNNN/?...&code=4/0A.... The browser will show "can't connect" or similar — this is expected and harmless. - Copy the entire failed URL from the address bar and send it back.
Then complete the exchange:
gog auth add [email protected] --remote --step 2 --auth-url "<the full 127.0.0.1 URL the user pasted>"
On success, gog auth list will show the account. The refresh token is stored (by default in a keyring backend; gog auth status prints which backend is active) and persists across container restarts.
Fallback flows
--manual— same idea as--remote, but as a single interactive prompt. Works when stdin is attached.- Browser on the same machine as gog (laptop install only): plain
gog auth add [email protected] --services gmail,calendar,driveopens the browser and catches the callback on 127.0.0.1 automatically. Do not use this inside a remote container. - Short-lived testing without persisted tokens:
GOG_ACCESS_TOKEN=<access_token> gog gmail .... Expires in ~1 hour, no refresh. - Google Workspace domains with admin access:
gog auth service-account set ...for domain-wide delegation (not applicable to personal @gmail.com).
Common auth failures
- "No tokens stored" after running
gog auth add: most often Step 1 (credentials set) was skipped — rungog auth credentials listto confirm. Other causes: Step 2 was never run, the cachedstatebetween Steps 1 and 2 expired, the user denied consent, or the keyring backend failed to write (checkgog auth status). - "redirect_uri_mismatch": the downloaded JSON is for a "Web application" client, not "Desktop app". Re-create as Desktop, or use
--redirect-urito override. - "access_denied": the user isn't added as a Test user on the OAuth consent screen (while it's in Testing state).
- Refresh token missing after authorization: add
--force-consentto force Google to re-issue one.
Scopes
--servicesacceptsuser,all, or a comma-separated list:gmail,calendar,chat,classroom,drive,docs,slides,contacts,tasks,sheets,people,forms,appscript,ads.--readonlyrequests read-only scopes where available (recommended for agents that shouldn't modify anything).--gmail-scope=readonlyand--drive-scope=readonly|filenarrow specific services.--gmail-no-sendblocksgog gmail sendregardless of scope — safer for autonomous agents.
Common commands (after auth is set up)
- Gmail search:
gog gmail search 'newer_than:7d' --max 10 --json - Gmail send:
gog gmail send --to [email protected] --subject "Hi" --body "Hello"(confirm with the user first) - Calendar events:
gog calendar events <calendarId> --from <iso> --to <iso> - Drive search:
gog drive search "query" --max 10 - Contacts:
gog contacts list --max 20 - Sheets get:
gog sheets get <sheetId> "Tab!A1:D10" --json - Sheets update:
gog sheets update <sheetId> "Tab!A1:B2" --values-json '[["A","B"],["1","2"]]' --input USER_ENTERED - Sheets append:
gog sheets append <sheetId> "Tab!A:C" --values-json '[["x","y","z"]]' --insert INSERT_ROWS - Sheets clear:
gog sheets clear <sheetId> "Tab!A2:Z" - Sheets metadata:
gog sheets metadata <sheetId> --json - Docs export:
gog docs export <docId> --format txt --out /tmp/doc.txt - Docs cat:
gog docs cat <docId>
Notes
- Set
[email protected]in the environment to avoid repeating--accounton every call. - For scripting, prefer
--json --no-input. - Sheets values:
--values-jsonis easier to generate than inline row args. - Docs supports export/cat/copy. In-place edits require a Docs API client (not in gog).
- Confirm before sending mail or creating calendar events.
openclaw doctor --fixdoes NOT help with gog auth. OAuth requires a human in a browser — no CLI tool can generate tokens on its own.