Skip to main content
ClaudeWave
Skill341 repo starsupdated today

google-workspace-setup

The google-workspace-setup skill performs one-time configuration for Google Workspace integrations by installing required tools, authenticating to Google Cloud, enabling necessary APIs, and capturing OAuth credentials through an inline form. Use this skill once before attempting any Google Workspace operations like reading email, accessing calendar, or managing Drive files. The skill is idempotent and distinguishes between initial provisioning and subsequent session re-authentication.

Install in Claude Code
Copy
git clone --depth 1 https://github.com/Lilac-Labs/gini-agent /tmp/google-workspace-setup && cp -r /tmp/google-workspace-setup/skills/google/google-workspace-setup ~/.claude/skills/google-workspace-setup
Then start a new Claude Code session; the skill loads automatically.

SKILL.md

# Google Workspace Setup

One-time onboarding for the Google Workspace skills (`google-gmail`, `google-calendar`, `google-drive`, `google-docs`, `google-sheets`, `google-meet`, `google-forms`). Installs `gws` and `gcloud`, signs the user into their own Google Cloud project, enables the Workspace APIs, captures an OAuth Desktop client through the inline Connect form, and completes `gws auth login`.

The OAuth client lives in the user's own GCP project. The Client ID and Client Secret are captured through the inline Connect form (`request_connector` tool) and stored in Gini's encrypted secret store — never write them to chat or logs, and never write `client_secret.json` to disk.

This skill is idempotent — re-running it re-verifies the install and lets the user widen scopes.

**Provisioning vs signing in.** The work splits in two: **provisioning** (install, `gcloud auth login`, project, APIs, `request_connector`) runs **once**, ever; **signing in** (`gws auth login`) runs again whenever the user's `gws` session expires. `gcloud` is *only* ever needed for provisioning — never for a re-auth. Step 0 decides which case you're in.

## The Flow

This is the **exact first-time sequence** (Step 0 short-circuits the re-auth case before you reach it). Within the first-time flow do not branch into shortcuts, do not pre-ask whether they have an existing OAuth client, do not list completed actions retrospectively. Status messages are action-oriented: what the user must do *next*.

1. The user asks Gini to do a Workspace thing (read mail, check calendar, share a Drive file, etc.).
2. Confirm setup with the user.
3. Install `gws` and `gcloud` silently in the background.
4. Run `gcloud auth login`, which pops up the user's default browser for sign-in.
5. After they sign in, create the Cloud project and enable the seven Workspace APIs in the background.
6. Send a single chat bubble with the last-step instructions (two Cloud Console URLs) and call `request_connector` — the inline form renders below the bubble.
7. After the user pastes the credentials and clicks **Save**, ask for a tag for this account and call `skill_run google-account-login`, which pops up the user's default browser for OAuth consent and registers the tagged account.
8. After they sign in, the original ask resumes.

## Step 0 — First-time or re-auth?

Before anything else, call `list_connectors` and look for a connector named `google-workspace-oauth`.

- **It exists** → the OAuth client is already provisioned and only the user's `gws` session expired. This is a **re-auth**, not setup. Ask once ("Your Google sign-in expired — want me to sign you back in?") and on yes go **straight to Step 6**, which now signs in by calling `skill_run google-account-login` for the relevant account. Re-auth **re-uses the expired account's existing config dir** so it keeps its id and tag — pass that account's `configDir` (and its `tag`), NOT a fresh login (which would mint a duplicate) and NOT `adopt: true` (which skips login and only works on an already-valid session):
  - A **tagged account** (from the "Connected Google accounts" block) whose session expired → `skill_run google-account-login` with `{ tag: "<that account's tag>", configDir: "<that account's configDir from the block>" }`.
  - The **default-dir session** (`~/.config/gws`) that has EXPIRED → `{ tag: "<its tag>", configDir: "~/.config/gws" }` (non-adopt, so it actually re-logs in).

  Then run Step 8 (smoke test). Do **not** run `gcloud`, create a project, or call `request_connector` — provisioning already happened and none of it is needed again. (Edge case: if `gws` is not on `$PATH`, run Step 2's install first, then Step 6. If login fails with `invalid_client`, the stored client is broken — fall through to the full first-time flow to re-provision it.)
- **It does not exist** → true first-time setup. Continue to Step 1.

## Step 1 — Confirm setup

Tell the user, in one short sentence, that Google Workspace isn't set up yet, and ask whether to set it up now. Wait for confirmation before doing anything.

If they say yes, proceed silently — do not narrate each substep. The user sees a chat bubble per **milestone** (sign in, last step), not per command.

## Step 2 — Install `gws` and `gcloud`

Both installs are silent and run through `terminal_exec`. If a binary is already on `$PATH`, skip its install.

Detect first:

```bash
command -v gws
command -v gcloud
```

Install whichever is missing:

```bash
# gws (macOS / Linux)
brew install googleworkspace-cli

# gcloud (macOS)
brew install --cask google-cloud-sdk

# gcloud (Linux) — see https://docs.cloud.google.com/sdk/docs/install for the
# tarball install. Use the platform-appropriate command via terminal_exec.
```

Verify both are on `$PATH` afterwards:

```bash
gws --version
gcloud --version
```

If either install fails (network, sudo, broken Homebrew), STOP and tell the user verbatim what failed and the one-line command to try manually. Do not loop.

## Step 3 — Sign in with `gcloud`

```bash
gcloud auth login
```

This opens the user's **default browser** to Google's OAuth consent page. They sign in there. The command returns when the user completes consent.

If `gcloud auth list` already shows an active account, ask once: "gcloud is signed in as `<email>`. Use this account?" — proceed on confirmation. Otherwise run `gcloud auth login` straight through.

## Step 4 — Reach a Cloud project with the seven APIs enabled

The goal of this step is a single value, `<PROJECT_ID>`, that names a Cloud project the active gcloud account owns AND in which the seven Workspace APIs are enabled. Every later step substitutes that string into URLs and `gcloud --project=` flags.

**Invariants for this step and every later `gcloud` call:**

- Pass `--project=<PROJECT_ID>` explicitly on every `gcloud` command that accepts it. Don't rely on `gcloud config get-value project`; its value can carry over from an unrelated shell or a prior failed run, which is exactly how t