Google Chat Setup Guide

August 13, 2026 · View on GitHub

This guide walks you through connecting cc-connect to Google Chat, so you can chat with your local Claude Code from a Google Chat space or DM.

cc-connect uses a registered Google Chat app whose Cloud Pub/Sub connection publishes events to a topic. cc-connect pulls that topic locally (native Go, no extra binaries) and replies through the Chat REST API as the app's service account. This means:

  • No public IP / domain / reverse proxy — events arrive over a Pub/Sub pull.
  • No subscription expiry or per-restart resource leak — the Pub/Sub subscription is fixed (unlike the Workspace Events API, whose subscriptions expire and are recreated each run).

Prerequisites

  • A Google Workspace account. The Google Chat API is only available to Workspace users; consumer @gmail.com accounts cannot configure a Chat app. (This applies to every Chat-app/REST integration, not just cc-connect.)
  • A Google Cloud project (billing enabled).
  • gcloud CLI installed and authenticated (for the one-time GCP setup below).
  • Claude Code installed and configured.

ℹ️ One Chat app per project. Google Cloud allows exactly one Chat app configuration per project. To run multiple Chat apps, use separate projects.


Architecture

┌──────────────────────────────────────────────────────────────┐
│                        Google Chat                            │
│                                                               │
│  Your message ─→ Chat app (Cloud Pub/Sub connection)          │
│                       │                                       │
│                       ▼                                       │
│            Cloud Pub/Sub topic ──→ subscription               │
└───────────────────────────────────────┼──────────────────────┘
                                         │ streaming pull (no public IP)

┌──────────────────────────────────────────────────────────────┐
│                     Your Local Machine                        │
│                                                               │
│  cc-connect ◄──► Claude Code CLI ◄──► Your Project Code       │
│       │                                                       │
│       └─ reply: Chat REST API as service account (chat.bot)   │
└──────────────────────────────────────────────────────────────┘

Both directions are native Go and authenticate with the same service-account key (chat.bot scope):

  • Receive: cc-connect opens a streaming pull on the subscription via the Cloud Pub/Sub client. The service account needs roles/pubsub.subscriber on the subscription.
  • Send: cc-connect posts to the Chat REST API as the service account, so replies appear as the bot.

Step 1: Enable APIs

In your Google Cloud project, enable:

  • Google Chat API (chat.googleapis.com)
  • Cloud Pub/Sub API (pubsub.googleapis.com)
gcloud services enable chat.googleapis.com pubsub.googleapis.com --project YOUR_PROJECT_ID

Step 2: Create the Pub/Sub topic and subscription

Create a topic, allow Google Chat to publish to it, and create a pull subscription that cc-connect will read.

PROJECT_ID=YOUR_PROJECT_ID

# Topic the Chat app publishes events to
gcloud pubsub topics create cc-connect-chat --project "$PROJECT_ID"

# Allow Google Chat's system service account to publish
gcloud pubsub topics add-iam-policy-binding cc-connect-chat --project "$PROJECT_ID" \
  --member='serviceAccount:chat-api-push@system.gserviceaccount.com' \
  --role='roles/pubsub.publisher'

# Pull subscription cc-connect reads
gcloud pubsub subscriptions create cc-connect-chat-sub --topic cc-connect-chat --project "$PROJECT_ID"

The subscription resource name is projects/YOUR_PROJECT_ID/subscriptions/cc-connect-chat-sub — you'll put this in config.toml.


Step 3: Create a service account

cc-connect uses one service account for both pulling events and replying.

gcloud iam service-accounts create cc-connect-bot --project "$PROJECT_ID" \
  --display-name "cc-connect Chat bot"

# Allow the service account to pull from the subscription
gcloud pubsub subscriptions add-iam-policy-binding cc-connect-chat-sub --project "$PROJECT_ID" \
  --member="serviceAccount:cc-connect-bot@${PROJECT_ID}.iam.gserviceaccount.com" \
  --role="roles/pubsub.subscriber"

# Download a JSON key (this is a secret — store it safely, e.g. ~/.config/cc-connect/)
mkdir -p ~/.config/cc-connect
gcloud iam service-accounts keys create ~/.config/cc-connect/cc-connect-bot-key.json \
  --iam-account="cc-connect-bot@${PROJECT_ID}.iam.gserviceaccount.com" \
  --project "$PROJECT_ID"
chmod 600 ~/.config/cc-connect/cc-connect-bot-key.json

⚠️ The key file grants the bot's identity — keep it private and never commit it.

  • Send: no project-level role is needed — a service account calling the Chat API with the chat.bot scope acts as the configured Chat app.
  • Receive: the roles/pubsub.subscriber binding above (on the subscription) is what lets the service account pull events.

Step 4: Configure the Chat app

Go to Chat API → Configuration (select your project) and set:

SectionSetting
App statusLive — available to users (the app must be LIVE or it cannot send replies)
Build as a Workspace add-onUnchecked (Cloud Pub/Sub connection requires the classic app model; do not convert to add-on — it's one-way)
Application infoApp name (e.g. Claude), Avatar URL (HTTPS square image), Description
Interactive featuresEnable
Functionality☑ Receive 1:1 messages (for DM use) and/or ☑ Join spaces and group conversations (for @mention in spaces)
Connection settingsCloud Pub/Sub → topic projects/YOUR_PROJECT_ID/topics/cc-connect-chat
VisibilityMake available to specific people → enter your own email only (keeps the app private to you; up to 5 people or a group)

Click Save.


Step 5: Configure cc-connect

Add a googlechat platform to your config.toml:

[[projects]]
name = "my-project"

[projects.agent]
type = "claudecode"

[projects.agent.options]
work_dir = "/path/to/your/project"   # must be a real directory
mode = "default"

[[projects.platforms]]
type = "googlechat"

[projects.platforms.options]
# Pub/Sub subscription the Chat app publishes to (required)
subscription = "projects/YOUR_PROJECT_ID/subscriptions/cc-connect-chat-sub"
# Service-account key, used to pull events AND reply as the bot (chat.bot) (required)
credentials_file = "/Users/you/.config/cc-connect/cc-connect-bot-key.json"
# Allowed sender IDs (e.g. "users/1234567890"); "*" = everyone (default).
allow_from = "*"
# "space" (default) | "thread" | "user"
session_scope = "space"

Options reference

OptionRequiredPurpose
subscriptionPub/Sub subscription the Chat app publishes to
credentials_fileService-account JSON key, used to pull events and reply (chat.bot)
allow_fromComma-separated allowed sender IDs; * = all
session_scopespace (default) / thread / user

Step 6: Start cc-connect

cc-connect
# or: cc-connect --config /path/to/config.toml

You should see:

level=INFO msg="googlechat: started" subscription=projects/.../cc-connect-chat-sub scope=space

Step 7: Start chatting

  • DM: in Google Chat, search for your app name, open a DM, and send a message. Every message in the DM reaches the bot.
  • Space: add the app to a space and @mention it (in spaces, a Chat app only receives messages that @mention it).

The bot replies in-thread as the app.

💡 Find your own sender ID for allow_from by running with [log] level = "debug" and sending a message — the log shows sender=users/<id>. Then restrict allow_from to that ID.


Key facts

  • The Chat app must be Live. If App status is not Live, the app neither receives events nor sends replies. Set it to Live — available to users in the Chat API Configuration tab.
  • One service account does both. The key in credentials_file pulls events (needs roles/pubsub.subscriber on the subscription) and posts replies (chat.bot).
  • Fixed subscription = no expiry, no leak. Unlike the Workspace Events API, the Chat app's Pub/Sub connection uses one stable topic/subscription, so there is no subscription to renew and nothing is recreated on restart.
  • One Chat app per Google Cloud project.

FAQ

Q: I sent a message but the bot doesn't respond at all.

  1. Is the Chat app App status = Live? (required for both receiving and sending)
  2. Is cc-connect running? Check the log for googlechat: started.
  3. Does the service account have roles/pubsub.subscriber on the subscription? (receive path)
  4. Is work_dir a real directory? The agent can't start otherwise.
  5. Give the agent a few seconds on the first message (cold start).

Q: It receives but never replies.

  1. Is credentials_file readable and a service-account key in the same project?
  2. Check logs for googlechat: send: status ....

Q: "Google Chat app is inactive" error when sending.

Set App status to Live — available to users in the Chat API Configuration tab.

Q: "Google Chat API is only available to Google Workspace users."

You're signed in with a consumer account. Use a Google Workspace account.

Q: Connection settings has no "Cloud Pub/Sub" option.

The "Build this Chat app as a Google Workspace add-on" checkbox is on. Cloud Pub/Sub is available in the classic model — clear that checkbox (or keep the add-on model, which also supports Pub/Sub but is configured differently).


References


See Also