CLAUDE LABEN
MODEL — Claude Sonnet 5が全プランの既定モデルになり、計画・ツール利用・自律実行が強化されましたPRICE — Sonnet 5は導入価格が100万トークンあたり入力$2・出力$10で、8月31日まで適用されますMODEL — Sonnet 5の性能はOpus 4.8に迫りつつ、より低価格でエージェントを常時運用できますCODE — Claude CodeがSonnet 5を既定モデルに採用し、ネイティブ1Mトークンのコンテキストに対応しましたCODE — Claude Codeにサンドボックスの資格情報ブロックと組織単位のモデル制限が追加されましたCLOUD — ClaudeがMicrosoft Foundry(Azure)で一般提供され、Azureネイティブで利用できますMODEL — Claude Sonnet 5が全プランの既定モデルになり、計画・ツール利用・自律実行が強化されましたPRICE — Sonnet 5は導入価格が100万トークンあたり入力$2・出力$10で、8月31日まで適用されますMODEL — Sonnet 5の性能はOpus 4.8に迫りつつ、より低価格でエージェントを常時運用できますCODE — Claude CodeがSonnet 5を既定モデルに採用し、ネイティブ1Mトークンのコンテキストに対応しましたCODE — Claude Codeにサンドボックスの資格情報ブロックと組織単位のモデル制限が追加されましたCLOUD — ClaudeがMicrosoft Foundry(Azure)で一般提供され、Azureネイティブで利用できます
記事一覧/Cowork
Cowork/2026-07-02上級

夜の同じ分に何本着火しているか — Cowork スケジュールタスクの衝突を cron から平らにする設計

Cowork のスケジュールタスクが同じ時刻に集中して共有リソースを奪い合う問題を、cron 式から着火時刻を展開して衝突と並行度を数え、プレミアム枠を動かさずにピークだけを削る貪欲オフセットで平準化する設計を、動くコードと実測 before/after で解説します。

Cowork32スケジュールタスク17cron2自動化66並行処理2

プレミアム記事

先日、夜の 20:00 ちょうどに複数のタスクが一斉に着火して、共有している /tmp の空き容量とレート上限を奪い合った結果、後から起動した処理が clone の途中で息切れした夜がありました。私自身、複数サイトの自動投稿を Cowork のスケジュールタスクに任せているのですが、一本ずつ追加していくうちに「気づけば夜の同じ時刻に何本も重なっていた」という状態に、いつの間にか陥っていたのです。

厄介なのは、個々のタスクは正常に見えることです。cron はそれぞれ意図どおりに動いています。問題は「全部を並べたとき、ある一分に何本が同時に走り出すか」という、俯瞰しないと見えない性質のほうにありました。以下では、その俯瞰を人間の勘ではなく cron 式から機械的に取り出し、収益に効くプレミアム枠は一切動かさずにピークだけを削る、という順序で、個人開発の現場から設計していきます。

cron を「時と分」に展開して、同じ分に着火する本数を数える

まず必要なのは「どのタスクが、1日のうちどの分に着火するか」を全タスクぶん展開することです。Cowork のスケジュールタスクは 分 時 日 月 曜日 の 5 フィールド cron で表現されるので、そこから着火分(0〜1439 の通し番号)を取り出します。

実運用の cron はほとんどが数値かカンマ列(例: 0 9,20 * * *)なので、まずはそこに絞ると読み間違いが減ります。範囲やステップを足すのは、この土台が正しく動いてからで十分です。

type Task = { id: string; cron: string; durationMin: number; protected: boolean };
 
// "0,30" や "9,20" のようなフィールドを数値配列に展開する
function parseField(field: string, min: number, max: number): number[] {
  if (field === "*") {
    const all: number[] = [];
    for (let v = min; v <= max; v++) all.push(v);
    return all;
  }
  return field.split(",").map((s) => {
    const n = Number(s);
    if (!Number.isInteger(n) || n < min || n > max) {
      throw new Error(`cron フィールドの値が不正です: "${s}"`);
    }
    return n;
  });
}
 
// 1日分の着火時刻(分の通し番号 0..1439)を返す。
// 日・月・曜日は「毎日走る」前提でここでは無視し、まず時と分だけで
// 日次の並行度を見る(多くの生成タスクが毎日か特定曜日のため)。
function fireMinutes(cron: string): number[] {
  const parts = cron.trim().split(/\s+/);
  if (parts.length !== 5) {
    throw new Error(`cron のフィールド数が5ではありません: "${cron}"`);
  }
  const [mField, hField] = parts;
  const minutes = parseField(mField, 0, 59);
  const hours = parseField(hField, 0, 23);
  const out: number[] = [];
  for (const h of hours) for (const m of minutes) out.push(h * 60 + m);
  return [...new Set(out)].sort((a, b) => a - b);
}

これで各タスクの着火分が得られたので、「同じ分に何本着火するか」の地図を作ります。

// 着火分 -> その分に起動するタスク ID の一覧
function collisionMap(tasks: Task[]): Map<number, string[]> {
  const map = new Map<number, string[]>();
  for (const t of tasks) {
    for (const fm of fireMinutes(t.cron)) {
      const list = map.get(fm) ?? [];
      list.push(t.id);
      map.set(fm, list);
    }
  }
  return map;
}
 
function toHHMM(minute: number): string {
  const h = String(Math.floor(minute / 60)).padStart(2, "0");
  const m = String(minute % 60).padStart(2, "0");
  return `${h}:${m}`;
}

collisionMap のうち値の長さが 2 以上の分だけを拾えば、「同じ分に着火するタスク群」が一覧になります。ここで私が最初につまずいたのは、この「同時着火の本数」を並行度そのものだと思い込んでいたことでした。実際にはこれは入口にすぎません。

「重なり」と「同時に走っている数」は別物です

着火が同じ分でなくても、実行に時間がかかるタスク同士は走行中に重なります。19:45 に始まる処理が 20 分かかれば、20:00 ちょうどに始まる別の処理と 20:00〜20:05 で並走します。つまり本当に見たいのは「着火の衝突」ではなく「ある瞬間に何本が同時に走っているか(並行度)」です。

各タスクの実行を [着火分, 着火分 + 実行分) の区間として並べ、掃引線(sweep line)で最大並行度を求めます。ここに一つ、見落としやすい落とし穴があります。同じ分で「終了」と「開始」が同時に起きたとき、それを重複と数えてしまうと並行度を過大評価します。隣り合っているだけの処理を、重なっていると誤検出してしまうのです。

type Interval = { start: number; end: number; id: string };
 
function runIntervals(tasks: Task[]): Interval[] {
  const intervals: Interval[] = [];
  for (const t of tasks) {
    for (const fm of fireMinutes(t.cron)) {
      intervals.push({ start: fm, end: fm + t.durationMin, id: t.id });
    }
  }
  return intervals;
}
 
function peakConcurrency(intervals: Interval[]): { peak: number; atMinute: number } {
  const events: { minute: number; delta: number }[] = [];
  for (const iv of intervals) {
    events.push({ minute: iv.start, delta: +1 });
    events.push({ minute: iv.end, delta: -1 });
  }
  // 同一分では終了(-1)を開始(+1)より先に処理する。
  // こうしないと「20:05 に終わる処理」と「20:05 に始まる処理」を
  // 同時走行と誤って数えてしまう。
  events.sort((a, b) => a.minute - b.minute || a.delta - b.delta);
 
  let cur = 0;
  let peak = 0;
  let atMinute = 0;
  for (const e of events) {
    cur += e.delta;
    if (cur > peak) {
      peak = cur;
      atMinute = e.minute;
    }
  }
  return { peak, atMinute };
}

delta の昇順ソートで -1+1 より先に来る点が肝です。区間を半開区間 [start, end) で扱っているのと辻褄が合い、隣接する処理を並走と数えません。この落とし穴を回避するには、必ず終了イベントを先に処理します。この一行の順序を間違えると、ピークが実態より 1〜2 本多く見えてしまい、必要のないタスクまで動かす判断につながります。本番運用に足す計測ほど、こうした境界条件で静かにズレていないかを疑う価値があります。

ここまでお読みいただきありがとうございます。

この記事の続きを読む

この先には、実装コードやベンチマーク結果など、実務でお役に立てる内容をご用意しています。このサイトは広告を掲載しておらず、サーバーや開発にかかる費用はメンバーの皆様のご支援で成り立っています。もしお役に立てていましたら、ご支援いただけますと大変ありがたいです。

この記事で得られること
全タスクの cron を1日分に展開し、同一分に着火する本数と時間帯ごとの並行度を機械的に検出する TypeScript 実装
「重なり」と「同時に走っている数」を区別する掃引線アルゴリズム。終了イベントを先に処理してピークを誤検出しない書き方まで
プレミアム枠は固定したまま、可変タスクの着火分だけをずらしてピークを削る貪欲オフセットと、その before/after の実測
Stripe による安全な決済 · いつでもキャンセル可能

この記事を購入する

この先の内容をすべてお読みいただけます。一度のご購入で、いつでも何度でもアクセスできます。このサイトは広告を掲載しておらず、皆さまのご支援がサーバー費用などの運営を支えています。

または
メンバーシップなら全記事が読み放題 →
シェア

お読みいただきありがとうございます

Claude Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

関連記事

Cowork2026-06-13
Cowork スケジュールタスク運用の実際 — 朝のダイジェストと週次レポートを無人で回すまで
Claude Cowork のスケジュールタスクで定期実行・リマインダー・自動レポートを設定する手順を、cron 式の基本から無人実行に耐えるプロンプト設計、複数タスクの時間帯設計まで、運用で掴んだ勘所とともにお届けします。
Cowork2026-07-01
上流タスクが今日ちゃんと動いたかを、下流タスクが自分で確かめる — 無人スケジューラの完了台帳と依存バリア
無人スケジューラには依存関係の概念がないため、朝の参照データ更新が静かに失敗しても、昼の生成タスクは前日の残り物でそのまま走り続けます。上流の完了を原子的に台帳へ記録し、下流が実行前に前提を検証する依存バリアの設計を、動くTypeScriptと私自身の運用体験で解説します。
Cowork2026-06-30
3日前のローカルミラーで判断していた — 無人タスクが古い作業コピーを信じて二重作業する事故を止める
速度のために使い回す永続クローンは、いつの間にかリモートとずれます。同期を確かめないまま「この記事はもう直したか」を読みに行くと、無人タスクは古い木を信じて二重編集や空振り成功を起こします。HEAD 突き合わせと書き込み可否のプリフライト、自己修復の再クローンをbashで実装します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →