From Sales OS
Interactive step-by-step installer for the Google Workspace CLI (gws) on macOS, Linux, WSL, OR native Windows (Git Bash / MINGW64). From a clean machine: detects platform, installs the package manager + Google Cloud SDK + gws CLI, helps accept GCP Terms of Service, creates a GCP project, enables the Workspace APIs the user picks, walks them through the Google Auth Platform consent screen + Desktop OAuth client (handling the multi-account-in-Chrome edge case), launches the OAuth login flow, verifies with a real Gmail call, and runs a tailored first-use proof-of-concept. Use whenever the user wants to install or set up the Google Workspace CLI / gws - phrases like "install gws", "set up Google Workspace CLI", "install gcloud for gws", "install Google Workspace CLI from scratch", "set up gws on my machine", "I want to use Google Workspace from my terminal", or any variation of onboarding onto the gws CLI from a clean state.
How this skill is triggered — by the user, by Claude, or both
Slash command
/sales-os:google-workspace-cli-installer-guideThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
You are guiding a user through a first-time install of the Google Workspace CLI (`gws`) on a clean machine. This is a real interactive setup with real shell calls. **Don't rush. Verify every step before moving on. Be patient with the Cloud Console clicks - that's where most users fumble.**
You are guiding a user through a first-time install of the Google Workspace CLI (gws) on a clean machine. This is a real interactive setup with real shell calls. Don't rush. Verify every step before moving on. Be patient with the Cloud Console clicks - that's where most users fumble.
Realistic time: 15-20 minutes if everything goes smoothly, 30-45 minutes for a first-time GCP user (Terms of Service + manual OAuth client creation add the extra time). Tell the user this upfront.
Always assume the user wants to install the CLI. Don't pitch an MCP alternative or ask if they'd prefer one - just install.
Run all checks before doing anything. If a check fails, STOP and surface it - don't try to recover by skipping.
which echo
If this errors, the agent doesn't have shell access. Stop and ask the user to run from a real shell (Claude Code in terminal / IDE / desktop app).
uname -s
Branch:
Darwin → macOSLinux → check /proc/version for "microsoft" → if found, WSL; else LinuxMINGW* / MSYS* / CYGWIN* → Windows (Git Bash / MINGW64)Save the platform - every subsequent step branches on it.
mkdir -p ~/.config && touch ~/.config/.test && rm ~/.config/.test
If this fails, surface the error.
(Removed in this version: the old "do you actually want to do this - or use MCP?" pre-flight. Always proceed with the install.)
Branch by platform.
which brew
If missing, install Homebrew:
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
After install, follow the printed instructions to add brew to $PATH. Apple Silicon:
echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
eval "$(/opt/homebrew/bin/brew shellenv)"
Intel Macs use /usr/local/bin/brew instead.
Use the system package manager (apt, dnf, etc.). Skip Homebrew - it's uncommon on Linux.
winget --version
Should be v1.0+. If missing, the user installs App Installer from Microsoft Store. Otherwise, no setup needed.
gcloud)which gcloud
If missing, branch by platform.
brew install --cask google-cloud-sdk
curl https://sdk.cloud.google.com | bash
exec -l $SHELL
Or use the distro-native packages from the official Cloud SDK install instructions.
From PowerShell:
winget install --id Google.CloudSDK --silent --accept-source-agreements --accept-package-agreements --disable-interactivity
This is a large install (~500 MB). Be patient.
gcloud --version
Should print Google Cloud SDK <version> plus components.
Gotcha 1: PATH doesn't refresh in the current shell. After winget install, an existing Git Bash / PowerShell session still won't see gcloud. Either restart the shell, or add the path manually for the session:
export PATH="/c/Users/<you>/AppData/Local/Google/Cloud SDK/google-cloud-sdk/bin:$PATH"
Gotcha 2: "Python was not found" error. If gcloud --version errors with "Python was not found; run without arguments to install from the Microsoft Store, or disable this shortcut from Settings > Apps > Advanced app settings > App execution aliases", the Microsoft Store python.exe alias is intercepting gcloud's Python call. The Cloud SDK ships with its own bundled Python - point gcloud at it:
export CLOUDSDK_PYTHON="/c/Users/<you>/AppData/Local/Google/Cloud SDK/google-cloud-sdk/platform/bundledpython/python.exe"
For a permanent fix, the user can either disable the python.exe execution alias in Settings → Apps → Advanced app settings → App execution aliases, or set CLOUDSDK_PYTHON permanently via setx.
Tip for the agent: persist these env vars to a file (e.g. /tmp/gws-session-path.sh) and source it at the start of every Bash call, since each Bash tool call starts a fresh shell.
gws)The npm path works on every platform - use it universally.
which gws || npm install -g @googleworkspace/cli
Verify:
gws --version
Should print gws 0.X.X and This is not an officially supported Google product.
(macOS users can try brew install googleworkspace-cli if available in their tap - but npm install -g @googleworkspace/cli is the simpler universal path and also bundles native binaries.)
Don't skip this conversation. Ask the user explicitly which Google Workspace services they actually plan to use.
"Which Google Workspace services do you want to use? Pick whatever's relevant - you can add more later by re-running auth login."
Common starter set (most people pick all of these):
- Gmail - read, compose, send, draft
- Google Drive - list, read, upload, share
- Google Sheets - create, read, update, format
- Google Docs - create, read, update
- Google Calendar - list events, create events, manage attendees
Power-user additions:
- Google Tasks - to-do list management
- Google Chat - send to spaces, list messages
- Google Slides - create and update presentations
- Google Forms - create and read forms
- Apps Script - programmatic Apps Script management
- Admin SDK - workspace user/group management (Workspace admins only)
Save the user's selection - you'll reference it again when enabling APIs (Step 6b).
Important nuance to flag honestly up front: Enabling an API on the GCP project (Step 6b) is separate from requesting an OAuth scope for it (Step 7). The default gws auth login scope set in v0.22.5 includes Drive, Sheets, Gmail, Calendar, Docs, Slides, and Tasks - but not Forms, Chat, Apps Script, or Admin SDK. If the user wants those, you'll need to dig into custom scope flags at auth time (gws auth login --help). Tell them this now so they aren't surprised later.
gcloud auth logingcloud auth login
Browser opens. The user signs in with the Google account gws should act as (typically their primary Google account). Verify:
gcloud auth list
Should show their account marked * as active.
Brand-new GCP users haven't accepted the Terms of Service. This blocks project creation in Step 6a with:
ERROR: (gcloud.projects.create) Operation [...] failed: 9: Callers must accept Terms of Service
TOS cannot be accepted via the CLI. The user must do it once via the web console. Open the cloud console for them:
| Platform | Command |
|---|---|
| macOS | open https://console.cloud.google.com/ |
| Linux | xdg-open https://console.cloud.google.com/ |
| WSL | cmd.exe /c start https://console.cloud.google.com/ |
| Windows (PowerShell) | Start-Process "https://console.cloud.google.com/" |
Tell the user:
Wait for them to confirm before continuing.
This is the meaty manual step. Take your time. This is where most installs fumble on first try - give exact instructions, not vague pointers.
PROJECT_ID="gws-cli-$(date +%s | tail -c 9)"
gcloud projects create "$PROJECT_ID" --name "My gws CLI"
gcloud config set project "$PROJECT_ID"
echo "$PROJECT_ID" > /tmp/gws-project-id.txt # persist for later steps
Project ID rules: 6-30 chars, lowercase letters / digits / hyphens, must start with a letter, must end with letter or digit, globally unique. The pattern above generates a unique ID using a Unix timestamp suffix.
If creation fails with Callers must accept Terms of Service, the user hasn't completed Step 5b - go back and finish it.
The original skill recommended enabling APIs via Cloud Console UI. Don't. gcloud services enable is faster, scriptable, and lets you enable everything in a single call:
gcloud services enable \
gmail.googleapis.com \
drive.googleapis.com \
sheets.googleapis.com \
docs.googleapis.com \
calendar-json.googleapis.com \
slides.googleapis.com \
forms.googleapis.com \
--project "$PROJECT_ID"
Adjust the list based on Step 4 selections. Service identifier reference:
| Service | API identifier |
|---|---|
| Gmail | gmail.googleapis.com |
| Drive | drive.googleapis.com |
| Sheets | sheets.googleapis.com |
| Docs | docs.googleapis.com |
| Calendar | calendar-json.googleapis.com |
| Slides | slides.googleapis.com |
| Forms | forms.googleapis.com |
| Tasks | tasks.googleapis.com |
| Chat | chat.googleapis.com |
| Apps Script | script.googleapis.com |
| Admin SDK | admin.googleapis.com |
gws auth setup (it WILL bail in v0.22.5 - that's expected)gws auth setup --project "$PROJECT_ID"
In v0.22.5 this fails with:
OAuth client creation requires manual setup in the Google Cloud Console.
That's the expected fork. The error message even gives you the right URLs. Proceed to 6d.
Launch this URL in the user's browser (replace <PROJECT_ID> and <email>):
https://console.cloud.google.com/auth/overview?project=<PROJECT_ID>&authuser=<email>
Use the platform-appropriate command:
| Platform | Command |
|---|---|
| macOS | open "<url>" |
| Linux | xdg-open "<url>" |
| WSL | cmd.exe /c start "" "<url>" |
| Windows (PowerShell) | Start-Process "<url>" |
Always include &authuser=<their-email>. This avoids the multi-account-in-Chrome trap - see below.
Symptoms the URL loaded under the wrong Google account:
clientauthconfig.clients.list, oauthconfig.verification.get, resourcemanager.projects.get, serviceusage.quotas.get)Two fixes:
&authuser=<the-target-email>What the user should see when correctly logged in:
Click Get started. Google replaced the old "OAuth consent screen" page with a 4-step wizard in 2024-2025. Walk the user through each step exactly:
Step 1 of 4 - App information
My gws CLI (or whatever the user prefers - purely cosmetic)Step 2 of 4 - Audience
Step 3 of 4 - Contact information
Step 4 of 4 - Finish
The wizard exits to the Google Auth Platform left-nav view (Branding, Audience, Clients, Data access, Verification centre, Settings).
The OAuth app starts in "Testing" mode. Without a test user listed, the user will hit Error 403: access_denied at OAuth time.
gws CLIclient_secret_*.jsonTell the user to leave the JSON in their default Downloads folder - the agent will move it.
mkdir -p ~/.config/gws
NEWEST=$(ls -t ~/Downloads/client_secret_*.json 2>/dev/null | head -1)
mv "$NEWEST" ~/.config/gws/client_secret.json
ls -la ~/.config/gws/client_secret.json
On Windows that's C:\Users\<user>\.config\gws\client_secret.json.
gws auth logingws auth login
Walk the user through:
localhost:XXXXX and shows "you can close this tab" - donegws prints:
Open this URL in your browser to authenticate:
https://accounts.google.com/o/oauth2/auth?...
…then blocks waiting for the localhost callback. Don't kill the process. Launch the URL via the platform-appropriate command:
| Platform | Command |
|---|---|
| macOS | open "<url>" |
| Linux | xdg-open "<url>" |
| WSL | cmd.exe /c start "" "<url>" |
| Windows (PowerShell) | Start-Process "<url>" |
(Tip: on Windows from PowerShell, paste the URL into a $url = '...' assignment using single quotes, then Start-Process $url - that handles the URL's special characters cleanly.)
If the user takes a while in the browser and you're worried gws died, check the localhost port. The redirect URL in 7b's output looks like redirect_uri=http://localhost:<port> - grab that port and:
netstat -an | grep -i LISTENING | grep ":<port>"
If it's gone, gws auth login is dead - re-run it.
--scopes shorthandDon't run gws auth login --scopes gmail,drive,sheets. The CLI sends those literal strings to Google, which rejects them. Use the default scope set (no --scopes flag) or check gws auth login --help for the correct override syntax.
The auth output prints:
{
"account": "<email>",
"credentials_file": "...config/gws/credentials.enc",
"encryption": "AES-256-GCM (key in OS keyring or local .encryption_key)",
"message": "Authentication successful. Encrypted credentials saved.",
"scopes": [...],
"status": "success"
}
Credentials live encrypted at ~/.config/gws/credentials.enc, with the key in the OS keyring (macOS Keychain, Windows Credential Manager, libsecret on Linux).
gws gmail users getProfile --params '{"userId":"me"}'
Should return JSON with the user's email, history ID, message count, and thread count. If it does, you're done with install - move to the demo.
| Symptom | Cause | Fix |
|---|---|---|
401 Token expired or revoked | OAuth token didn't store, or expired | Re-run gws auth login |
403 accessNotConfigured | API not enabled on the GCP project | gcloud services enable <api>.googleapis.com --project <PROJECT_ID> |
403 access_denied at OAuth | User isn't on the OAuth Test users list | Step 6f - add them |
command not found: gws | npm global path not on $PATH | Restart shell. Verify with npm config get prefix and ensure that path's bin dir is on PATH |
| Browser refused to open | Headless / restricted env | Copy the URL printed by the CLI, open in any browser manually |
Don't run a generic test command. Look at what the user actually does and build a one-shot proof-of-concept around their real workflow. This is what makes the install worth their time.
gws gmail +triage --max 5 # recent unread inbox
gws calendar +agenda --week # upcoming calendar
gws drive files list --params '{"pageSize": 10, "orderBy": "modifiedTime desc", "fields": "files(id,name,mimeType,modifiedTime)"}'
Look at what came back. Patterns to notice:
"Based on what I'm seeing in your workspace, here are a few proof-of-concept workflows that would be high-leverage for you:
- [tailored option A - based on what you saw]
- [tailored option B]
- [tailored option C]
Or, if none fit, what's a recurring Google Workspace task you'd most want to automate?"
Whatever they pick, actually build it end-to-end and let them see the artifact in their account. Don't print example commands and stop - execute them and produce a real artifact (URL, inbox notification, calendar event).
Common PoC patterns:
A. Weekly digest emailed to self. gmail +triage + calendar +agenda → format → send via gws gmail +send or raw API.
B. New Sheet populated from a spec the user describes. gws sheets spreadsheets create → spreadsheets values update (with valueInputOption: USER_ENTERED so formulas evaluate) → spreadsheets batchUpdate for header formatting, conditional formatting, frozen rows, currency / percent formats. End with the URL.
C. Calendar event batch. Loop a list, run gws calendar +insert per event. Show events appearing in their calendar.
D. Doc template populated. gws docs documents create → documents batchUpdate to populate with TITLE / HEADING / NORMAL_TEXT styles. Send the link.
E. Bulk personalized email send. CSV → loop → gws gmail +send (or raw API for HTML).
F. Spreadsheet template (e.g. monthly budget, expense tracker, habit tracker). Same flow as B: create blank → values.update with categories + SUM/IFERROR/percentage formulas → batchUpdate for currency formatting + conditional color rules + frozen rows + section headers + column widths. End with URL.
After the PoC runs, show the user the artifact (URL, inbox notification, calendar event). Open the URL in their browser via open / xdg-open / Start-Process - don't just print it.
Tell the user clearly:
The OAuth user-grant expires every few weeks. When commands fail with 401 Token expired or revoked, run gws auth login again. 30 seconds. No need to redo any GCP setup.
gcloud services enable <api>.googleapis.com --project <PROJECT_ID>gws auth login to re-grant scopes that include the new APIFor Forms / Chat / Apps Script / Admin SDK - these aren't in the default gws auth login scope set. Check gws auth login --help for scope override flags.
The killer use case for the CLI is unattended automation. Branch by platform:
macOS / Linux / WSL - cron:
# crontab -e, then:
0 8 * * 1 /full/path/to/script.sh > /tmp/gws-monday.log 2>&1
Windows - Task Scheduler:
gws ... commands in a .bat or .ps1 fileThe CLI uses tokens stored in the OS keyring, so scheduled jobs run with the user's credentials with zero extra setup.
gws --help, gws gmail --help, gws sheets --help, etc. for command referencegws schema <service.resource.method> (e.g. gws schema sheets.spreadsheets.batchUpdate) to inspect any Google API method's schemagws auth --help to list auth subcommandsNote: older skill versions reference gws auth check and gws doctor - those don't exist in v0.22.5. Use gws auth --help to see what's actually available.
<PROJECT_ID> (also stored in gcloud config get project)~/.config/gws/client_secret.json~/.config/gws/credentials.enc (key in OS keyring)gws: npm config get prefix/bin| Symptom | Fix |
|---|---|
command not found: gws after install | Restart shell. Check npm config get prefix and ensure that path's bin dir is on PATH. |
| OAuth: "Access blocked: app not verified" | Click Advanced → "Go to [project] (unsafe)". User's own OAuth client - safe. |
Some requested scopes were invalid on auth login | Don't pass --scopes shorthand. Run plain gws auth login. |
403 accessNotConfigured | Specific API not enabled on the project. gcloud services enable <api>.googleapis.com. |
401 Token expired or revoked | gws auth login. 30 seconds. |
403 access_denied at OAuth | User isn't on the OAuth test users list. Step 6f. |
| Browser doesn't open | Copy the printed URL, launch via open / xdg-open / Start-Process. Or check the redirect_uri=http://localhost:<port> listener is still alive. |
| Wrong Google account got authed | gws auth logout, then gws auth login and pick the correct account. |
| Multiple Google accounts | Use --profile for separate accounts: gws auth login --profile work, then gws -p work gmail +triage. |
| Cloud Console shows "You need additional access" page | Multi-account-in-Chrome bug. Append &authuser=<email> to the URL, or switch accounts via the avatar menu. |
Callers must accept Terms of Service | First-time GCP user. Visit console.cloud.google.com once, accept TOS, retry. |
gws auth setup fails on OAuth client creation | Expected in v0.22.5. Walk through 6d-6h manually. |
gws auth setup fails with "No GCP project configured" | Create project first via gcloud projects create, then gcloud config set project. |
(Windows) gcloud command not found after winget install | Restart shell, or export PATH="<install>/google-cloud-sdk/bin:$PATH" for the session. |
(Windows) gcloud errors "Python was not found" | Microsoft Store python.exe alias intercepts. Set CLOUDSDK_PYTHON to the bundled Python at <install>/google-cloud-sdk/platform/bundledpython/python.exe. |
(Windows) start doesn't work in Git Bash | Use cmd //c start "<url>" from Git Bash or Start-Process "<url>" from PowerShell. |
open / xdg-open / Start-Process / cmd.exe /c start). Don't print URLs and expect copy-paste - that's friction.delete, no drop, no overwrite without explicit consent.gws process is still alive on a localhost port - netstat -an | grep LISTENING | grep :<port> confirms./tmp/gws-session-path.sh) and source it at the top of every shell call. Bash tool calls don't share state across invocations, so PATH and CLOUDSDK_PYTHON exports don't persist without this.&authuser=<email> in every Cloud Console URL you launch for the user. Multi-account-in-Chrome failures look mysterious and waste 10 minutes if you don't.npx claudepluginhub hubert-sys/benai-skills --plugin sales-osGuides collaborative design exploration before implementation: explores context, asks clarifying questions, proposes approaches, and writes a design doc for user approval.
Creates structured, bite-sized implementation plans from specs or requirements before writing code. Useful for breaking down multi-step tasks into testable steps with file structure and task boundaries.
Synthesizes the current conversation into a structured spec (PRD) and publishes it to the project issue tracker with a ready-for-agent label, without interviewing the user.
2plugins reuse this skill
First indexed Jul 18, 2026