google-chat-messages について
google-chat-messagesは、Google Chatの受信Webhook経由で通知や構造化された更新を送るスキルです。テキスト、cardsV2カード、スレッド返信に対応し、メッセージの作成と送信に使えるTypeScriptユーティリティを備えています。
主な機能
- 01書式付きテキストメッセージの送信
- 02cardsV2リッチカードの作成
- 03スレッド返信の送信
- 04TypeScript Webhookユーティリティの利用
活用シーン
- 01デプロイ状況の通知
- 02週次ダイジェストカードの送信
- 03スレッド内でのアラート更新
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ jezweb/ claude-skills --skill google-chat-messagesインストール後、Claude Code で/google-chat-messagesを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
assets/card-builder.tstypes.tswebhook-sender.ts詳細
Google Chat メッセージ
受信 Webhook を通じて Google Chat のスペースにメッセージを送信します。テキストメッセージ、リッチカード(cardsV2)、スレッド返信を作成できます。
作成できるもの
- Google Chat の書式設定に対応したテキストメッセージ
- ヘッダー、セクション、ウィジェットを含むリッチカードメッセージ(cardsV2)
- スレッド形式の会話
- 再利用可能な Webhook 送信ユーティリティ
ワークフロー
ステップ 1:Webhook URL を取得する
Google Chat で:
- スペースを開き、スペース名をクリックして、Webhook を管理を選択します
- Webhook を作成します(名前を付け、必要に応じてアバター URL を追加します)
- Webhook URL をコピーします
URL は環境変数またはシークレットマネージャーに保存し、ハードコードしないでください。
ステップ 2:メッセージの種類を選ぶ
| 必要なもの | 種類 | 複雑さ |
|---|---|---|
| シンプルな通知 | テキストメッセージ | 低 |
| 構造化された情報(ステータス、ダイジェスト) | カードメッセージ(cardsV2) | 中 |
| 継続的な更新 | スレッド返信 | 中 |
| アクションボタン(URL を開く) | buttonList を含むカード | 中 |
ステップ 3:メッセージを送信する
送信ユーティリティには assets/webhook-sender.ts を使用します。構造化カードの作成には assets/card-builder.ts を使用します。
テキストの書式設定
Google Chat では標準の Markdown は使用されません。
| 書式 | 構文 | 例 |
|---|---|---|
| 太字 | *text* | *important* |
| 斜体 | _text_ | _emphasis_ |
| 取り消し線 | ~text~ | ~removed~ |
| 等幅 | `text` | `code` |
| コードブロック | ```text``` | 複数行のコード |
| リンク | <url|text> | <https://example.com|こちらをクリック> |
| ユーザーへのメンション | <users/USER_ID> | <users/123456> |
| 全員へのメンション | <users/all> | <users/all> |
サポート対象外:**double asterisks**、見出し(###)、引用、表、インライン画像。
テキストメッセージの例
await sendText(webhookUrl, '*Build Complete*\n\nBranch: `main`\nStatus: Passed\n<https://ci.example.com/123|View Build>');
cardsV2 の構造
カードには cardsV2 形式を使用します(従来のカード形式より推奨)。
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
]
}]
}
}]
};
ウィジェットのリファレンス
cardsV2 のセクションで使用できるすべてのウィジェットタイプです。
textParagraph
書式設定されたテキストブロックです。Google Chat の書式設定(*bold*、_italic_、<url|text>)に対応しています。
{
textParagraph: {
text: '*Status*: All systems operational\n_Last checked_: 5 minutes ago'
}
}
decoratedText
アイコンを任意で付けられるラベル付きの値です。キーと値のデータに最も汎用的なウィジェットです。
基本:
{
decoratedText: {
topLabel: 'Environment',
text: 'Production',
bottomLabel: 'Last deployed 2h ago'
}
}
開始アイコン付き:
{
decoratedText: {
topLabel: 'Status',
text: 'Healthy',
startIcon: { knownIcon: 'STAR' }
}
}
カスタムアイコン URL 付き:
{
decoratedText: {
topLabel: 'GitHub',
text: 'PR #142 merged',
startIcon: {
iconUrl: 'https://github.githubassets.com/favicons/favicon.svg',
altText: 'GitHub'
}
}
}
ボタン付き:
{
decoratedText: {
topLabel: 'Alert',
text: 'CPU at 95%',
button: {
text: 'View',
onClick: { openLink: { url: 'https://monitoring.example.com' } }
}
}
}
クリック可能(ウィジェット全体):
{
decoratedText: {
text: 'View full report',
wrapText: true,
onClick: { openLink: { url: 'https://reports.example.com' } }
}
}
テキストの折り返し付き:
{
decoratedText: {
topLabel: 'Description',
text: 'This is a longer description that should wrap to multiple lines instead of being truncated',
wrapText: true
}
}
buttonList
1 つ以上のアクションボタンです。ボタンを使用すると URL を開いたり、アクションを実行したりできます。
単一のボタン:
{
buttonList: {
buttons: [{
text: 'Open Dashboard',
onClick: { openLink: { url: 'https://dashboard.example.com' } }
}]
}
}
複数のボタン:
{
buttonList: {
buttons: [
{
text: 'Approve',
onClick: { openLink: { url: 'https://app.example.com/approve/123' } },
color: { red: 0, green: 0.5, blue: 0, alpha: 1 }
},
{
text: 'Reject',
onClick: { openLink: { url: 'https://app.example.com/reject/123' } }
}
]
}
}
アイコン付きボタン:
{
buttonList: {
buttons: [{
text: 'View on GitHub',
icon: { knownIcon: 'BOOKMARK' },
onClick: { openLink: { url: 'https://github.com/org/repo/pull/42' } }
}]
}
}
image
単独で表示する画像ウィジェットです。
{
image: {
imageUrl: 'https://example.com/chart.png',
altText: 'Monthly usage chart'
}
}
divider
ウィジェット間に水平の区切り線を表示します。
{ divider: {} }
折りたたみ可能なセクション
セクションは折りたたんで、最初の N 個のウィジェットだけを表示できます。
{
header: 'Details',
collapsible: true,
uncollapsibleWidgetsCount: 2, // Show first 2, collapse rest
widgets: [
{ decoratedText: { topLabel: 'Status', text: 'Active' } },
{ decoratedText: { topLabel: 'Region', text: 'AU' } },
// These start collapsed
{ decoratedText: { topLabel: 'Instance', text: 'prod-01' } },
{ decoratedText: { topLabel: 'Memory', text: '2.1 GB' } },
{ decoratedText: { topLabel: 'CPU', text: '45%' } }
]
}
既知のアイコン
decoratedText と button ウィジェットで knownIcon を通じて使用できるアイコンです。
{ startIcon: { knownIcon: 'STAR' } }
// or
{ icon: { knownIcon: 'EMAIL' } }
| アイコン名 | 用途 |
|---|---|
AIRPLANE | 旅行、フライト |
BOOKMARK | 保存、参照、リンク |
BUS | 交通機関、公共交通 |
CAR | 運転、交通機関 |
CLOCK | 時刻、所要時間、スケジュール |
CONFIRMATION_NUMBER_ICON | チケット、予約 |
DESCRIPTION | ドキュメント、ファイル |
DOLLAR | 金銭、価格、費用 |
EMAIL | メール、メッセージ |
INVITE | 招待 |
MAP_PIN | 場所、住所 |
MEMBERSHIP | メンバー、ユーザー |
MULTIPLE_PEOPLE | チーム、グループ |
OFFER | セール、プロモーション |
PERSON | 個人ユーザー |
PHONE | 電話番号、通話 |
SHOPPING_CART | 商取引、購入 |
STAR | 評価、お気に入り、重要 |
STORE | 店舗、小売 |
TICKET | チケット、イベント |
VIDEO_CAMERA | 動画、会議 |
一覧にないアイコンには、一般公開されている任意の画像を iconUrl で使用します(正方形で、24x24 または 48x48 ピクセルが理想的です)。
スレッド
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'
});
threadKey はクライアントが割り当てる文字列です。関連するメッセージには一貫したキーを使用します(例: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 } } }]
}
}]
}
]
});
エラーの防止
| 間違い | 修正方法 |
|---|---|
テキスト内の **bold** | *bold*(アスタリスク1つ)を使用します |
[text](url) 形式のリンク | <url|text> 形式を使用します |
cardsV2 ラッパーがない | カードを { cardsV2: [{ cardId, card }] } でラップします |
| スレッドへの返信がスレッド化されない | Webhook URL に &messageReplyOption=REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD を追加します |
| Webhook が 400 を返す | JSON 構造を確認します。よくある原因は、トップレベルに text または cardsV2 がないことです |
| カードが表示されない | sections にウィジェットが少なくとも1つ含まれていることを確認します |
アセットファイル
| ファイル | 用途 |
|---|---|
assets/types.ts | cardsV2 の TypeScript 型定義 |
assets/card-builder.ts | カードメッセージを作成するユーティリティ |
assets/webhook-sender.ts | エラー処理付きで Webhook に POST します |