コードを書かないSE日誌

SE歴26年。コードを書かずにClaude Codeで8体のAIエージェントチームを動かしています。AIエージェント・自動化・GTDの実験日誌。

Claude Codeのスケジュール枠は3つだけ——ディスパッチャー方式で何タスクでも回す設計

動機: 毎朝の手作業がしんどくなった

この記事を読み終えると、こういうプロンプトを自然に打てるようになる。

毎朝6時にZenn記事を1本公開するタスクを作って。
記事ごとの公開スケジュールはtasks/zenn-publish-queue.mdに定義してある
やるべき作業の通知を、9時〜18時の業務時間だけに絞って

この記事は、そこへたどり着くまでの話だ。

なお、この記事で紹介するディスパッチャー方式は単一エージェントでも動く。記事中に登場する agent:repo: フィールドは著者独自のマルチエージェント構成に固有の拡張で、省略して使っても問題ない。

Claude Codeを使い始めて1週間が経った。毎朝起動するたびに、同じことを繰り返していた。

  • 「今日公開予定のZenn記事があれば公開してきて」
  • 「今日期限のタスクをSlackに通知して」
  • 「ニュース収集してレポートを作って」
  • 「月曜だから組織ヘルスチェックをやって」

Claude Codeはこれらを忠実にこなしてくれる。が、問題はこちら側だ。起動のたびに、毎朝、同じことを言い続けている。

「これは自動化できるのではないか」と気づいたのは、Claude Codeのスケジュール実行(Scheduled Tasks。設定画面上では「Remote Triggers」と表示される)という機能を知ったときだった。設定した時刻に、登録したプロンプトを自動実行してくれる仕組みだ。「毎朝6時にZenn記事を公開して」と一度登録しておけば、あとは何もしなくていい。

追加費用は発生しない(著者確認時点(2026年4月)では、スケジュール実行はプランのサブスクリプション料金に含まれている)。

1週間の試行錯誤で気づいたことを整理する。

スケジュール枠の制約と「ディスパッチャー方式」の発明

スケジュール実行には、見落としやすい制約がある。

プランごとにスケジュールの登録枠数に上限があるのだ。これは公式ドキュメントには未記載で、GitHubのIssueで報告されている情報だ(Issue #40124)。Issue の原文は "3 daily cloud scheduled sessions" という表現で、登録枠数とも1日の実行回数とも読める。私の環境(Max 5xプラン)での実測では、同時に登録できるスケジュールが3枠まで機能している。あなたのプランで何枠利用可能かは確認してみてほしい。

注記: 本記事の情報は執筆時点(2026年4月)のものです。プランや仕様は変更される可能性があります。「3枠」はMax 5xプランでの実測値であり、あなたのプランでは異なる場合があります。

1枠に1プロンプトしか登録できない。つまり3枠あれば3タスクまでの計算になる。

やりたいことを数えてみた:

  • 毎朝: Zenn記事の公開、デイリーリサーチ、組織ヘルスチェック(月曜のみ)、月次ログアーカイブ
  • 毎時: 期限タスクのSlack通知

5つある。そしてこれは「今のところ」の話であって、使い込むほど増える。3枠はあっという間に溢れた。

「1つのセッションで複数タスクを回せないか」と考えた結果、ディスパッチャー方式を思いついた。

発想はシンプルだ。スケジュール実行に登録するのは「ディスパッチャーを呼び出すだけ」という最小プロンプト1本だけにする。実際のタスク定義はファイルに持たせ、ディスパッチャーがそのファイルを読んで振り分ける。

実際に登録しているプロンプトの骨格はこうだ:

cd <リポジトリ名>

.claude/schedules/daily.md を読み込み、
enabled: true のタスクを上から順に実行してください。

タスクごとに condition と hours を評価し、
条件を満たすものだけ実行すること。
エラーが発生しても必ず次のタスクに進むこと(中断禁止)。
実行ログは logs/dispatch/ に保存すること。
ERROR があれば Slack #claude-alerts に通知すること。

冒頭の cd <リポジトリ名> は省略できそうに見えるが、必須だ。スケジュール実行の環境はリポジトリのルートディレクトリから開始するとは限らない。実際に筆者の環境では作業ディレクトリが /home/user で始まり、リポジトリは1階層下にクローンされていた。cd がないとスケジュールファイルが見つからず、何も実行されずに終了する。

これで枠は2本で済む。毎日用と毎時用の2つだ。タスクの追加・停止・変更はファイルを編集するだけで完結する。スケジュール実行の設定ページを開く必要がない。

ディレクトリ構成とファイルの役割

実際のディレクトリ構成はこうなっている。以下は著者の運用リポジトリの構成例だ(テンプレートリポジトリの詳細は後述のセットアップ参照)。

.claude/schedules/
├── hourly.md              ← 毎時実行のタスクリスト
├── daily.md               ← 毎朝実行のタスクリスト
├── adhoc.md               ← 手動実行のタスクリスト
└── tasks/                 ← タスク定義ファイル(部品ライブラリ)
    ├── zenn-publish.md         ← 記事公開タスクの定義(手順書)
    ├── zenn-publish-queue.md   ← zenn-publish.mdが参照する公開スケジュール(データ)
    ├── daily-research.md
    ├── org-health-check.md
    ├── logs-archive.md
    └── todo-due-notify.md

ポイントは「タスクリスト」と「タスク定義ファイル」を分けている点だ。

タスクリストhourly.md / daily.md / adhoc.md)は、どのタスクをいつ・どの条件で実行するかを管理する。有効/無効の切り替えもここで行う。

タスク定義ファイルtasks/ 配下)は、タスクの具体的な手順をエージェントへの指示として記述したものだ。ここが「AIへの依頼書」本体にあたる。1つのタスク定義ファイルを複数のスケジュールから参照できるため、「毎日実行」と「手動実行」で同じ定義ファイルを使い回せる。

たとえば tasks/todo-due-notify.md の中身はこうなっている:

# todo-due-notify

期限超過・今日期限のGitHub Issueを検索し、Slack #claude-alerts に通知する。

1. gh issue list で due-date ラベルを持つ Issue を取得
2. 期限超過・今日期限のものを抽出
3. 該当があれば Slack #claude-alerts に通知
4. 該当がなければ何もしない(ログのみ記録)

やることを自然言語で箇条書きにするだけだ。シェルスクリプトでもYAMLでもない。

adhoc.md もスケジュール実行とは少し異なる使い方をする。定義したタスクをコミット&プッシュしたあと、claude.ai/code/scheduled から手動で「Run now」をクリックしてトリガーする。スケジュールは不要だが、毎回プロンプトを打ち直したくない繰り返し作業(月次アーカイブなど)の置き場として使っている。なお、実行後はディスパッチャーが自動で enabled: false に書き戻してコミットする設計になっているため、意図せず二重実行される心配がない。

スケジュールファイルの書き方

まずディスパッチャーが動作する流れを押さえておく。

1. スケジュールファイル(daily.md / hourly.md)を読み込む
2. task-id セクションを上から順に処理
3. 各タスクについて:
   a. enabled を確認 → false なら SKIP
   b. condition を確認 → 今日の曜日・日付に合わなければ SKIP
   c. hours を確認 → 現在時刻が範囲外なら SKIP
   d. task-file を読み込んで実行
   e. 結果を DONE / ERROR / SKIP として記録
4. エラーがあっても次のタスクに必ず進む(中断禁止)
5. 実行ログを logs/dispatch/ に保存
6. ERROR があれば Slack #claude-alerts に通知

「中断禁止」が重要な設計方針だ。あるタスクがエラーになっても、後続のタスクは必ず実行される。朝起きたら「Zennも通知も何もされていなかった」という状況を防ぐためのルールだ。

実際のスケジュールファイルを見てみよう。daily.md の一部を抜粋する。

## task-id: zenn-publish

- enabled: true
- description: Zenn記事の予約公開+Qiita・はてなクロスポスト
- condition: date-range: 2026-04-09..2026-04-17
- agent: secretary
- repo: zenn-content
- task-file: tasks/zenn-publish.md


## task-id: org-health-check

- enabled: true
- description: 組織の健全性点検
- condition: weekday: mon
- agent: devops
- repo: 000-partner
- task-file: tasks/org-health-check.md

毎時実行の hourly.md はこうなる。

## task-id: todo-due-notify

- enabled: true
- description: 期限超過・今日期限のタスクをSlack通知
- condition: always
- hours: 7-22
- agent: secretary
- repo: 000-partner
- task-file: tasks/todo-due-notify.md

各フィールドの意味は以下の通りだ。

フィールド 説明
enabled true / false で即座に一時停止できる
description 人間が読むためのメモ。ディスパッチャーは参照しない
condition 実行条件(下表参照)
hours 実行を許可するJST時間帯
agent 担当エージェント名(著者独自の拡張フィールド。テンプレートには含まれない)
repo 作業対象のリポジトリ名(著者独自の拡張フィールド。テンプレートには含まれない)
task-file タスク定義ファイルのパス

agent:repo: はマルチエージェント構成を採っている著者の運用に固有のフィールドだ。単一エージェントで動かす場合はこの2行を省いてもディスパッチャーは問題なく動作する。

condition フィールドでよく使うのは、毎回実行なら always、特定曜日のみなら weekday: mon(例: 月曜)、連載公開のような期間限定なら date-range: 2026-04-01..2026-04-30 の3パターンだ。全パターンは以下に示す。

condition の全パターン

意味
always 毎回実行
weekday 月〜金のみ
weekend 土日のみ
weekday: mon 月曜のみ(mon / tue / wed / thu / fri / sat / sun
monthday: 1 毎月1日のみ
date-range: 2026-04-01..2026-04-30 指定期間のみ

hours の値一覧

意味
7-22 7時〜22時
7,12,18 7時・12時・18時のみ
* 全時間帯
3 3時のみ

conditionhours の組み合わせが柔軟性の肝だ。「平日の業務時間帯(9〜18時)だけSlack通知を送る」なら condition: weekday + hours: 9-18 となる。

AIへのプロンプト例

この仕組みを整えてから、スケジューラーの操作はすべてClaude Codeへの自然言語指示になった。設定ファイルの書き方を覚える必要はなく、「こう言えばいい」という感覚だけで運用できている。

Claude Codeはタスクの description やファイルの内容から文脈を読んでくれる。英語のタスク名(task-id)を覚える必要はない。日本語で用途を伝えれば、該当するタスクを推測して操作してくれる。

実際に使っているプロンプト例を紹介する。

新しいタスクを追加したいとき

毎朝6時にZenn記事を1本公開するタスクを作って。
記事ごとの公開スケジュールはtasks/zenn-publish-queue.mdに定義してある

実行条件を変えたいとき

組織ヘルスチェックを月曜だけでなく金曜にも実行するように変更して

タスクを一時停止したいとき

デイリーリサーチを一時停止して。来週月曜に再開する

通知の時間帯を絞りたいとき

やるべき作業の通知を、9時〜18時の業務時間だけに絞って

臨時で今すぐ実行したいとき

組織ヘルスチェックを今すぐ実行して

エラーログを確認したいとき

先週のスケジューラー実行ログでエラーがあったか確認して

「こう言えばいいのか」という発見があれば、この方式の価値が伝わったと思う。cronを書く必要もなく、タスクIDを暗記する必要もない。自然言語で管理できることが、このアーキテクチャの最大のメリットだ。

プロンプトの書き方に慣れてくると、タスク定義ファイル自体の品質も上がっていく。「条件と成功基準を明示する」と失敗が減ることに気づいたのも、このスケジューラーを運用し始めてからだ。タスク定義ファイルを書くことは、「エージェントへの依頼書を書く練習」でもある。

ディスパッチャーが回す4軸の自動化(タスク管理・リサーチ・記事公開・通知)の全体像を知りたい方は「タスク管理・リサーチ・記事公開を全部AIに振ったら、人間はどこで判断すればよくなったか」も合わせてどうぞ。

使い分けとセットアップ

ディスパッチャー方式の立ち位置を整理してからセットアップに進む。

スケジュール関連機能の整理

Claude Codeには元からスケジュール系の機能が2つある。それぞれの位置づけを把握しておくと、どの機能を使うべきか迷わなくなる。

機能 用途 特徴
/schedule スケジュール実行の作成・管理 「3時にPRレビューして」のように自然言語で登録可能。1枠=1プロンプト。スケジュールの確認・変更・手動実行もできる
/loop セッション内の繰り返し・単発実行 「15時にreleaseブランチをpushして」のようなatコマンド的な使い方も可能。セッション中のみ有効
ディスパッチャー方式(本記事) 複数タスクの一元管理 /schedule で登録する1枠の中で、ファイルベースで何個でもタスクを回す

ディスパッチャー方式は /schedule を置き換えるものではなく、その上に乗る「運用設計」だ/schedule コマンドで2本(毎日用・毎時用)のトリガーを登録し、その中でファイルベースのタスク管理をする。

なお、リモートで動いているセッションへの介入手段(Desktopからのメッセージ送信や --teleport でのローカル引き取り)については「リモートセッションをローカルに引き戻す——Claude Code の新UIと teleport を使った話」で解説している。

/loop はセッション中のみ有効なので、PCを閉じたら止まる。「明日の朝6時に実行」のような用途にはスケジュール実行が適切だ。

cronやGitHub Actionsではだめなのか

技術的には可能だ。同じことをcronやGitHub Actionsで実現しようと思えばできる。ただし、ディスパッチャー方式には明確な優位性が2つある。

1つ目は「自然言語でタスクを管理できること」だ。cronはシェルスクリプトを書く必要があり、GitHub Actionsはワークフロー定義のYAMLを書く必要がある。ディスパッチャー方式ではタスク定義ファイルがそのまま「AIへの指示書」になる。タスクの追加・停止・条件変更はプロンプト1文で済む(先ほどのプロンプト例のように)。別言語を書く必要がない。

2つ目は「Claude Codeのエコシステム内で完結すること」だ。タスク定義ファイルをClaude Code上で作り、Claude Codeが読み、Claude Codeが実行する。ツールを横断しないため、文脈の分断がない。

一方で、正直に書いておく。1時間未満の細かい間隔で実行したい場合や、複雑な条件分岐・依存関係が必要なワークフローには、cron・GitHub Actionsの方が適している。この仕組みは「AIに自然言語で頼みたいタスク」に向いている。

スケジュール実行 vs /loop の比較

「定型業務を自動化したい」という用途では、スケジュール実行と /loop のどちらを選ぶかが最初の判断になる。主な違いをまとめた。

観点 スケジュール実行 /loop
セッション維持 不要(クラウド実行) 必要(PC起動・セッション中のみ)
最小間隔 1時間 1分
ローカルファイル 不可(リポジトリ内のみ) 可能
起動コスト 毎回clone(リポジトリサイズに依存) なし(即時)
安定性 PC電源オフでも動く PCスリープ・セッション切れで停止
トークン消費 トリガー実行分のみ ポーリングごとに消費(会話コンテキスト蓄積)
適するタスク 日次・毎時の定型業務 リアルタイム監視・ローカル作業

結論: 「放っておいても動いてほしい定型業務」はスケジュール実行、「今この場で繰り返し確認したい作業」は /loop だ。

なお、スケジュール実行の最小間隔が1時間である点は公式ドキュメントの比較表に明記されている。1時間より細かい間隔が必要なリアルタイム監視には /loop が適している。

Cloud版 vs Desktop版の違い

スケジュール実行には、Web版(claude.ai)とDesktop版で動作の差がある。どちらを使ってもディスパッチャー方式は動く。実行環境の選択は「ローカルファイルにアクセスが必要か」「PCを閉じていても動かしたいか」の2点で判断できる。

私がCloud版を選んだ理由は「PCを閉じていても朝6時に動いてほしい」という一点だ。ローカルファイルへのアクセスが必要になったときはDesktop版に切り替えればよい。

Cloud版 vs Desktop版 比較表

項目 Cloud(Web版) Desktop版
実行場所 Anthropicクラウド ローカルマシン
マシンOFF 動作する スキップ
ローカルファイル 不可(リポジトリ内のみ)
最小間隔 1時間 1分(公式ドキュメント Scheduled Tasks - Desktop に記載)
MCP コネクターのみ 設定ファイル+コネクター

なお、スケジュール実行はリポジトリを毎回cloneして実行する仕組みのため、リポジトリが肥大化すると起動が遅くなる。Markdownベースで運用する・ログは月次アーカイブで管理する・画像やバイナリは入れない、といった工夫で対処できる。

セットアップ

今すぐ始めるなら、bash 3行で十分だ。

mkdir -p .claude/schedules/tasks
mkdir -p logs/dispatch
touch logs/dispatch/.gitkeep

daily.md の最小テンプレート:

# Daily Schedule

## task-id: sample-task

- enabled: true
- description: サンプルタスク
- condition: always
- agent: secretary
- repo: your-repo
- task-file: tasks/sample-task.md

スケジュール登録はClaude Codeに向けてこう言えばよい:

cd <リポジトリ名>

.claude/schedules/daily.md を読んで enabled: true のタスクを
条件に合致するものだけ上から順に実行してください。
エラーが発生しても中断せず全タスクを実行してください。

このプロンプトを /schedule コマンドで登録する手順はこうだ。

  1. Claude Codeで /schedule を入力する
  2. 「毎朝6時にこのリポジトリで daily.md を実行して」のように自然言語で時刻と内容を伝える
  3. 登録後、claude.ai/code/scheduled の「Run now」ボタンで即時テスト実行して動作を確認する

先頭の cd <リポジトリ名> を忘れないこと。これを毎朝の希望時刻にスケジュール登録する。補足: スケジュール時刻はローカルタイムゾーン基準で設定され、実行は予定時刻より数分遅延する場合がある。

cd の省略とタイムゾーンの扱いは特にハマりやすい。詳しくは後述の「運用で踏んだ落とし穴」を参照してほしい。登録したら、必ず「Run now」で手動テストして動作を確認してから定期スケジュールを有効にすること。

テンプレートリポジトリを公開している。「Use this template」からリポジトリを作成し、/schedule でトリガーを登録するだけで動く。

運用で踏んだ落とし穴

ディスパッチャー方式を実際に動かし始めて、初回のトリガーで2つの落とし穴を踏んだ。どちらも「動かしてみないとわからない」類のもので、設定画面やドキュメントからは予測できなかった。

作業ディレクトリの罠

スケジュール実行の環境は、リポジトリのルートディレクトリで開始されるとは限らない。筆者の環境では /home/user がカレントディレクトリで、リポジトリは /home/user/000-partner にクローンされていた。

プロンプトの1行目が .claude/schedules/daily.md を読み込み… だったため、ファイルが見つからず何の出力もなく終了した。エラーメッセージすらなかった。

対策は単純で、プロンプトの冒頭に cd <リポジトリ名> を入れるだけだ。

タイムゾーンの罠

タスク定義ファイルの中で date -u +%Y-%m-%d を使ってUTC日付を取得していた。公開キューの日付はJST基準で書いていた。

トリガーを毎朝5:30 JSTに設定すると、UTCでは前日の20:30になる。JSTでは4月12日だが、UTCでは4月11日。公開キューに「2026-04-12」と書いてある記事が、いつまでも公開されない。

- date -u +%Y-%m-%d          # UTC: 前日の日付が返る
+ TZ=Asia/Tokyo date +%Y-%m-%d  # JST: 意図通りの日付が返る

スケジュール時刻がローカルタイムゾーン基準で設定される以上、タスク定義内の日付取得もそのタイムゾーンに合わせるのが自然だ。「UTC統一が正しい」という先入観が落とし穴だった。

この2つの問題はどちらも、修正後に「今すぐ実行」ボタンで再テストして解決を確認した。スケジュール実行には手動実行ボタンがある(claude.ai/code/scheduled)ので、初回セットアップ時には必ず手動実行で動作確認することを強く推奨する。

実際に稼働させてからもトラブルは続く。「プロンプトが消えた」「初期ディレクトリが変わった」「シークレットが渡らない」といった実運用での罠は「Claude Code スケジュール実行で踏んだ6つの罠と対処法」で続けて解説している。

まとめ

1週間の試行錯誤で見えてきた設計のポイントを共有する。変化は明確だ。

毎朝5回AIに話しかけていた定型の手作業はゼロになった(ただしログの監視や異常時の対応は引き続き必要だ)。Zenn記事の公開も、期限タスクのSlack通知も、週初めの組織ヘルスチェックも、朝起きたらすでに終わっている。

設計はこの記事を書くにあたって見直し、再構成した。最初は日次+週次の2トリガー構成で動かしていたが、「期限通知は毎時ほしい」という要件を整理した結果、日次+毎時の構成に切り替えた。設計は変えていい。 タスク定義がファイルに分離されているため、スケジュールの組み換えはファイルを整理するだけで済む。試行錯誤のコストが低い。

今後試したいのは、Slack経由での動的なタスク追加・停止、タスク間の依存関係(「AのDONE後にBを実行」)あたりだ。Claude Codeのスケジュール機能自体も進化中なので、枠数の制約が将来的に変わる可能性もある。

実際に使ってみて「このタスク定義の書き方が参考になった」「ここで詰まった」といったフィードバックをもらえると嬉しい。コメントでも、はてなスターでも。

ディスパッチャー方式のスケジューラ設計を含む、AIエージェント組織の全体設計をまとめた電子書籍を出しています。

コードを書けない私が、AIに「チーム」を持たせるまで(序章・第1部無料)

この記事のテーマを深掘りした本

Claude Codeで作る1人エージェントチーム エンジニア向け。writer + reviewer の2体から始めるサブエージェント設計(序章無料)

シリーズ全6冊: Vol.1 作るまでVol.2 回すまでVol.3 書き続けるまでVol.4 仕組みを渡すまでVol.5 仕事を任せるまでVol.6 1人エージェントチーム