
Google Chat Messages
Post structured Google Chat webhook messages (cardsV2 and formatted text) from your agent or backend without guessing Chat-specific markup.
Overview
google-chat-messages is an agent skill for the Build phase that builds typed Google Chat webhook messages (cardsV2 and formatted text) for solo builders integrating Workspace notifications.
Install
npx skills add https://github.com/jezweb/claude-skills --skill google-chat-messagesWhat is this skill?
- buildCard() composes cardsV2 with header, sections, optional image, and threadKey threading
- buildText() sends plain webhook text with Google Chat formatting rules documented inline
- Documents Chat markup (*bold*, _italic_, ~strike~, `code`, <url|label>)—not standard Markdown
- Typed exports against CardWithId, CardSection, WebhookMessage, and Thread shapes
- Pairs card and text builders with sendWebhook-style delivery patterns
Adoption & trust: 892 installs on skills.sh; 841 GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
You need to notify a Google Chat space from code but keep mixing up cardsV2 structure and Chat-specific text formatting.
Who is it for?
Solo builders adding deploy, alert, or agent status posts to Google Chat via webhooks from a TypeScript service or script.
Skip if: Teams building full Google Chat apps with OAuth, slash commands, or REST spaces APIs without webhooks—this skill does not cover app installation or auth flows.
When should I use this skill?
You are implementing or fixing Google Chat webhook posts and need cardsV2 or text payloads with correct Chat markup.
What do I get? / Deliverables
You emit valid WebhookMessage objects with headers, sections, threads, and Chat-safe formatting ready to POST to an incoming webhook.
- WebhookMessage JSON for cardsV2 or text
- Reusable buildCard/buildText helper patterns
Recommended Skills
Journey fit
Canonical shelf is Build because the skill is implemented as TypeScript helpers you wire into apps and automation that call Google Chat incoming webhooks. Integrations fits webhook payloads, cardsV2 layout, and thread keys—external messaging surface, not core product UI.
How it compares
Use instead of hand-rolling JSON from generic Markdown examples that break in Chat webhooks.
Common Questions / FAQ
Who is google-chat-messages for?
Indie and solo developers shipping small backends or automation that must post readable updates into Google Chat spaces using incoming webhooks.
When should I use google-chat-messages?
During Build integrations when you add monitoring bots, CI summaries, or agent handoff messages; also in Operate when you tweak alert card layouts for on-call channels.
Is google-chat-messages safe to install?
Review the Security Audits panel on this Prism page and inspect the skill source in your repo before granting network or secret access to webhook URLs.
SKILL.md
READMESKILL.md - Google Chat Messages
import type { CardWithId, CardHeader, CardSection, WebhookMessage, Thread } from './types'; interface BuildCardOptions { cardId: string; title: string; subtitle?: string; imageUrl?: string; imageType?: 'SQUARE' | 'CIRCLE'; sections: CardSection[]; } /** * Build a cardsV2 webhook message. * * Usage: * const message = buildCard({ cardId: 'my-card', title: 'Hello', sections: [...] }); * await sendWebhook(webhookUrl, message); */ export function buildCard( options: BuildCardOptions, thread?: { threadKey: string } ): WebhookMessage { const header: CardHeader = { title: options.title, ...(options.subtitle && { subtitle: options.subtitle }), ...(options.imageUrl && { imageUrl: options.imageUrl }), ...(options.imageType && { imageType: options.imageType }), }; const card: CardWithId = { cardId: options.cardId, card: { header, sections: options.sections, }, }; const message: WebhookMessage = { cardsV2: [card], }; if (thread) { message.thread = { threadKey: thread.threadKey }; } return message; } /** * Build a simple text webhook message. * * Remember: Google Chat uses *bold*, _italic_, ~strikethrough~, `code`, * and <url|text> for links. NOT standard Markdown. */ export function buildText( text: string, thread?: { threadKey: string } ): WebhookMessage { const message: WebhookMessage = { text }; if (thread) { message.thread = { threadKey: thread.threadKey }; } return message; } // Google Chat cardsV2 TypeScript types for webhook messages // Reference: https://developers.google.com/workspace/chat/api/reference/rest/v1/spaces.messages export interface WebhookMessage { text?: string; cardsV2?: CardWithId[]; thread?: Thread; } export interface Thread { threadKey?: string; } export interface CardWithId { cardId: string; card: Card; } export interface Card { header?: CardHeader; sections: CardSection[]; } export interface CardHeader { title: string; subtitle?: string; imageUrl?: string; imageType?: 'SQUARE' | 'CIRCLE'; } export interface CardSection { header?: string; widgets: Widget[]; collapsible?: boolean; uncollapsibleWidgetsCount?: number; } export interface Widget { textParagraph?: { text: string }; image?: { imageUrl: string; altText?: string }; decoratedText?: DecoratedText; buttonList?: { buttons: Button[] }; divider?: Record<string, never>; } export interface DecoratedText { topLabel?: string; text: string; bottomLabel?: string; startIcon?: Icon; endIcon?: Icon; wrapText?: boolean; onClick?: OnClick; button?: Button; } export interface Icon { knownIcon?: string; iconUrl?: string; altText?: string; } export interface Button { text: string; icon?: Icon; color?: { red?: number; green?: number; blue?: number; alpha?: number }; onClick: OnClick; disabled?: boolean; altText?: string; } export interface OnClick { openLink?: { url: string }; action?: { function?: string; parameters?: { key: string; value: string }[]; }; } import type { WebhookMessage } from './types'; interface SendOptions { /** Thread key for threading messages together */ threadKey?: string; /** If true, replies to existing thread or falls back to new thread */ replyToThread?: boolean; } /** * Send a message to Google Chat via incoming webhook. * * @param webhookUrl - The webhook URL from Google Chat space settings * @param message - WebhookMessage (use buildCard or buildText to create) * @param options - Threading options * * @example * // Simple text * await sendWebhook(url, { text: '*Hello* from webhook' }); * * // Card message * const card = buildCard({ cardId: 'test', title: 'Test', sections: [...] }); * await sendWebhook(url, card); * * // Threaded reply * await sendWebhook(url, card, { threadKey: 'deploy-123', replyToThread: true }); */ export async function sendWebhook( webhookUrl: string, message