Skip to content

Google Cloud Setup

P3DROVFX edited this page Oct 12, 2026 · 1 revision

Google Cloud Setup

Four features of the shell talk to Google on your behalf — Gmail, Google Tasks, Google Calendar (sync, event colours and re-authorization) and the Google Drive backup — and a fifth, the Screen Translator, can use Google Cloud's Translate and Vision. None of them ships shared credentials. You create one Google Cloud project and one OAuth client in your own account, and every Google feature reuses it. It takes about ten minutes, once, and it is free for personal use.

Why bring your own? A key shared by every user of a dotfiles repo would be rate-limited together, could be revoked for everyone at once, and would put your mail behind a project you do not control. With your own project, Google sees an app you wrote, and your tokens can only ever be used with credentials only you hold.

What each feature uses

Feature API to enable Scope(s) requested How it authorizes
[[Gmail Gmail-Integration]] Gmail API gmail.modify, gmail.send, userinfo.email, userinfo.profile
[[Google Tasks To-Do-and-Tasks]] Google Tasks API tasks (+ email profile)
Calendar event colours ([[Timetable Calendar-and-Timetable]]) Google Calendar API calendar, calendar.events
Calendar sync ([[Khal Khal-Integration]]) Google Calendar API calendar
[[Drive backup Rclone-and-Google-Drive]] Google Drive API drive
Screen Translator ([[Screen Translator Screen-Translator]]) Cloud Translation, Cloud Vision service account (not OAuth)

Scopes are requested per feature, at the moment you connect it. A refresh token carries exactly the scopes it was authorized with, so connecting Tasks never gives Gmail access, and disconnecting one feature leaves the others alone. (One consequence worth remembering: the Calendar API colour feature needs its own Connect Google Calendar — the Tasks token cannot be reused for it, and trying gives 403 insufficient authentication scopes.)


1. Create the project

  1. Open the Google Cloud Console and create a project (or pick one — "ii-shell" is fine).
  2. APIs & Services → Library: enable the APIs for the features you want — Gmail API, Google Tasks API, Google Calendar API, Google Drive API. Enabling an API you do not use costs nothing.

2. Configure the OAuth consent screen

  1. APIs & Services → OAuth consent screen (or Google Auth Platform). User type External.
  2. Fill the app name (anything), your email as support and developer contact.
  3. Scopes: add the ones from the table for the features you will use. The Gmail scopes are …/auth/gmail.modify, …/auth/gmail.send, …/auth/userinfo.email, …/auth/userinfo.profile; for Tasks …/auth/tasks; for Calendar …/auth/calendar; for Drive …/auth/drive.
  4. Test users: add the Google account(s) you will connect.
  5. Publish the app (Publish App → In production). Do this even though it is only for you. While the app is in Testing, Google expires every refresh token after seven days, which shows up as Gmail asking you to sign in again each week and as the Timetable's Google Calendar token expired or was revoked banner. A published app does not need Google's verification for personal use; you only accept an "unverified app" warning at the first sign-in (Advanced → Go to … (unsafe), the unsafe being your own app).

3. Create the OAuth client

APIs & Services → Credentials → Create credentials → OAuth client ID → Application type: Desktop app. Copy the Client ID and Client secret.

It must be Desktop app. A Web client fails with redirect_uri_mismatch, because the shell receives the authorization on http://localhost:<port>/callback, which only a Desktop client permits.

4. Give the credentials to the shell

Put the pair in ~/.config/quickshell/ii/.env:

# Google OAuth2 credentials (shared by Gmail, Google Tasks, Calendar and Drive backup)
GOOGLE_CLIENT_ID=1234567890-abc….apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-…

(The legacy names GMAIL_CLIENT_ID and GMAIL_CLIENT_SECRET are still read as a fallback.) You do not have to edit the file by hand: the Email tab's setup screen and Settings → Accounts & Backup have Client ID / Client Secret fields and a Save & Apply button that write the keyring and this file for you. The .env.example beside it documents the variables. TickTick's variables live in the same file.

The Python helpers read .env from the shell directory; the QML side reads the keyring first. Both are kept in step by Save & Apply.

5. Connect each feature

  • Gmail — Cheat Sheet → Email → Connect Account (Gmail Integration).
  • Google Tasks — Settings → Accounts & Backup → Google Tasks → Connect Google Tasks (To-Do and Tasks).
  • Calendar — copy the same client ID and secret into vdirsyncer's google_calendar storage, then vdirsyncer discover (Khal Integration); optionally Connect Google Calendar in the Timetable settings for per-event colours.
  • Drive — Settings → Accounts & Backup → Google Drive → authorize (Rclone and Google Drive).

The Welcome app has a tutorial for each (Set up Gmail, Set up Google Calendar, Set up Google Drive backup), with the console links and live "done" states.


Where things are stored

What Where
Client ID / secret The system keyring (apiKeys.*) and ii/.env
Gmail accounts and refresh tokens Keyring: gmail_accounts
Google Tasks account Keyring: google_tasks_accounts
Calendar API account Keyring: google_calendar_account
vdirsyncer's calendar token token_file from your vdirsyncer config (0600)
Drive token rclone's own config, remote ii-gdrive
Service-account key (Translate / Vision) Keyring: googleCloud.serviceAccountKey

The keyring is the Secret Service API — GNOME Keyring or KWallet — under the application illogical-impulse. Secrets are never written into config.json and never included in exported presets; see Preset Store. If the keyring is locked at login, the shell asks it to unlock.

The service account (Screen Translator)

The Screen Translator's Google engine is not OAuth: it uses a service account key with Cloud Translation and Cloud Vision enabled. Create the service account in IAM, download its JSON key and paste it into the Screen Translator panel; the shell stores it in the keyring and turns it into short-lived access tokens (services/gCloud/token_from_key.py, run in a private virtualenv). It is independent of the OAuth client above.

Troubleshooting

Message Meaning
redirect_uri_mismatch The client is not of type Desktop app
Access blocked: app has not completed verification Add your account under Test users, or publish the app
invalid_grant, Token has been expired or revoked The refresh token died — the app was in Testing (7 days), you revoked access in your Google account, or you changed the client. Reconnect the feature
Scope has changed (vdirsyncer) The token was granted with different scopes than vdirsyncer asks for; reconnect with Reconnect Google
Google Tasks API is not enabled for this project / Gmail API has not been used… Enable that API in the same project and retry
403 Request had insufficient authentication scopes That feature's token was authorized for other scopes; use that feature's own Connect button
Google OAuth credentials are not configured GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET are empty — Save & Apply
Requests hang on a network with broken IPv6 The Google helpers resolve IPv4 first to avoid this; if you see it elsewhere, check your DNS / routes

Related pages

← Back to Home

Clone this wiki locally