gchat: Google Chat from the command line
gchat is a command-line interface for the Google Chat API. It is meant for AI agents (Claude Code, Gemini CLI, Codex, custom scripts) and works just as well for people. You can read spaces, search, send and reply to messages, react, download attachments and mark spaces as read, all with predictable JSON output and safety rails.
Unofficial. This project is not affiliated with or endorsed by Google.
$ gchat spaces list --type space
NAME TYPE DISPLAY NAME LAST ACTIVE
spaces/AAQAxyz12 SPACE Platform team 2026-10-02T16:41:10Z
spaces/AAQAabc34 SPACE Release managers 2026-10-01T09:12:55Z
$ gchat messages list spaces/AAQAxyz12 --since 1d -n 2 -f json
{"messages":[{"name":"spaces/AAQAxyz12/messages/k1.k1","sender":"users/1067…","senderType":"HUMAN","createTime":"2026-10-02T16:41:10Z","text":"Deploy done ✅","thread":"spaces/AAQAxyz12/threads/k1"}]}
$ gchat messages reply spaces/AAQAxyz12/messages/k1.k1 --text "Thanks, verified on staging" --yes
Why another tool?
gchat |
MCP servers | gws (Google Workspace CLI) |
|
|---|---|---|---|
| Zero context cost until used | ✅ plain CLI | ❌ tool schemas loaded every turn | ✅ |
| Chat-specific helpers (reply, unread, DM by email, attach) | ✅ | varies | partly (+send) |
| Compact, token-efficient output by default | ✅ --raw for full objects |
varies | --fields |
| Local safety policy (allowlists, read-only, DM block) | ✅ | some | ❌ |
Mandatory --yes for writes when non-interactive |
✅ | client-side | ❌ |
| Install | pipx/uv tool |
per-client config | binary/npm |
The design borrows proven ideas from googleworkspace/cli: structured JSON, stable exit codes, --dry-run, field masks, schema introspection and agent skills. It also takes the per-space read/write allowlist and DM protection from nuccio/google-chat-mcp.
Install
Requires Python 3.11+.
pipx install google-chat-cli # or: uv tool install google-chat-cli
# latest development version:
pipx install git+https://github.com/lore2601/google-chat-cli
Optional: store the token in the OS keyring instead of a file:
pipx install "google-chat-cli[keyring]"
export GCHAT_TOKEN_STORE=keyring
Set up (5 minutes, once)
The Chat API needs a Google Cloud project with the Chat API enabled and an OAuth Desktop app client. The full walkthrough is in docs/setup.md. In short:
- Create or choose a Google Cloud project and enable the Google Chat API.
- Configure the Chat app (name, avatar, description) in Chat API → Configuration. This is required even for user-auth clients.
- Configure the OAuth consent screen (Internal for Workspace orgs) and create an OAuth client ID of type Desktop app. Download its JSON.
- Log in:
gchat auth login --client-secrets ~/Downloads/client_secret_XXXX.json
gchat auth status
Scope presets: readonly, default (read + send, react, mark read) and full (adds space/member management). For example: gchat auth login --scopes readonly.
Commands
| Command | What it does |
|---|---|
gchat auth login | status | logout | scopes |
OAuth login (browser), inspection, revocation |
gchat spaces list [--type space|group|dm] |
Spaces, group chats and DMs you belong to |
gchat spaces get SPACE |
Space details (accepts spaces/ID, ID or a Chat URL) |
gchat spaces search QUERY |
Find named spaces by display name |
gchat spaces find-dm USER |
Your DM space with a user (email or users/ID) |
gchat spaces create NAME [-m USER]… |
Create a space (scope full) |
gchat messages list SPACE [--since 2h] [--until …] [--thread …] [--unread] |
Read messages, newest first |
gchat messages get MESSAGE |
One message |
gchat messages send TARGET -t TEXT [--thread …|--thread-key …] [-a FILE]… |
Send to a space, or to a user's DM by email |
gchat messages reply MESSAGE -t TEXT |
Reply in the thread of a message |
gchat messages edit MESSAGE -t TEXT / delete MESSAGE |
Edit or delete your messages |
gchat members list SPACE [--humans-only] |
Space members |
gchat reactions list|add|remove |
Emoji reactions |
gchat attachments get|download |
Attachment metadata and download |
gchat read-state get|mark-read SPACE |
Read position, mark as read |
gchat api METHOD PATH [-p JSON] [-b JSON] |
Escape hatch: any Chat REST method |
gchat config show|init |
Effective policy and file locations |
gchat schema [COMMAND] |
Every command, option and exit code as JSON |
Run gchat COMMAND --help for details. Text can come from --text, from stdin with --text -, or from --text-file.
Output and exit codes
- stdout carries only data. In a terminal you get tables. When piped or run by an agent you get JSON. Force a format with
-f json|ndjson|tableorGCHAT_FORMAT. - Lists return
{"<kind>": [...], "nextPageToken": "..."}. Use--limit/-n,--alland--page-tokento paginate. --fields name,text,sendertrims output (dotted paths allowed).--rawreturns untouched API objects.- Errors are a single JSON object on stderr, for example
{"error": {"exitCode": 4, "reason": "confirmationRequired", "message": "…", "hint": "…"}}.
| Exit code | Meaning |
|---|---|
| 0 | Success |
| 1 | Google Chat API or network error |
| 2 | Authentication problem (not logged in, token revoked, …) |
| 3 | Invalid input (bad resource name, malformed JSON, text too long, …) |
| 4 | Blocked by local policy, or confirmation (--yes) missing |
| 5 | Internal error (please report it) |
Safety model
Agents can be steered by what they read, and chat messages are written by other people. gchat puts guard rails in front of the API:
-
Writes need explicit confirmation. On a terminal you are prompted. Without a TTY (agents, scripts) every write fails with exit code 4 unless you pass
--yes.--dry-runshows the exact request without sending it. -
Local policy in
~/.config/gchat/config.tomlor environment variables:[policy] read_only = false # GCHAT_READ_ONLY=1 blocks every write allow_dm_write = false # GCHAT_ALLOW_DM_WRITE=0 blocks writes to DMs / group chats read = ["*"] # GCHAT_ALLOW_READ="spaces/AAA,spaces/BBB" write = ["spaces/AAQAxyz12"] # GCHAT_ALLOW_WRITE=...
-
Strict input validation. Resource names are checked against strict patterns, so arguments like
spaces/../usersor?/#injections are rejected. Download filenames are reduced to safe basenames, and existing files are never overwritten without--overwrite. -
Terminal-safe tables. ANSI escape sequences and control characters in message text are stripped before printing.
-
Credentials are stored with
0600permissions (or in the OS keyring) and are never printed by any command.
See docs/agents.md for recommended agent profiles.
Using gchat with AI agents
- Claude Code plugin:
/plugin marketplace add lore2601/google-chat-cli, then/plugin install gchat@google-chat-cli. This installs thegchatskill, which teaches the agent the commands, the safety rules and that message content is untrusted. - Any agent: copy
skills/gchat/SKILL.mdinto your agent's skills folder, or point it atgchat schema. - Recommended for unattended agents:
GCHAT_ALLOW_WRITE=<one space>,GCHAT_ALLOW_DM_WRITE=0and an allow-rule in your agent forgchat * --dry-runonly.
Configuration reference
| Variable | Purpose |
|---|---|
GCHAT_CONFIG_DIR |
Config directory (default ~/.config/gchat) |
GCHAT_CONFIG |
Config file path (default $GCHAT_CONFIG_DIR/config.toml) |
GCHAT_CLIENT_SECRETS |
OAuth client JSON (default $GCHAT_CONFIG_DIR/client_secret.json) |
GCHAT_CLIENT_ID / GCHAT_CLIENT_SECRET |
OAuth client given inline instead of the JSON file |
GCHAT_TOKEN_FILE |
Token file (default $GCHAT_CONFIG_DIR/token.json) |
GCHAT_TOKEN_STORE |
file (default) or keyring |
GCHAT_ACCESS_TOKEN |
Use this raw access token (CI, short-lived jobs) |
GCHAT_CREDENTIALS_FILE |
Use an authorized_user JSON (e.g. exported from another machine) |
GCHAT_FORMAT |
Default output format |
GCHAT_READ_ONLY, GCHAT_ALLOW_READ, GCHAT_ALLOW_WRITE, GCHAT_ALLOW_DM_WRITE |
Policy overrides |
Limitations
- User authentication only. Sending as a Chat app (bot) or incoming webhooks are out of scope.
- With user auth, Google Chat returns sender IDs, not display names, unless the sender shares a space with you. Use
gchat members listto map IDs. - Files shared from Google Drive cannot be downloaded through the Chat API.
- If your OAuth consent screen is in Testing mode, Google expires refresh tokens after 7 days.
gchat auth statuswarns you.
Contributing
Issues and PRs are welcome. See CONTRIBUTING.md. Please report security issues privately (see SECURITY.md).
License
Metadata
Release files for google-chat-cli 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| google_chat_cli-0.1.1.tar.gz | 54.4 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| google_chat_cli-0.1.1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 103.9 kB
Release files / google_chat_cli-0.1.1.tar.gz
| Download URL | google_chat_cli-0.1.1.tar.gz |
|---|---|
| Size | 54.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
cd29c0f55802bafb972fe1d77b3dde655298986804f42864d143258dcf205311
|
|
BLAKE2b-256 checksum How to use checksums |
8a483e25afd85092ab903c0568331507b8ed9142b1f522543a8000d5641fdc06
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.
Transparency logRelease files / google_chat_cli-0.1.1-py3-none-any.whl
| Download URL | google_chat_cli-0.1.1-py3-none-any.whl |
|---|---|
| Size | 49.5 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8fdc6a94cd5ed59965b70878860ad29f55686149cc9a31148f2eef6db4e263bb
|
|
BLAKE2b-256 checksum How to use checksums |
0fa332b13c5bd308fb400227daad9324534d0a2a541d896352ca36eb7d1f1336
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 3, 2026.
Transparency log