google-chat-messages by jezweb/claude-skills
npx skills add https://github.com/jezweb/claude-skills --skill google-chat-messages通过传入的 webhook 向 Google Chat 空间发送消息。可生成文本消息、富卡片(cardsV2)和线程回复。
在 Google Chat 中:
请将 URL 存储在环境变量或你的密钥管理器中——切勿硬编码。
| 需求 | 类型 | 复杂度 |
|---|---|---|
| 简单通知 | 文本消息 | 低 |
| 结构化信息(状态、摘要) | 卡片消息(cardsV2) | 中 |
| 持续更新 | 线程回复 | 中 |
| 操作按钮(打开 URL) | 带有按钮列表的卡片 | 中 |
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
使用 assets/webhook-sender.ts 作为发送工具。使用 assets/card-builder.ts 来构建结构化卡片。
Google Chat 不使用标准的 Markdown。
| 格式 | 语法 | 示例 |
|---|---|---|
| 粗体 | *text* | *important* |
| 斜体 | _text_ | _emphasis_ |
| 删除线 | ~text~ | ~removed~ |
| 等宽字体 | text | code |
| 代码块 | text | 多行代码 |
| 链接 | `<url | text>` |
| 提及用户 | <users/USER_ID> | <users/123456> |
| 提及所有人 | <users/all> | <users/all> |
不支持:**双星号**、标题(###)、引用块、表格、行内图片。
await sendText(webhookUrl, '*构建完成*\n\n分支:`main`\n状态:已通过\n<https://ci.example.com/123|查看构建>');
卡片使用 cardsV2 格式(推荐使用,而非旧版卡片)。
const message = {
cardsV2: [{
cardId: 'unique-id',
card: {
header: {
title: '卡片标题',
subtitle: '可选副标题',
imageUrl: 'https://example.com/icon.png',
imageType: 'CIRCLE' // 或 'SQUARE'
},
sections: [{
header: '分区标题', // 可选
widgets: [
// 小部件放在这里
]
}]
}
}]
};
文本段落 — 格式化的文本块:
{ textParagraph: { text: '*粗体* 和 _斜体_ 文本' } }
装饰文本 — 标签 + 值,可选图标:
{
decoratedText: {
topLabel: '状态',
text: '已部署',
startIcon: { knownIcon: 'STAR' }
}
}
按钮列表 — 操作按钮:
{
buttonList: {
buttons: [{
text: '查看仪表板',
onClick: { openLink: { url: 'https://dashboard.example.com' } }
}]
}
}
图片 — 独立图片:
{ image: { imageUrl: 'https://example.com/chart.png', altText: '使用情况图表' } }
分隔线 — 水平分隔符:
{ divider: {} }
所有小部件类型及完整示例请参见 references/widget-reference.md。所有可用的 knownIcon 值请参见 references/icon-list.md。
使用 threadKey 将消息组织到线程中:
// 第一条消息 — 创建线程
const response = await sendCard(webhookUrl, card, {
threadKey: 'deploy-2026-02-16'
});
// 回复到线程 — 在 webhook URL 后追加 &messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD
const threadUrl = `${webhookUrl}&messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD`;
await sendCard(threadUrl, replyCard, {
threadKey: 'deploy-2026-02-16'
});
threadKey 是客户端分配的字符串。对相关消息使用一致的键(例如 deploy-{日期}、alert-{id})。
import { buildCard, sendCard } from './assets/card-builder';
import { sendWebhook } from './assets/webhook-sender';
const card = buildCard({
cardId: 'deploy-notification',
title: '部署完成',
subtitle: 'production - v2.1.0',
imageUrl: 'https://example.com/your-icon.png',
sections: [{
widgets: [
{ decoratedText: { topLabel: '环境', text: 'Production' } },
{ decoratedText: { topLabel: '版本', text: 'v2.1.0' } },
{ decoratedText: { topLabel: '状态', text: '*健康*', startIcon: { knownIcon: 'STAR' } } },
{ buttonList: { buttons: [{ text: '查看部署', onClick: { openLink: { url: 'https://dash.example.com' } } }] } }
]
}]
});
const digest = buildCard({
cardId: 'weekly-digest',
title: '每周摘要',
subtitle: `本周有 ${count} 条更新`,
sections: [
{
header: '亮点',
widgets: items.map(item => ({
decoratedText: { text: item.title, bottomLabel: item.date }
}))
},
{
widgets: [{
buttonList: {
buttons: [{ text: '查看全部', onClick: { openLink: { url: dashboardUrl } } }]
}
}]
}
]
});
await sendText(webhookUrl, `*告警*:\`worker-prod-1\` 上的 CPU 使用率超过 90%\n<${alertUrl}|查看告警>`);
| 错误 | 修复方法 |
|---|---|
文本中使用 **bold** | 使用 *bold*(单星号) |
[text](url) 格式的链接 | 使用 `<url |
缺少 cardsV2 包装器 | 将卡片包装在 { cardsV2: [{ cardId, card }] } 中 |
| 线程回复未进入线程 | 在 webhook URL 后追加 &messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD |
| Webhook 返回 400 | 检查 JSON 结构——常见问题是顶层缺少 text 或 cardsV2 |
| 卡片未显示 | 确保 sections 中至少有一个小部件 |
| 文件 | 用途 |
|---|---|
assets/types.ts | cardsV2 的 TypeScript 类型定义 |
assets/card-builder.ts | 构建卡片消息的工具 |
assets/webhook-sender.ts | 向 webhook 发送 POST 请求,包含错误处理 |
每周安装量
367
仓库
GitHub 星标数
643
首次出现
2026年2月18日
安全审计
安装于
opencode327
codex323
github-copilot323
gemini-cli321
cursor319
kimi-cli313
Send messages to Google Chat spaces via incoming webhooks. Produces text messages, rich cards (cardsV2), and threaded replies.
In Google Chat:
Store the URL as an environment variable or in your secrets manager — never hardcode.
| Need | Type | Complexity |
|---|---|---|
| Simple notification | Text message | Low |
| Structured info (status, digest) | Card message (cardsV2) | Medium |
| Ongoing updates | Threaded replies | Medium |
| Action buttons (open URL) | Card with buttonList | Medium |
Use assets/webhook-sender.ts for the sender utility. Use assets/card-builder.ts for structured card construction.
Google Chat does NOT use standard Markdown.
| Format | Syntax | Example |
|---|---|---|
| Bold | *text* | *important* |
| Italic | _text_ | _emphasis_ |
| Strikethrough | ~text~ | ~removed~ |
| Monospace | text |
Not supported : **double asterisks**, headings (###), blockquotes, tables, images inline.
await sendText(webhookUrl, '*Build Complete*\n\nBranch: `main`\nStatus: Passed\n<https://ci.example.com/123|View Build>');
Cards use the cardsV2 format (recommended over legacy cards).
const message = {
cardsV2: [{
cardId: 'unique-id',
card: {
header: {
title: 'Card Title',
subtitle: 'Optional subtitle',
imageUrl: 'https://example.com/icon.png',
imageType: 'CIRCLE' // or 'SQUARE'
},
sections: [{
header: 'Section Title', // optional
widgets: [
// widgets go here
]
}]
}
}]
};
Text paragraph — formatted text block:
{ textParagraph: { text: '*Bold* and _italic_ text' } }
Decorated text — label + value with optional icon:
{
decoratedText: {
topLabel: 'Status',
text: 'Deployed',
startIcon: { knownIcon: 'STAR' }
}
}
Button list — action buttons:
{
buttonList: {
buttons: [{
text: 'View Dashboard',
onClick: { openLink: { url: 'https://dashboard.example.com' } }
}]
}
}
Image — standalone image:
{ image: { imageUrl: 'https://example.com/chart.png', altText: 'Usage chart' } }
Divider — horizontal separator:
{ divider: {} }
See references/widget-reference.md for all widget types with full examples. See references/icon-list.md for all available knownIcon values.
Thread messages together using threadKey:
// First message — creates thread
const response = await sendCard(webhookUrl, card, {
threadKey: 'deploy-2026-02-16'
});
// Reply to thread — append &messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD
const threadUrl = `${webhookUrl}&messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD`;
await sendCard(threadUrl, replyCard, {
threadKey: 'deploy-2026-02-16'
});
The threadKey is a client-assigned string. Use consistent keys for related messages (e.g., deploy-{date}, alert-{id}).
import { buildCard, sendCard } from './assets/card-builder';
import { sendWebhook } from './assets/webhook-sender';
const card = buildCard({
cardId: 'deploy-notification',
title: 'Deployment Complete',
subtitle: 'production - v2.1.0',
imageUrl: 'https://example.com/your-icon.png',
sections: [{
widgets: [
{ decoratedText: { topLabel: 'Environment', text: 'Production' } },
{ decoratedText: { topLabel: 'Version', text: 'v2.1.0' } },
{ decoratedText: { topLabel: 'Status', text: '*Healthy*', startIcon: { knownIcon: 'STAR' } } },
{ buttonList: { buttons: [{ text: 'View Deployment', onClick: { openLink: { url: 'https://dash.example.com' } } }] } }
]
}]
});
const digest = buildCard({
cardId: 'weekly-digest',
title: 'Weekly Summary',
subtitle: `${count} updates this week`,
sections: [
{
header: 'Highlights',
widgets: items.map(item => ({
decoratedText: { text: item.title, bottomLabel: item.date }
}))
},
{
widgets: [{
buttonList: {
buttons: [{ text: 'View All', onClick: { openLink: { url: dashboardUrl } } }]
}
}]
}
]
});
await sendText(webhookUrl, `*Alert*: CPU usage above 90% on \`worker-prod-1\`\n<${alertUrl}|View Alert>`);
| Mistake | Fix |
|---|---|
**bold** in text | Use *bold* (single asterisks) |
[text](url) links | Use `<url |
Missing cardsV2 wrapper | Wrap card in { cardsV2: [{ cardId, card }] } |
| Thread replies not threading | Append &messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD to webhook URL |
| Webhook returns 400 | Check JSON structure — common issue is missing or at top level |
| File | Purpose |
|---|---|
assets/types.ts | TypeScript type definitions for cardsV2 |
assets/card-builder.ts | Utility to build card messages |
assets/webhook-sender.ts | POST to webhook with error handling |
Weekly Installs
367
Repository
GitHub Stars
643
First Seen
Feb 18, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykPass
Installed on
opencode327
codex323
github-copilot323
gemini-cli321
cursor319
kimi-cli313
Azure 升级评估与自动化工具 - 轻松迁移 Functions 计划、托管层级和 SKU
68,100 周安装
code |
| Code block | text | Multi-line code |
| Link | `<url | text>` |
| Mention user | <users/USER_ID> | <users/123456> |
| Mention all | <users/all> | <users/all> |
textcardsV2| Card not showing | Ensure sections has at least one widget |