アプリ・Webサービス・業務ツールの制作を、証拠分析→確定的な初稿→要件定義→体験設計→機能分解→実装→品質ゲート→リリース判定の手順ゲート制で進めるスキル。質問で要件を埋めるのではなく、依頼文・既存コード・資料・ログから最有力案を選び、動く成果物を先に出して差分で改善する。ユーザーが「アプリを作りたい」「ツールを作って」「〜を自動化したい」「システム化したい」「要件定義」「仕様を決めたい」「UI/UXを設計して」「体験を良くしたい」「機能を洗い出して」「MVPを決めたい」「品質チェック」「リリースしていいか判断して」などと言ったら必ず使用する。外部データの取込・マスタ・締め処理を伴う業務システムでは references/data-lifecycle.md も併用する。新規・既存を問わずアプリの制作・改善・リニューアルで使用する。
durable-objects
Cloudflare Durable Objects の実装とレビューに使用する。チャットルーム、マルチプレイ、予約システムなどの状態を持つ協調処理、RPC methods、SQLite storage、alarms、WebSockets、Workers統合、wrangler設定、Vitestでのテストを扱う。
事前学習の知識より最新のCloudflare docsの取得を優先する。
含まれるファイル(4)
- SKILL.md7.4 KB
- references/rules.md8.3 KB
- references/testing.md6.4 KB
- references/workers.md7.4 KB
SKILL.md(原文)
インストールする前に、エージェントに与えられる指示の中身を確認できます。
本ファイルは cloudflare/skills(Apache-2.0)を基に改変しています。詳細は リポジトリルートの ATTRIBUTION.md を参照。
Durable Objects の実装・レビュー
Durable Objectsを使い、Cloudflare edge上に状態を持つ協調型アプリケーションを実装する。
最新情報の取得先
Durable Objects APIsや設定は更新されるため、事前学習の知識より最新の公式情報を優先する。API signature、設定項目、制限値を記憶だけで断定しない。
正本は cloudflare Skill の「最新情報の取得先」(docs MCP 第一手段、不通時の復旧、workers-types / config-schema の取得方法)。ここには本Skill固有の取得先だけを書く。
| 取得先 | 取得方法 | 使う場面 |
|---|---|---|
| Cloudflare docs (MCP) | cloudflare-docs MCPで durable-objects + API名(sql.exec、setAlarm 等)を検索 | 既定の第一手段。API reference、制限値、compatibility date要件 |
| Durable Objects docs (Web) | https://developers.cloudflare.com/durable-objects/(api/、best-practices/、examples/) | MCP不通時 |
実装前に該当ページとプロジェクトのWrangler config schema / Workers typesを確認する。本Skillと最新の公式情報が食い違う場合は公式情報を優先し、不明なAPIや設定を推測で補わない。
使う場面
- 協調処理のために新しいDurable Object classを作る
- RPC methods、alarms、WebSocket handlersを実装する
- 既存のDOコードをBest Practicesに照らしてレビューする
wrangler.jsonc/wrangler.tomlにDO bindingsとmigrationsを設定する@cloudflare/vitest-pool-workersでテストする- sharding戦略やparent-child関係を設計する
詳細リファレンス
./references/rules.md- 中核ルール、storage、concurrency、RPC、alarms./references/testing.md- Vitest設定、unit/integration tests、alarm testing./references/workers.md- Workers handlers、types、wrangler config、observability
検索キーワード: blockConcurrencyWhile, idFromName, getByName, setAlarm, sql.exec
中核原則
Durable Objectsが適する用途
| 必要な性質 | 例 |
|---|---|
| 複数利用者の協調 | チャットルーム、マルチプレイ、共同編集 |
| Strong consistency | 在庫、予約システム、ターン制ゲーム |
| entity単位のstorage | Multi-tenant SaaS、利用者ごとのデータ |
| 持続接続 | WebSockets、real-time notifications |
| entity単位の予定処理 | 契約更新、ゲームのtimeout |
使わない用途
- statelessなrequest handling、plain Workersで十分な処理
- 最大限のglobal distributionが優先される処理
- 互いに独立したhigh fan-out requests
実装早見表
Wrangler設定
// wrangler.jsonc
{
"durable_objects": {
"bindings": [{ "name": "MY_DO", "class_name": "MyDurableObject" }]
},
"migrations": [{ "tag": "v1", "new_sqlite_classes": ["MyDurableObject"] }]
}
基本パターン
import { DurableObject } from "cloudflare:workers";
export interface Env {
MY_DO: DurableObjectNamespace<MyDurableObject>;
}
export class MyDurableObject extends DurableObject<Env> {
constructor(ctx: DurableObjectState, env: Env) {
super(ctx, env);
ctx.blockConcurrencyWhile(async () => {
this.ctx.storage.sql.exec(`
CREATE TABLE IF NOT EXISTS items (
id INTEGER PRIMARY KEY AUTOINCREMENT,
data TEXT NOT NULL
)
`);
});
}
async addItem(data: string): Promise<number> {
const result = this.ctx.storage.sql.exec<{ id: number }>(
"INSERT INTO items (data) VALUES (?) RETURNING id",
data
);
return result.one().id;
}
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const stub = env.MY_DO.getByName("my-instance");
const id = await stub.addItem("hello");
return Response.json({ id });
},
};
必須ルール
- coordination atomで分ける - 1つのglobal DOに集約せず、chat room / game / userごとに1 DOとする
- deterministic routingに
getByName()を使う - 同じ入力は同じDO instanceへ導く - SQLite storageを使う - migrationsで
new_sqlite_classesを設定する - constructorで初期化する -
blockConcurrencyWhile()はschema setupだけに使う - RPC methodsを使う -
fetch()handlerで代用しない。compatibility dateの要件は実装時に最新docsで確認する - persistを先、cacheを後にする - in-memory stateを更新する前にstorageへ書き込む
- alarmは1 DOに1つ -
setAlarm()は既存alarmを置き換える
禁止パターン
- 1つのglobal DOで全requestsを処理する。bottleneckになる
- 毎requestで
blockConcurrencyWhile()を使いthroughputを落とす - 重要なstateをmemoryだけに保持する。eviction / crashで失われる
- 関連するstorage writesの間に
awaitを挟みatomicityを壊す fetch()や外部I/OをまたいでblockConcurrencyWhile()を保持する
Stubの作成
// Deterministic - preferred for most cases
const stub = env.MY_DO.getByName("room-123");
// From existing ID string
const id = env.MY_DO.idFromString(storedIdString);
const stub = env.MY_DO.get(id);
// New unique ID - store mapping externally
const id = env.MY_DO.newUniqueId();
const stub = env.MY_DO.get(id);
Storage操作
// SQL (synchronous, recommended)
this.ctx.storage.sql.exec("INSERT INTO t (c) VALUES (?)", value);
const rows = this.ctx.storage.sql.exec<Row>("SELECT * FROM t").toArray();
// KV (async)
await this.ctx.storage.put("key", value);
const val = await this.ctx.storage.get<Type>("key");
Alarmsの実装
// Schedule (replaces existing)
await this.ctx.storage.setAlarm(Date.now() + 60_000);
// Handler
async alarm(): Promise<void> {
// Process scheduled work
// Optionally reschedule: await this.ctx.storage.setAlarm(...)
}
// Cancel
await this.ctx.storage.deleteAlarm();
テストの最小例
import { env } from "cloudflare:test";
import { describe, it, expect } from "vitest";
describe("MyDO", () => {
it("should work", async () => {
const stub = env.MY_DO.getByName("test");
const result = await stub.addItem("test");
expect(result).toBe(1);
});
});
検証と報告
- プロジェクト既存のtypecheck / testコマンドと
@cloudflare/vitest-pool-workersの対象テストを実行する。実行できない検証は未実施理由を明記する。 - bindings、migrations、class名、生成された
Env型が一致することを確認する。新規のremote migrationや破壊的変更は、ユーザーの明示依頼がなければ実行しない。 - 最終報告は「選んだDO分割単位」「設定・実装の変更」「実行した検証と結果」「未検証項目・残るリスク」の順で簡潔に日本語で示す。
レビュー
まだレビューはありません。使ってみた感想をお寄せください。
同じリポジトリのスキル
概要と使いどころ
Webアプリの準備→要件定義→設計→実装→公開→品質ゲートを実行する内部オーケストレーター。Claude Codeの /build-app /improve-app、Codexの $build-app / $improve-app から明示的に委譲された場合、custom agent起動時、または利用者が $app-orchestrator を明示した場合だけ使用する。一般のアプリ相談から暗黙起動しない。
run-extract-blueprint が生成した章別ブループリントの忠実性を独立 context で評価したいとき、事実/推測区別と粒度と被覆を検証し draft_hash に束縛した PASS/FAIL verdict をローカル品質ゲート (C01 の周回内の受入判定・差し戻し) へ渡したいときに使う。
確認点で利用者が見る深さを選んだあと打ち合わせ資料を作り手とは別の目で確かめたいとき、正確さ・言葉・見た目・シンプルさの指摘を資料の編集なしで受け取りたいときに使う。
生成した handout 資料が初心者に伝わるか読みやすさレビューを依頼したいとき、独立 context のレビュアーから指摘と根拠つきの verdict を回収したいときに使う。
Notion ページを描画する直前に粒度を検証したいとき、info-collector-agent ページと同等の section 充足度を section_canonical_map 基準で機械検証したいときに使う。