Claude Codeで定期実行する3つの方法と、GitHub Actionsを選んだ理由
Routines・Desktop scheduled tasks・/loop は別物です。3つの違いを公式仕様で整理したうえで、私が実際に動かしている日次バッチにGitHub Actionsを選んだ理由と、そこで測った遅延・停止の実データを書きます。
「Claude Codeで定期実行する」と言ったとき、まったく違う3つの仕組みが候補になります。
私は最初これを混同していました。「クラウドで動く」「PCを閉じてもいい」「/schedule で作る」——これらが同じものを指していると思っていたのですが、違いました。
3つを整理したうえで、私が実際に動かしている日次バッチではどれも選ばなかった理由を書きます。
3つの選択肢
公式ドキュメントの比較表です。
| Routines(クラウド) | Desktop scheduled tasks | /loop |
|
|---|---|---|---|
| 実行場所 | Anthropicのクラウド | 自分のマシン | 自分のマシン |
| PCの電源 | 不要 | 必要 | 必要 |
| セッションを開いておく | 不要 | 不要 | 必要 |
| 再起動しても残る | 残る | 残る | --resume で復帰(未失効なら) |
| ローカルファイルへのアクセス | 不可(リポジトリを毎回クローン) | 可 | 可 |
| 許可の確認 | なし(自律実行) | タスクごとに設定可 | セッションを継承 |
| 最短の実行間隔 | 1時間 | 1分 | 1分 |
(出典: Run prompts on a schedule)
一番効いてくる違いは「ローカルファイルへのアクセス」です。
Routinesはクラウドで動くため、あなたのPCにあるファイルは見えません。GitHubリポジトリを毎回クローンして、その中で作業します。つまりGitHubに入っていないものは扱えません。
Routinesの正確な仕様
私が誤解していた点を中心に、公式の記述を引用します。
研究プレビューです
Routines are in research preview. Behavior, limits, and the API surface may change.
仕様が変わる前提で使う必要があります。
「追加コストなし」ではありません
これが一番の誤解でした。
Routines draw down subscription usage the same way interactive sessions do. In addition to the standard subscription limits, routines have a daily cap on how many runs can start per account.
対話セッションと同じようにサブスクリプションの枠を消費します。 そのうえで、1日に開始できる実行回数に別途上限があります。
「Maxプランなら無料で使い放題」ではありません。夜間に重いタスクを回せば、翌朝の対話に使える枠が減ります。
利用可能なのは Pro / Max / Team / Enterprise プランで、Claude Code on the web が有効になっていることが条件です。
許可の確認なしで動きます
Routines run autonomously as full Claude Code cloud sessions: there is no permission-mode picker and no approval prompts during a run.
パーミッションモードの選択肢がありません。 確認は一切入りません。
さらに、コネクタの扱いに注意が要ります。
Under Connectors at the bottom of the form, all of your connected MCP connectors are included by default. Remove any the routine doesn’t need: Claude can use every tool from an included connector, including writes, without asking for permission during a run.
接続済みのコネクタが既定で全部入ります。 そして書き込みを含むすべてのツールが、確認なしで使えます。
私はGmail・Google Drive・Google Calendar・Todoist・Figma・Canvaの6台を接続しています(MCPの記事参照)。これが全部、無確認で書き込み可能な状態でルーティンに渡ります。 作成フォームで外す必要があります。
実行は自分のアカウントとして行われます
Anything a routine does through your connected GitHub identity or connectors appears as you: commits and pull requests carry your GitHub user, and Slack messages, Linear tickets, or other connector actions use your linked accounts for those services.
コミットもPRも、あなたの名前で作られます。
最短1時間、ブランチは claude/ 接頭辞
The minimum interval is one hour; expressions that run more frequently are rejected.
Claude pushes its work to branches prefixed with
claude/, which are always accepted.
保護ブランチや、他人のコミットを含むブランチへのpushは拒否される仕組みになっています。
/loop は別物です
セッション内で動く仕組みで、Routinesとはまったく違います。
/loop 5m check if the deployment finished and tell me what happened
間隔を省くと、Claudeが状況を見て自分で次の間隔を決めます(1分〜1時間)。
制約が3つあります。
- セッションを閉じると止まります。 ターミナルを閉じたら終わりです
- 7日で自動失効します。 「忘れられたループが永久に回る」ことを防ぐ設計です
- 発火時刻がずれます(ジッター)
3番目は実務で効くので引用します。
Recurring tasks fire up to 30 minutes after the scheduled time (or up to half the interval, for tasks that run more often than hourly). An hourly job scheduled for
:00may fire anywhere up to:30.
毎時0分に設定しても、0分〜30分のどこかで動きます。 全セッションが同時にAPIを叩かないための意図的な仕様です。
回避策も書かれています。
If exact timing matters, pick a minute that is not
:00or:30, for example3 9 * * *instead of0 9 * * *, and the one-shot jitter will not apply.
:00 と :30 を避ける。これは後述するGitHub Actionsでも同じ話が出てきます。
現在のセッションの状態は、Claudeに聞けば分かります。
what scheduled tasks do I have?
裏では CronList というツールが呼ばれます。私の環境で実行した結果です。
No scheduled jobs.
私はGitHub Actionsを使っています
3つのうちどれも使っていません。実際に動かしている日次バッチはGitHub Actionsです。
AI各社のRSSを取得して要約し、通知するバッチを毎日走らせています。設定はこれだけです。
name: AI Daily Digest
on:
schedule:
# 毎日 21:26 UTC = 翌06:26 JST に実行(前日分をまとめて朝に通知)
# 毎時0分・30分ちょうどはGitHub Actions側が混雑し遅延・スキップされやすいため、
# あえて半端な分にずらしている
- cron: "26 21 * * *"
workflow_dispatch: # 手動実行も可
permissions:
contents: write # state/seen.json をコミットで永続化するため
concurrency:
group: ai-daily-digest
cancel-in-progress: false
なぜGitHub Actionsなのか
理由は3つです。
1. 決定的に動いてほしい
このバッチはAIエージェントである必要がありません。RSSを取り、Gemini APIに投げ、結果を整形して通知します。手順が完全に決まっています。
Routinesは「プロンプトを渡して自律的に判断させる」仕組みです。手順が決まっている処理をエージェントに任せると、毎回違う結果になるリスクを背負うだけです。
2. 失敗したときにログが残る
gh run view <id> --log-failed で、失敗したステップのログが全部読めます。実際、後述する2日間の停止はこれで原因を特定しました。
3. 状態をリポジトリにコミットできる
「どの記事を処理済みか」を state/seen.json に持ち、実行のたびにコミットしています。permissions: contents: write はそのためです。状態の履歴がgitに残ります。
判断基準
整理するとこうなります。
| 処理の性質 | 向いているもの |
|---|---|
| 手順が決まっている | GitHub Actions(決定的・ログが残る) |
| 判断が要る・毎回違う | Routines(自律実行) |
| ローカルのファイルを触る | Desktop scheduled tasks |
| 今このセッションで見張りたい | /loop |
「Claude Codeで自動化する」と考えると全部エージェントに寄せたくなりますが、決まった手順はスクリプトのほうが確実です。
GitHub Actionsで踏んだこと
自分の選択の弱点も書いておきます。
cronは1時間近く遅れます
設定は 21:26 UTC です。実際の実行時刻を並べます。
2026-07-28T22:32
2026-07-29T22:27
2026-07-30T22:34
2026-08-02T22:25
毎回1時間ほど遅れています。 :00 :30 を避けて半端な分にずらしてもこうです。
GitHub Actionsのスケジュール実行は混雑時に遅延・スキップされます。即時性が要件になるなら、この選択は間違いです。
面白いのは、/loop のジッターと理由が似ていることです。片方は仕様として明記されたジッター、もう片方は混雑による遅延ですが、どちらも「指定時刻ちょうどには動かない」。1日単位の枠を使う処理では、これが後述の障害の一因になります。
2日間止まっていることに気づきませんでした
2026-07-30T22:34 success
2026-07-31T22:31 failure ← ここから
2026-08-01T22:25 failure ← 2日連続
2026-08-02T05:49 success ← 復旧
失敗しても通知が飛ばない作りでした。 これはGitHub Actionsの問題ではなく、私の設計の問題です。
Routinesにも同じ落とし穴があります。公式にこう書かれています。
A green status in the run list means the session started and exited without an infrastructure error. It does not mean the task in your prompt succeeded.
緑は「インフラ的に落ちなかった」だけで、「タスクが成功した」ではありません。 どの方式を選んでも、成否を自分で判定して通知する仕組みが別途要ります。
この障害の詳細と、そのあと書いたリトライ実装は529 Overloadedと429の記事に書いています。
落とし穴:APIキーがあると /schedule が使えません
Routinesを作る /schedule コマンドが「そんなコマンドはない」と言われる場合、原因はこれかもしれません。
/schedulerequires a claude.ai subscription login. With a Console API key, submitting/scheduleinstead shows/schedule is available with Claude for Enterprise… IfANTHROPIC_API_KEYorANTHROPIC_AUTH_TOKENis set in your shell, orapiKeyHelperis set insettings.json, remove it first, since these take precedence over a claude.ai login
また ANTHROPIC_API_KEY です。
この記事群で、同じ環境変数が3回登場しました。
| 症状 | 記事 |
|---|---|
| サブスクではなくAPI従量課金になる | 完全ガイド |
| claude.aiのコネクタが読み込まれない | MCPの記事 |
/schedule がコマンド一覧から消える |
この記事 |
「機能が見当たらない」と思ったら、まず /status を見てください。 私はこの環境変数を4ヶ月放置していました。
なお /schedule が消える原因はもう1つあります。
DISABLE_TELEMETRY,DO_NOT_TRACK,CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC, orDISABLE_GROWTHBOOKis set… These disable feature-flag fetching, which/scheduledepends on
テレメトリを切っていると使えません。 プライバシー設定を絞っている人は該当します。
どう選ぶか
私の結論です。
まず「本当にAIに判断させる必要があるか」を問う。 手順が決まっているならGitHub Actionsやcronのほうが確実で、安く、ログが残ります。
判断が要るならRoutines。 ただし研究プレビューであること、サブスクの枠を消費すること、コネクタが全部無確認で渡ることを理解したうえで使います。
ローカルのファイルを触るならDesktop scheduled tasks。 Routinesはクラウドなので、GitHubに入っていないものは扱えません。
その場の見張りは /loop。 7日で失効するので、恒久的な自動化には使えません。
そしてどれを選んでも、失敗に気づける仕組みを別途作ってください。 私は2日間気づきませんでした。
この記事の確認環境
| 項目 | 内容 |
|---|---|
| 確認日 | 2026-08-03 |
| 実運用中の自動化 | GitHub Actions(日次・cron: "26 21 * * *") |
| 実測した遅延 | 設定時刻から約1時間 |
CronList の実行結果 |
No scheduled jobs. |
| 仕様の出典 | Claude Code公式ドキュメント(Routines / Scheduled tasks) |
Routines自体は、本記事の執筆時点で私は運用していません。仕様はすべて公式ドキュメントからの引用とし、実測値はGitHub Actionsの運用から取っています。