栖王ヴァルハラ3丁目 ヘッダーイラスト
Illustration by ruder

明日になったら今日じゃない

栖王ヴァルハラ3丁目

すばら3 / Subara3

Claude Codeで、毎朝Discordへ自動投稿させる

カテゴリ: tech

タグ: Claude Code,Discord,GitHub Actions,自動化

Discordに届いた朝のまとめ。日付タイトルと公募情報のセクションが並ぶ

趣味の短歌とか俳句とかと、ゲームジャムの情報とかを眺めている。ほか、天気など。

Claude Code(claude.ai)の ルーチン機能 で、毎朝6時にいい感じに情報を集めてDiscordに自動投稿してくれるようにしました。

外部サービス(Cloudflare Workers / n8n / Zapier 等)は使わず、GitHub と claude.ai だけで完結する構成です。

経緯

もともと立ち上げっぱなしのMacBookを使用して、OpenClawでやってたんですが、いまいち安全ではないな、と思っていたところでClaude公式から機能が追加されたのでこちらに移行しました。月額料金の範囲内で使用できるのが良い点ですね。

ルーチン機能について

Claude Code には、定期実行用の仕組みが2種類あるようです。いつのまにか増えてました。

Routines(ルーチン)Desktop Scheduled Tasks
実行場所Anthropic のクラウドローカルPC
PC起動不要必要
ローカルファイルアクセス不可
トリガーcron / 一回限り / API / GitHub webhookスケジュール / 手動

今回は「PCを開いてなくても毎朝動いてほしい」ので クラウド側のルーチン を使います。
逆に、ローカルファイルを触る定期処理(例:手元のリポジトリをビルドして FTP アップロード)は Desktop Scheduled Tasks のほうが向いています。

参考: Routines / Desktop Scheduled Tasks(公式ドキュメント)

claude.ai のサイドバーにあるルーチンタブ。登録済みのルーチンが一覧で表示される

claude.ai のルーチンタブ。登録済みのルーチンが並ぶ。

全体の流れ

claude.ai のルーチンが Markdown を git push し、GitHub Actions が Discord webhook に POST する流れ

ルーチン側は Markdown を git push しています。GitHub Actions が拾ってDiscordに流します。
claude.ai のサンドボックスから直接 Discord は叩けない(egress allowlist 外)ので、間に GitHub Actions を一段挟みます。

やったこと

1. 空の private リポジトリを作る

GitHub の Web UI で <owner>/daily-brief のような空 repo を作ります。

2. Claude.ai の GitHub App にそのリポジトリを追加する

github.com/settings/installations → Claude → Repository access で、作った repo を選択。
これを忘れると、ルーチン側からの clone が通りません。

3. Discord webhook を Actions Secret に登録する

gh secret set DISCORD_WEBHOOK_URL \
  --repo <owner>/daily-brief \
  --body "https://discord.com/api/webhooks/..."

--body "VALUE" で直接渡します。

4. Workflow を commit する

.github/workflows/post-to-discord.yml:

name: post-to-discord
on:
  push:
    paths: ['posts/**.md']
jobs:
  post:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with: { fetch-depth: 2 }
      - name: Send to Discord
        env:
          WEBHOOK: ${{ secrets.DISCORD_WEBHOOK_URL }}
        run: |
          set -euo pipefail
          if [ -z "${WEBHOOK:-}" ]; then echo 'WEBHOOK secret not set'; exit 1; fi
          if git rev-parse HEAD~1 >/dev/null 2>&1; then
            FILES=$(git diff --name-only --diff-filter=AM HEAD~1 HEAD -- 'posts/*.md' || true)
          else
            FILES=$(git ls-files 'posts/*.md')
          fi
          [ -z "$FILES" ] && { echo 'no post files'; exit 0; }
          for f in $FILES; do
            python3 - "$f" <<'PY'
          import sys, os, json, time, urllib.request
          path = sys.argv[1]
          webhook = os.environ['WEBHOOK']
          UA = 'daily-brief-bot/1.0'
          text = open(path, encoding='utf-8').read().rstrip() + '\n'
          paras = text.split('\n\n')
          chunks, cur = [], ''
          for p in paras:
              candidate = (cur + '\n\n' + p) if cur else p
              if len(candidate) <= 1900:
                  cur = candidate
              else:
                  if cur: chunks.append(cur)
                  cur = p if len(p) <= 1900 else p[:1900]
          if cur: chunks.append(cur)
          for i, c in enumerate(chunks):
              body = json.dumps({'content': c, 'allowed_mentions': {'parse': []}}).encode()
              req = urllib.request.Request(webhook, data=body, method='POST',
                  headers={'Content-Type': 'application/json', 'User-Agent': UA})
              with urllib.request.urlopen(req) as r:
                  print(f'{path} [{i+1}/{len(chunks)}] -> {r.status}')
              if i < len(chunks) - 1:
                  time.sleep(1.2)
          PY
          done

ポイント

  • paths: ['posts/**.md']posts/ 配下の .md 変更だけをトリガにする
  • User-Agent ヘッダを必ずセットする(urllib のデフォルト UA は Cloudflare に bot 判定されて 403 になる)
  • Discord の2000字制限に引っかからないよう、段落境界で分割。チャンク間に1.2秒 sleep
  • fetch-depth: 2 で直前 commit を確保し、diff で「今回追加された投稿」だけを送る

5. claude.ai のルーチンを作る

  • cron_expression: "0 21 * * *"(06:00 JST = 21:00 UTC)
  • session_context.sources: [{git_repository: {url: "https://github.com/<owner>/daily-brief"}}]
  • プロンプトは「harness が clone 済みの前提で、WebSearch → Markdown 生成 → posts/$DATE.md に write → git add/commit/push origin main

6. 完成

翌朝 06:00 JST に Discord に流れてきます。
確かめたければ実行ボタンを押せばいいですね。

記事

プライバシーポリシー Last Update: 2025/10/14

個人情報の取り扱いについて

当サイトでは、お問い合わせフォームからご連絡いただいた際に、お名前やメールアドレスなどの個人情報をお預かりすることがあります。

これらの情報は、お問い合わせへの返信や必要なご連絡のためにのみ使用し、それ以外の目的で使用することはありません。また、法令に基づく場合を除き、第三者に開示・提供することはありません。

Cookieの使用について

当サイトでは、サイトの利便性向上やアクセス解析のためにCookieを使用しています。

Cookieはブラウザの設定により無効にすることができますが、一部の機能が正しく動作しなくなる場合があります。

アクセス解析ツールについて

当サイトでは、Googleによるアクセス解析ツール「Google Analytics」を使用しています。

Google Analyticsはトラフィックデータの収集のためにCookieを使用しており、このトラフィックデータは匿名で収集されています。個人を特定するものではありません。

この機能はCookieを無効にすることで収集を拒否することができますので、お使いのブラウザの設定をご確認ください。

詳細については、Google アナリティクス利用規約をご参照ください。

広告の配信について

当サイトでは、第三者配信の広告サービス「Google AdSense」を使用しています。

広告配信事業者は、ユーザーの興味に応じた広告を表示するためにCookieを使用することがあります。

Google AdSenseの詳細については、Google 広告に関するポリシーをご参照ください。

アフィリエイトについて

当サイトは、Amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイトプログラムである、Amazonアソシエイト・プログラムの参加者です。

その他、各種アフィリエイトプログラムに参加している場合があります。

著作権について

当サイトに掲載されている文章、画像、その他のコンテンツの著作権は、当サイト管理者または正当な権利を有する第三者に帰属します。

無断転載・複製はご遠慮ください。引用の際は、出典を明記のうえ、リンクを貼っていただけますようお願いいたします。

免責事項

当サイトの情報は、可能な限り正確な情報を掲載するよう努めていますが、その正確性や安全性を保証するものではありません。

当サイトに掲載された内容によって生じた損害等について、一切の責任を負いかねますのでご了承ください。

また、当サイトからリンクやバナーなどによって他のサイトに移動された場合、移動先サイトで提供される情報、サービス等について一切の責任を負いません。

プライバシーポリシーの変更について

当サイトは、個人情報に関して適用される日本の法令を遵守するとともに、本ポリシーの内容を適宜見直し、その改善に努めます。

修正された最新のプライバシーポリシーは常に本ページにて開示されます。

01

ここについて

栖王ヴァルハラ3丁目は、個人(頻子)が運営しているサイトです。小説、ゲーム、アプリケーションなどがあります。サイトのコンテンツは、予告なく改稿したり、削除されることがあります。

(2022/5/29)二次創作置き場を増設しました。


もし何かご用があれば、お問い合わせフォームからお声をおかけください(記名不要)。

応援・ご感想・誤字脱字報告などお気軽にどうぞ

お問い合わせ
02

自己紹介

頻子(ひんこ)です。
ゲームと文章を書くことが好きです。

info★subara3.com (★→@)

活動場所

投げ銭

03

このサイトへのリンク

2017/09/06 有料サーバーに移行 2025/10/10 独自ドメイン化
04

既刊情報

すばら3ロゴ

すばら3の既刊はBOOTH、DLsite、kindle、あるいは各種イベントで入手することができます。

一部の本は、国会図書館に預けてきました
寄稿したものは、それぞれの頒布先をご確認ください。

サークルロゴは高瀬川さんがつくってくださいました。ありがとう!

05

寄稿・お手伝い

06

お仕事

気まぐれに軽めの単発案件を受け付けています。
簡単なスクリプトなど、ご入用のものがありましたらぜひどうぞ!

info★subara3.com (★→@)

07

プライバシーポリシー

最終更新: 2025/10/14

個人情報の取り扱い

お問い合わせフォームからご連絡いただいたメッセージは、必要なご連絡のためにのみ使用します。許可なく第三者に開示・提供することはありません。

Cookieの使用

サイトの利便性向上やアクセス解析のためにCookieを使用しています。ブラウザ設定で無効にできますが、一部機能が正しく動作しなくなる場合があります。

アクセス解析

Google Analyticsを使用しています。トラフィックデータは匿名で収集され、個人を特定するものではありません。

広告配信

第三者配信の広告サービス「Google AdSense」を使用しています。ユーザーの興味に応じた広告表示のためにCookieを使用することがあります。

アフィリエイト

Amazonアソシエイト・プログラム等に参加しています。

著作権

掲載コンテンツの著作権は当サイト管理者または正当な権利者に帰属します。無断転載・複製はご遠慮ください。

免責事項

情報の正確性・安全性を保証するものではありません。当サイトの内容によって生じた損害等について責任を負いかねます。