story-generator について
MkDocs Materialの教材向けに、科学・数学・技術の貢献者や架空の事例を題材とする教育用グラフィックノベルを作るスキルです。コマ数を設定でき、画像プロンプトの作成やテキスト画像生成APIによる画像生成にも対応します。
主な機能
- 01構成に沿ったグラフィックノベルの作成
- 02--panels N によるコマ数の設定
- 03物語文と画像プロンプトの作成
- 04表紙と各コマの画像生成
- 05教材に沿ったストーリー案の作成
活用シーン
- 01教材に歴史上の人物の物語を追加
- 02架空の事例で概念を説明
- 03教材のテーマに合うストーリー案を作成
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ dmccreary/ ibook-skills --skill story-generatorインストール後、Claude Code で/story-generatorを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
references/index-template.mdscripts/fix-references.pygenerate-images.pyuncomment-images.shverify-images.py詳細
ストーリー生成ツール
このスキルは、MkDocs Material で構築されたインテリジェントな教科書向けに、科学、数学、技術への主要な貢献者を題材にした完全なグラフィックノベルの物語と、架空のケーススタディを生成します。デフォルトの物語の長さは**表紙に加えて12パネル(合計13枚の画像)**ですが、パネル数は設定できます。シンプルな物語は6~8パネルで表現でき、総合的な物語は16パネルまで設定できます。各パネルにはその下に物語の段落があり、折りたたみ可能な<details>ブロック内に詳細な画像生成プロンプトが含まれます。
2026-04のスキル更新により、このスキルでは、Google GeminiやOpenAI gpt-image-1を含む複数のテキスト画像生成APIを使用して、16:9(1344×768)で各パネル画像(表紙1枚+Nパネル)をネイティブに自動生成できるようになりました。正確なテキスト配置を含む高品質画像の現在の費用は、画像1枚あたり約**$0.039**です(デフォルトの13枚の物語では約$0.51、6パネルの物語では約$0.27)。詳しくは、以下の「手順3.5:画像の生成」をご覧ください。
--panels N 引数
このスキルでは、物語の番号付きパネル数を指定する省略可能な--panels N引数を受け付けます。表紙画像は常に別途作成されるため、物語の画像は合計N + 1枚です。
- デフォルト:
--panels 12(従来のグラフィックノベルの展開) - 推奨範囲: 4~16
- 4未満: 展開を描く余地がありません。そもそも物語が必要かどうか検討してください
- 16超: 読者は多くの画像に注意を払うことになります。2つの物語に分けてください
Nの選び方:
| 物語の構成 | 推奨N |
|---|---|
| 単一の手法、変更前/変更後のみ | 6 |
| 直線的な発見(監査 → 修正 → 結果) | 7~8 |
| 謎+種明かし+複数段階の修正 | 9 |
| 歴史上の人物の生涯を描く完全な展開 | 12(デフォルト) |
| 複数章にわたる総合的な内容、またはまとめのモンタージュ | 14~16 |
ユーザーによる呼び出し方:
ユーザーは次のように入力します。
/story-generator The Cache That Wasn't --panels 8
ユーザーの呼び出しに--panels Nが含まれている場合は、その後のワークフロー全体でNを正式なパネル数として扱います。--panels引数が指定されていない場合は、デフォルトの12を使用します。
スクリプトを変更せずに動作する理由:
generate-images.pyとverify-images.pyはどちらも、index.md内の<details>...Image Prompt...</details>ブロックを数えて、生成または検証する画像の数を決定します。12を固定値としていません。index.mdに記述したパネル数に応じてスクリプトが画像を生成・検証するため、スクリプト側でフラグを指定する必要はありません。
このスキルを使用する場面
次のような場合に、このスキルを使用します。
- ユーザーが科学者、数学者、エンジニア、その他の歴史上の人物を題材にした新しいグラフィックノベルの物語を求めている
- インテリジェントな教科書の「物語」/「歴史」セクションに物語を追加する
- 画像プロンプトを埋め込んだ教育用の物語コンテンツを作成する
- ユーザーが歴史上の人物について「物語」「グラフィックノベル」「ナラティブ」と言及している
- ユーザーが「グラフィックノベルの物語のアイデアをいくつか出して」と言っている — 「ストーリーアイデア生成」ワークフローを開始します(以下を参照)
ストーリーアイデア生成
ユーザーが**「グラフィックノベルの物語のアイデアをいくつか出して」と言った場合は、現在の教科書の主題に合わせて厳選した、短編グラフィックノベルのアイデア一覧を生成します。結果はdocs/stories/story-ideas.mdに保存します。各アイデアには、物語の自然な構成に合わせて選んだ推奨パネル数**(通常は6~12)を含めてください。上記の「パネル数の目安」を参照してください。すべてをデフォルトの12にするのは避けてください。6~8パネルにまとめた物語のほうが、冗長な12パネルの物語より優れていることがよくあります。
ワークフロー
ステップ 1:教科書の主題を分析する
次のファイルを読み、教科書のテーマ、対象読者、主なテーマを把握します。
docs/course-description.md— コース名、説明、対象読者、学習目標mkdocs.yml— サイト名とナビゲーション構造(追加の背景情報)docs/learning-graph/learning-graph.csv(存在する場合)— 概念の一覧と分類カテゴリ
次の項目を抽出します。
- 主題分野(例:認識論、幾何学、関数、生物学)
- 対象読者(例:IB の生徒、AP の生徒、9~12 年生)
- コースの説明と学習グラフに含まれる主なテーマと概念
ステップ 2:ストーリーのアイデアを作成する
教科書の主題に関連する15~20 件のストーリーアイデアを作成します。それぞれ、推奨パネル数を 6~12(総括・最終課題となるストーリーの場合は最大 16)とするミニ・グラフィックノベルのコンセプトにします。
多様性に関する要件 — 次のすべてのカテゴリを含めます。
- 歴史上の人物 — 教科書のテーマに直接関連する業績を残した科学者、数学者、技術者、発明家、哲学者
- 多様なイノベーター — 分野に大きく貢献した、過小評価されているグループ(女性、有色人種、グローバルサウスの貢献者など)の人々
- 科学と教条の対立 — 証拠と理性を用い、宗教的教条、政治的正統主義、または制度的抵抗に異議を唱えた人々の物語
- 誤情報との闘い — 危険な誤りを暴き、科学と批判的思考で世界をより良くした人々の物語(例:レイチェル・カーソンによる『沈黙の春』での DDT の危険性の告発、イグナーツ・ゼンメルワイスによる手洗いの提唱)
- 知られざる英雄 — 基礎を築いたものの、見過ごされてきた、あまり知られていない貢献者
- 現代の人物 — 現在、または近年にこの分野を発展させている人々
各ストーリーアイデアに含める項目:
- タイトル — 魅力的で簡潔なタイトル(例:「沈黙の春 — レイチェル・カーソンの DDT との闘い」)
- 主題 — フルネーム、生没年、国名(架空のケーススタディを題材にする場合は舞台)
- テーマ — 物語の中心となるテーマ(例:「産業界に異議を唱える勇気」「拒絶されても続ける粘り強さ」)
- 教科書との関連 — この物語が教科書の特定の概念や章とどう関係するか
- パネル数 — 推奨パネル数(6~16)と、その長さにする理由を 1 行で記載します。パネル数の目安:単一の手法を扱うストーリーは 6、発見までを時系列で描くものは 8、謎と解決を扱うものは 9、生涯全体を描くものは 12、複数の要素を統合するモンタージュは 14~16 です。ユーザーはスキルの実行時に
--panels Nを指定して変更できます。 - あらすじ — 推奨パネル数に沿ったストーリー展開を 2~3 文で説明します
- この物語が心に響く理由 — 若い読者が共感できる理由を 1 文で説明します
ステップ 3:書式を整えて保存する
次の形式でストーリーアイデアを docs/stories/story-ideas.md に保存します。
# Story Ideas for {Book Title}
These mini-graphic novel ideas are designed to inspire young
readers by connecting the subject matter of this textbook to
the real people who shaped the field. Each story can be
generated using the `/story-generator` skill, with the
suggested panel count or your own override via `--panels N`.
## Selection Criteria
Stories were selected for:
- **Relevance** — direct connection to the textbook's key concepts
- **Diversity** — range of backgrounds, cultures, genders, and time periods
- **Inspiration** — themes that resonate with the target audience
- **Drama** — compelling narrative arcs with conflict and resolution
## Story Ideas
### 1. {Title}
| | |
|---|---|
| **Subject** | {Full Name} ({birth}–{death}), {country} |
| **Theme** | {Central narrative theme} |
| **Connection** | {How it connects to specific textbook concepts} |
| **Panels** | **{N}** — {one-line rationale for that length} |
{2-3 sentence synopsis}
*Why this inspires:* {1 sentence}
---
### 2. {Title}
...
## How to Generate a Story
To turn any of these ideas into a full graphic novel with
generated images, use:
> /story-generator {Story Title} --panels {N}
Provide the subject's name (and optionally `--panels N` to
override the suggested count) and the skill will handle the
rest — writing the narrative, creating image prompts, and
optionally generating all panel images via multiple
text-to-image APIs (Google Gemini, OpenAI gpt-image-1, or
others). Current cost for high-quality images with accurate
text placement is
approximately **$0.039 per image**, so $0.039 × (N + 1) per
story — about $0.27 for 6 panels, $0.51 for 12 panels.
ステップ 4:ナビゲーションを更新する
ストーリーアイデアのページを Stories セクションの下に mkdocs.yml で追加します。
- Stories:
- Overview: stories/index.md
- Story Ideas: stories/story-ideas.md
# ... individual stories follow
例:知識の理論
知識の理論の教科書では、ストーリーのアイデアとして次のようなものが考えられます。
- 「沈黙の春」 — DDTの危険性を明らかにするために闘ったレイチェル・カーソン(科学対産業界の誤情報)
- 「星界の報告」 — ガリレオの望遠鏡と、天動説の教義に立ち向かう闘い
- 「死を洗い流す」 — 医学界からの拒絶に抗して手洗いを提唱したイグナーツ・ゼンメルワイス
- 「秘密の解読」 — DNAのX線結晶構造解析に取り組みながら、その功績が認められなかったロザリンド・フランクリン
- 「ランプの貴婦人」 — 統計的証拠を用いて軍病院を改革したフローレンス・ナイチンゲール
- 「絵で考える」 — ニューロダイバージェントな知覚を通じて、動物の取り扱い方法を再設計したテンプル・グランディン
- 「ワクチンの開発者」 — 公衆の恐怖や迷信を乗り越えて天然痘ワクチンを開発したエドワード・ジェンナー
- 「コレラの地図」 — 水系感染による疾病の伝播を証明したジョン・スノウのデータ可視化
- 「大胆な仮説」 — 何十年も否定された後に正しさが証明された、アルフレート・ヴェーゲナーの大陸移動説
- 「隠された人物たち」 — 人種の壁がある中で、宇宙飛行士を宇宙へ送り出すための計算を行ったキャサリン・ジョンソン
各ストーリーは、ティーンエイジャーや若年成人の読者を惹きつけるように設計された、一貫した構成に沿って進みます。
必須要素
- YAML Frontmatter — タイトル、説明、Open Graph画像のパス
- カバー画像 —
<details>ブロック内に詳細な生成プロンプトを記載 - ナラティブプロンプト — ストーリー全体の背景となる文脈
- プロローグ — 主題の重要性を紹介する導入
- 登場人物の独立した紹介 — 名前のある登場人物全員を、ナラティブで初めて言及する前に、文章で紹介
- 12パネル — それぞれにナラティブテキスト、画像プレースホルダー、画像プロンプトを含める
- エピローグ — 教訓の表(課題/対応/今日への教訓)
- 行動喚起 — 読者につながる、心を動かすメッセージ
- 引用 — 主題に関する、記憶に残る引用を2~3件
- 参考資料 — 実際にアクセスできるURLを5件(最初の3件はWikipedia、その後に二次資料)。
(PLACEHOLDER)は絶対に使用しないでください。
完全な構成のテンプレートは references/index-template.md にあります。
YAML Frontmatter
ソーシャルメディアでの共有には、Open Graphプロトコルを使用します。
---
title: <Catchy Title> - <Subject Name>'s <Theme>
description: A graphic-novel story of how <brief description>...
image: /stories/{story-dir-name}/cover.png
og:image: /stories/{story-dir-name}/cover.png
twitter:image: /stories/{story-dir-name}/cover.png
social:
cards: false
---
{story-dir-name} は、ケバブケースのディレクトリ名です。
長さの目安:
- タイトル:最大60~70文字(これより長いタイトルはソーシャルメディアで省略されます)
- 説明:155~200文字(簡潔で印象的な文を1~2文)
画像プロンプトの要件
画像プロンプトには、すべて以下を指定してください。
- すべてのプロンプト本文の先頭に、パネル識別行を記載する:
- カバー:(This is the Cover Image. Do not include this label in the image.)
- パネル:(This is Panel N. Do not include the panel number in the image.)。Nはパネル番号です
- 横長の16:9形式(
generate-images.pyスクリプトがAPI設定を通じて指定するため、プロンプト内のテキストは重複しますが、問題ありません) - 時代に適したアートスタイル(下記の「アートスタイルの参考表」を参照)
- 具体的な身体的特徴や服装を含む登場人物
- 年と場所を含む具体的な舞台設定
- カラーパレットの指示
- 感情的なトーンと雰囲気
- ありきたりな出力を避け、画像生成を導くための具体的な視覚的詳細を、プロンプトごとに少なくとも6つ
- 次の文で終える:
Generate the image immediately without asking clarifying questions.
generate-images.py スクリプトは、ストーリーの index.md から <details><summary>Image Prompt</summary>...</details> ブロックを直接解析するため、ブロックの構造が重要です。HTMLの形を変更しないでください。
ワークフロー
歴史上の人物を扱うストーリーもあれば、架空の設定や概念を扱うストーリーもあります。どちらの場合もワークフローは同じですが、調査と執筆のプロセスは多少異なります。
ステップ 1:情報を集め、物語を計画する
執筆する前に、次の情報を特定します。
- 主題となる人物のフルネームと生没年
- 国と歴史上の時代
- 主な発見、貢献、または人生の出来事
- 中心となるテーマ(例:「失敗を乗り越える粘り強さ」「ほかの人には見えなかったものを見る」)
- その時代にふさわしいアートスタイル
- N 枚のパネル(既定値は N=12)の軸となる、人生の重要な出来事を 3〜5 件(フィクションの場合は物語の展開)。2〜3 枚のパネルにつき 1 つの展開を目安にします。通常、6 枚の物語なら展開は 3 つ、12 枚の物語なら 4〜6 つです。
--panels Nが指定されている場合は、ここでもその N を使用します。
ステップ 2:ストーリーのディレクトリを作成する
mkdir -p docs/stories/{story-dir-name-in-kebab-case}
ディレクトリ名にはケバブケース(小文字とハイフン)を使用します:ada-lovelace、rene-descartes、marie-curie。スペースやアンダースコアは使用しないでください。
ステップ 3:ストーリーを書く
references/index-template.md のテンプレートに従って、docs/stories/{story-dir-name}/index.md を作成します。
主な規則:
- 番号付きパネル N 枚に表紙 1 枚を加え、画像は合計 N + 1 枚です(既定値は N = 12、
--panels Nで変更できます) - パネル番号は
panel-01からpanel-NNまで連続させます。欠番や余分なパネルを作らないでください - 各パネル識別行には、このストーリーの実際の N を使って「panel X of N」と記載します(例:6 パネルのストーリーで「panel 3 of 8」とするのは誤りです。すべてのプロンプトで、分母はパネルの総数と一致させてください)
- すべての画像参照には
.png拡張子を使用します - パネル画像のプロンプトは、
<details><summary>Image Prompt</summary>...</details>ブロックで囲みます - 表紙画像のプロンプトは、
<details><summary>Cover Image Prompt</summary>...</details>ブロックで囲みます - すべてのプロンプト本文は、パネル識別行から始めます(「画像プロンプトの要件」を参照)
- 物語の段落は各パネルの画像の下に記載し(
<details>ブロック内には入れないでください) - すべてのストーリーは独立した作品として扱います。物語本文で登場人物の名前が初めて出る前に、その人物のフルネームと、平易な言葉で表した役割または物語との関係を示す短い文を加えてください。繰り返し登場する人物も、ストーリーごとに紹介し直します。フロントマター、タイトル、画像プロンプト、キャプション、キャラクターシート、および以前のストーリーは対象外です。名前のあるマスコットや案内役も、物語本文で初めて登場する前に同じように紹介してください。
- 参考資料:実在する URL を 5 件記載し、
(PLACEHOLDER)は使用しないでください。下記の「参考資料のガイドライン」を参照してください
references/index-template.md のテンプレートには、標準的な 12 パネルのレイアウトが記載されています。 それより短い、または長いストーリーでは、パネルごとの同じ形式に従いつつ、N 枚目で終えてください。12 枚に達するためだけに埋め草のパネルを追加しないでください。冗長な 12 パネルより、まとまりのある 6 パネルのストーリーのほうが優れています。
ステップ 3.5:画像を生成する(任意ですが推奨)
Markdown の作成後、scripts/generate-images.py を使って N + 1 枚のパネル画像を自動生成します。このスクリプトは index.md 内の <details>...Image Prompt...</details> ブロックからパネル数を自動検出するため、スクリプトに --panels N を渡す必要はありません。Markdown に記述した内容がそのまま生成されます。
前提条件:
-
Python パッケージ:
pip install google-genai -
API キー — https://aistudio.google.com/apikey で無料のキーを取得し、次のように設定します:
export GEMINI_API_KEY="your-key-here"設定を永続化するには、
~/.zshrcまたは~/.bashrcに追加してください。無料枠では、クレジットカードも請求先アカウントも必要ありません。
初回実行 — 追加の 12 枚でクレジットを消費する前に、カバー画像を確認します:
python3 ~/.claude/skills/story-generator/scripts/generate-images.py \
docs/stories/{story-dir-name} --first-only
カバー画像のみを生成し、sips で 16:9 であることを確認します。アスペクト比が正しくない場合は自動的に中断します。カバー画像を目視で確認し、希望するアートスタイルや構図になっているか確かめてください。問題なければ、全体の生成に進みます。
全画像の生成:
python3 ~/.claude/skills/story-generator/scripts/generate-images.py \
docs/stories/{story-dir-name}
このコマンドは、ネイティブ解像度 1344×768(16:9)で N + 1 枚の画像(カバー + N 枚のパネル)をすべて生成します。10 RPM のレート制限での所要時間は、概算で 6 × (N + 1) 秒 です。標準の 12 パネルのストーリーでは約 90 秒、6 パネルのストーリーでは約 45 秒です。画像はそれぞれ生成直後に検証されます。
便利なフラグ:
| フラグ | 用途 |
|---|---|
--first-only | カバー画像のみを生成します(アスペクト比とスタイルの確認) |
--skip-existing | PNG ファイルがすでに存在する画像をスキップします(再試行時も安全です) |
--rpm N | デフォルトの 10 RPM のレート制限を上書きします(割り当て量が多い有料枠で使用します) |
--aspect-ratio W:H | デフォルトの 16:9 を上書きします。対応する値:21:9、16:9、4:3、3:2、1:1、9:16、3:4、2:3、5:4、4:5 |
スクリプトによって生成されるもの:
docs/stories/{story-dir-name}/cover.pngとpanel-01.pngからpanel-12.pngまでの PNG ファイル- 実行メタデータ、概要の合計、画像ごとの表、プロンプトの抜粋を記録した、ストーリーごとの Markdown ログ
logs/{story-dir-name}-{YYYY-MM-DD}.md - 画像ごとの JSONL 監査行(タイムスタンプ、トークン数、計算されたコスト)を
logs/image-generation-usage.jsonlに追記
画像生成に失敗した場合:
このスクリプトは安全性フィルターによる失敗や API の例外を捕捉し、理由(finish_reason と安全性評価を含む)をログに記録してから次の画像の生成に進みます。画像の失敗はスキップされ、処理全体は中断されません。実行後、--skip-existing を指定して再実行すると、失敗した画像だけを再試行できます。安全性フィルターにかかるプロンプトを調整する方法については、以下の「Safety Filter Patterns」セクションを参照してください。
ステップ 4:画像を検証する
生成後、検証スクリプトを実行して、すべての画像が存在し、アスペクト比が正しいことを確認します:
python3 ~/.claude/skills/story-generator/scripts/verify-images.py \
docs/stories/{story-dir-name}
これは読み取り専用の監査で、確認のみを行い、変更は行いません。終了コード 0 は問題なし、1 は問題ありを示します。特に次の用途に便利です:
- 以前の Antigravity ワークフローで生成された古い正方形画像の検出
- 一部のみ実行した後、13 枚すべてのパネルが揃っていることの確認
- コミット前フック
ステップ 5:ナビゲーションに追加する
mkdocs.yml を編集し、対象者の生年順にストーリーを追加します:
- Stories:
- Overview: stories/index.md
- <Subject Name> - <Title>: stories/<subject-name>/index.md
年代順の例(プロジェクトに合わせて調整してください):
- アルキメデス(紀元前 287 年)
- ガリレオ(1564 年)
- デカルト(1596 年)
- ニュートン(1643 年)
- オイラー(1707 年)
- フーリエ(1768 年)
- ファラデー(1791 年)
- ラブレース(1815 年)
- マクスウェル(1831 年)
- テスラ(1856 年)
- マリー・キュリー(1867 年)
- アインシュタイン(1879 年)
- ネーター(1882 年)
- ラマヌジャン(1887 年)
- チューリング(1912 年)
ステップ 6:ストーリー一覧にグリッドカードを追加する
docs/stories/index.md を編集し、MkDocs Material のグリッド形式でカードを追加します:
- **[<Story Title>](<subject-name>/index.md)**

<2-4 sentence compelling description emphasizing the story's theme>
ステップ 7:他の教科書のストーリーを再利用する
別の知識教科書プロジェクトにすでにストーリーがある場合(例:知識論のストーリーを生態学の教科書で再利用する場合)は、重複して掲載するのではなく、元の教科書の公開サイトにあるストーリーへリンクしてください。各ストーリーには、約 170 行の Markdown と 13 枚の生成画像(カバー 1 枚+パネル 12 枚)が含まれています。これらを教科書間で重複させると、価値を高めることなく不要な容量が増えてしまいます。
カバー画像のみをコピーし、外部のストーリーへリンクします。
# Copy ONLY the cover image from the source project into the current project
mkdir -p docs/stories/<subject-name>
cp /path/to/other-textbook/docs/stories/<subject-name>/cover.png \
docs/stories/<subject-name>/cover.png
mkdocs serve での開発時にも表示されるよう、カバー画像はローカルに置く必要があります。画像に外部 URL を使用しないでください。ローカルでは表示されず、別サイトへの依存が生じます。
ストーリーのタイトルリンクは、元の教科書サイト上の公開 URL を指定してください。
- **[<Story Title>](https://dmccreary.github.io/<source-book>/stories/<subject-name>/)**

<2-4 sentence compelling description>
別サイトに移動した学生が戸惑わないよう、相互リンクしたストーリーのグリッドの上に読者向けの案内を追加してください。カードごとではなく、グリッドの前に一度だけ配置します。
*Clicking a card below will take you to the <Source Book Name> site, where the
full story and all 12 panel images are hosted. Use your browser's back button
to return here. We link rather than duplicate because each story includes 13
generated images — copying them across textbooks would add unnecessary bulk
without adding value.*
現在のプロジェクトにストーリーの Markdown 全体や 12 枚のパネル画像を複製しないでください。ローカルにコピーするのはカバー画像だけです。
参考資料に関するガイド
初稿の段階で、実際に機能する URL を記載してください。(PLACEHOLDER) は使用しないでください。
各ストーリーでは、次の標準的な 5 件の参考資料パターンに従ってください。
| # | 出典 | 用途 |
|---|---|---|
| 1 | Wikipedia:<人物の伝記> | 詳細な伝記記事 |
| 2 | Wikipedia:<主な貢献> | その人物を代表する発見または業績 |
| 3 | Wikipedia:<関連する概念または業績> | 2 件目のテーマに関連するリンク(例:その人物に関連する発明、その人物にちなんで名付けられた方程式、重要な論文) |
| 4 | MacTutor(数学者)、Nobel Prize(受賞者)、NASA(ミッションの科学者)、または同等の機関による人物紹介 | 信頼性の高い学術的な歴史資料 |
| 5 | Encyclopaedia Britannica または Stanford Encyclopedia of Philosophy | 編集された概要資料 |
例 — エイダ・ラブレス:
## References
1. [Wikipedia: Ada Lovelace](https://en.wikipedia.org/wiki/Ada_Lovelace) - Biography of the English mathematician often called the first programmer
2. [Wikipedia: Analytical Engine](https://en.wikipedia.org/wiki/Analytical_Engine) - Babbage's proposed mechanical general-purpose computer
3. [Wikipedia: Note G](https://en.wikipedia.org/wiki/Note_G) - Lovelace's note describing the first published algorithm
4. [MacTutor: Augusta Ada King, Countess of Lovelace](https://mathshistory.st-andrews.ac.uk/Biographies/Lovelace/) - University of St Andrews history of mathematics archive
5. [Encyclopaedia Britannica: Ada Lovelace](https://www.britannica.com/biography/Ada-Lovelace) - Overview of Lovelace's life and contributions to computing
PLACEHOLDER URL を含む既存ストーリーの修正
2026-04 のスキル更新前に生成されたストーリーには、(PLACEHOLDER) の参考資料 URL が残っている場合があります。まとめて修正するには、scripts/fix-references.py をプロジェクトの src/ ディレクトリにコピーし、先頭の REFS 辞書にストーリーと厳選した URL を記載してから、次のコマンドを実行します。
cp ~/.claude/skills/story-generator/scripts/fix-references.py src/stories/
# Edit src/stories/fix-references.py to fill in the REFS dict
python3 src/stories/fix-references.py
このスクリプトは、一覧にある各ストーリーの index.md について、## References 見出しからファイル末尾までを書き換えます。安全に繰り返し実行できます。
このスクリプトは、意図的に汎用ではない設計になっています。適切な参考資料を選ぶには判断が必要であり、プロジェクトごとに求める出典が少しずつ異なるためです。プロジェクト内でカスタマイズしたコピーを管理するのが適切な方法です。
セーフティフィルターのパターン
Gemini 2.5 Flash Image は、安全性分類器に検知されるプロンプトを拒否します。拒否された場合、レスポンスに finish_reason=FinishReason.IMAGE_SAFETY が表示されます。スクリプトはその内容をログに記録し、クラッシュすることなく次の画像の処理を続行します。
既知のトリガー:
- ナチスの明示的な画像(かぎ十字、ナチスの旗、SS の制服)
- 生々しい暴力、傷、または血
- ヌードまたは性的なコンテンツ
- 未成年者が明らかに苦痛を感じている場面
- 実在の人物が殺害または拷問されている描写
表現を和らげるパターン — トリガーを取り除きながら、感情的な重みを保てるようにプロンプトを書き換えます。
| 元の表現(フィルターに検知される) | 和らげた表現(通常は問題なく生成できる) |
|---|---|
| "建物に掲げられたナチスの旗" | "裸の木々が立つ、無人の灰色の通り" |
| "手紙に押されたかぎ十字のスタンプ" | "手紙に押された一般的な封蝋" |
| "ナチスの法律によって追放された" | "ドイツを離れる準備をしている" |
| "床の血" | "床に落ちた壊れた物" |
| "銃殺隊によって処刑された" | "彼の無人の机と倒れた椅子" |
事例 — Emmy Noether のパネル 10(2026-04-05): 元のプロンプトには「遠くの建物にナチスの旗が掲げられている」と「かぎ十字のスタンプが押された解雇通知」が明示されていました。Gemini は IMAGE_SAFETY により拒否しました。「裸の木々が立つ、無人の灰色の通り」と「一般的な封蝋が押された政府からの解雇通知」に表現を和らげたところ、次の試行で問題なく生成できました。強制的な亡命という歴史的な意味は保たれ、露骨な象徴表現は取り除かれています。
プロンプトがブロックされた場合のワークフロー:
- スクリプトは失敗をログに記録して処理を続行します — クラッシュしません
- ストーリーの
index.mdで問題のあるプロンプトを編集し、トリガーとなる表現を和らげます - 再実行します:
python3 generate-images.py docs/stories/<name> --skip-existing - 以前に失敗したパネルだけが再生成され、ほかのパネルはすべてスキップされます
- 和らげたプロンプトをコミットして、今後の再生成が初回から成功するようにします
コスト分析
Gemini 2.5 Flash Image の料金(2026年初頭に確認):
- 入力テキストトークン:100万トークンあたり $0.30
- 出力画像トークン:100万トークンあたり $30.00
- 固定料金:画像1枚あたり出力トークン1,290個 = 有料プランで画像1枚あたり $0.039
無料プラン(注意 — 下記の警告をご覧ください):
- 1日あたり500リクエスト(RPD)
- 1分あたり10リクエスト(RPM)
- 1分あたり約250,000トークン(TPM)
- クレジットカード不要、請求先アカウント不要と案内されています
警告:「無料プラン」では画像生成がサポートされていない可能性があります(2026年4月時点)。 2026-04-06にテストしたところ、無料プランで新規作成したGoogle AI Studioプロジェクトでは、
gemini-2.5-flash-preview-imageに対してlimit: 0のRESOURCE_EXHAUSTEDが返されました。つまり、無料プランのプロジェクトでは画像生成モデルの割り当てがゼロです。これはレート制限や一時的な上限ではなく、完全なゼロです。画像の生成に成功したのは、Tier 1の後払い請求(クレジットカード必須)が有効なプロジェクトのみでした。無料プランはテキストのみのGemini呼び出しでは機能する可能性がありますが、画像生成には対応していないようです。これは、以下およびGeminiのドキュメントに記載された以前の情報と矛盾します。Googleが無料プランでの画像生成を再開した場合、この警告は削除できます。
コストの見積もり(有料プランのみ — 現在、無料プランでは画像を生成できません):
ストーリーごとのコストはパネル数に比例します。Nパネルのストーリーの場合、**$0.039 × (N + 1)**です。
| 対象 | 画像数 | 有料プランのコスト |
|---|---|---|
| 6パネルのストーリー(表紙1枚 + 6パネル) | 7 | 約$0.27 |
| 8パネルのストーリー(表紙1枚 + 8パネル) | 9 | 約$0.35 |
| デフォルトの12パネルのストーリー(表紙1枚 + 12パネル) | 13 | $0.51 |
| 16パネルのストーリー(表紙1枚 + 16パネル) | 17 | 約$0.66 |
| 14ストーリーの教科書1冊(すべてデフォルトの12パネル) | 182 | 約$7.10 |
| 14ストーリーの教科書1冊(混在:平均8パネル) | 約126 | 約$4.91 |
| 16ストーリーの教科書1冊(すべてデフォルトの12パネル) | 208 | 約$8.07 |
支出上限に関する警告: Google AI StudioのTier 1後払いプロジェクトには、設定可能な月間支出上限があります(デフォルト値は異なります)。上限の適用には最大10分の遅延があるため、数パーセントの超過が発生する可能性があります。https://aistudio.google.com/spendで支出を確認してください。上限は毎月1日(PST)にリセットされます。実行中に上限に達した場合、スクリプトは各失敗をログに記録して処理を続行します。上限を引き上げた後、--skip-existingを指定して再実行してください。
推奨事項: ストーリーごとに**$0.039 × (N + 1)**を予算として見積もってください。デフォルトの12パネルの長さなら約$0.50、コンパクトな6パネルのストーリーなら$0.30未満です。デフォルトの長さのストーリーで構成される14ストーリーの教科書は約$7、ストーリーあたり平均8パネルの混在した長さの教科書は約$5です。月間の想定支出額に、超過分に備えた少額の余裕を加えた金額以上に、支出上限を設定してください。
代替モデル(大量生産向け)
1つのプロジェクトで1日あたり500枚を継続的に超える場合、より安価な選択肢があります。ただし、品質にはばらつきがあります。
| モデル | プロバイダー | 画像1枚あたりのおおよそのコスト | 備考 |
|---|---|---|---|
| FLUX.1 [schnell] | Fal / Replicate | $0.003 | 13倍安価、品質は良好、16:9のネイティブ設定なし |
| FLUX.1 [dev] | Fal / Replicate | $0.025 | 中価格帯、非常に高品質 |
| SD 3.5 Medium | Stability AI | 約$0.035 | Geminiと同程度 |
| gpt-image-1 (low) | OpenAI | $0.011 | 3倍安価、品質は低め、アスペクト比に制限あり |
| ローカルSDXL / FLUX | セルフホストGPU | ほぼ無料 | 16 GB以上のVRAMとセットアップ時間が必要 |
率直な評価: Gemini 2.5 Flash Imageは、このスキルが想定する規模では、依然としてコストあたりの品質が最も優れています。代替モデルが有効になるのは、1つのプロジェクトで1日あたり500枚を超える場合だけです。現実的な教科書作成のワークフローで、この数に達することはありません。
既知の問題
無料プランでは画像を生成できません(2026年4月時点)
無料プランで新規作成された Google AI Studio プロジェクトでは、gemini-2.5-flash-preview-image のクォータはゼロです。API は limit: 0 を伴う RESOURCE_EXHAUSTED を返します。これはレート制限ではなく、完全にゼロの状態です。このことは、2026-04-06 に別々の無料プランのプロジェクト2件で確認しました。画像を生成できるのは、Tier 1 Postpay 課金(クレジットカードが必要)が有効なプロジェクトだけです。これは、関数の教科書を生成した当時の動作から変更されたようです。新しいプロジェクトで limit: 0 エラーが表示された場合は、待ったり再試行したりするのではなく、https://aistudio.google.com/billing で課金を有効にしてください。
支出上限に達すると、生成が通知なしにブロックされることがあります
Google AI Studio の Tier 1 Postpay プロジェクトには、設定可能な月間支出上限があります。上限に達すると、すべての API 呼び出しは「Your project has exceeded its spending cap.」というメッセージを伴う RESOURCE_EXHAUSTED を返します。generate-images.py スクリプトはこのエラーを記録して処理を続行します(致命的なエラーではありません)が、画像は生成されません。上限の適用には最大10分の遅延があるため、数パーセントの超過は通常発生します。https://aistudio.google.com/spend で状況を確認し、上限を調整してください。上限は毎月1日(PST)にリセットされます。
Antigravity の generate_image ツールでは aspect_ratio を指定できません
Google Antigravity IDE に付属する内部の generate_image ツールは、Prompt、ImageName、ImagePaths、およびツールのメタデータのみを受け付けるスキーマです。aspect_ratio や size は公開されていないため、生成される画像はすべてデフォルトで1:1の正方形になります。グラフィックノベルのコマには Antigravity の generate_image を使用しないでください。 代わりに scripts/generate-images.py(このスキル)を使用してください。このスクリプトは google-genai を介して Gemini を直接呼び出し、ImageConfig(aspect_ratio="16:9") を渡します。
「16:9 の横長で映画のような構図」といったプロンプトレベルの回避策は機能しません。Gemini は ImageConfig.aspect_ratio には従いますが、プロンプト内のアスペクト比に関する指定は、せいぜいスタイル上の提案として扱います。
報告する価値があります。Antigravity チームには、Gemini がサポートする10種類すべてのアスペクト比(21:9、16:9、4:3、3:2、1:1、9:16、3:4、2:3、5:4、4:5)に加え、できれば response_modalities と透過 PNG オプションも公開してほしいところです。
コマ間でのキャラクターの顔の一貫性
Gemini 2.5 Flash Image は、似たプロンプトで複数回生成した際にスタイルの一貫性(アートスタイル、カラーパレット、雰囲気)を保ちますが、同じキャラクターの顔の特徴を正確に維持することはできません。3コマ目のマリー・キュリーと5コマ目のマリー・キュリーは、スタイルは似ていますが、同一にはなりません。コマをナレーションとともに順に読む教育用グラフィックノベルでは、通常は許容できます。ピクセル単位で同一のキャラクターの顔が必要なプロ向けの制作では、Flux Kontext、参照画像を使用する Imagen 4、またはファインチューニングしたキャラクター LoRA を検討してください。このスキルの対象範囲外です。
最初の画像パートのみ使用されます
Gemini が1回のレスポンスで複数の画像パートを返した場合(まれですが、発生する可能性があります)、スクリプトは最初の画像だけを保存します。複数画像のレスポンスには対応していません。
時代別のアートスタイルの参考例
| 時代 | 推奨アートスタイル |
|---|---|
| 古代(西暦500年以前) | 古典的な地中海風、モザイクに着想を得たスタイル |
| ルネサンス(1400-1600) | イタリア・ルネサンス、暖かな照明 |
| 啓蒙時代(1600-1800) | バロック、オランダ黄金時代 |
| ナポレオン帝国時代(1795-1815) | 帝政期フランスのアカデミック絵画 |
| ヴィクトリア朝(1800-1900) | ラファエル前派、産業的なスタイル |
| 金ぴか時代(1870-1900) | アール・ヌーヴォー、アメリカの産業的なスタイル |
| 近代初期(1900-1950) | アール・デコ、モダニズム、バウハウス(ヴァイマル期ドイツ向け) |
| 第二次世界大戦時代(1939-1945) | 1940年代のノワール、彩度を抑えたオリーブ色/カーキ色 |
| ミッドセンチュリー(1950-1980) | アトミック・エイジ、すっきりした線、ベル研究所のモダニズム |
| 宇宙時代(1957-1975) | NASA の技術イラスト、宇宙を思わせる青 |
| 現代(1980年以降) | 時代を感じさせる要素を取り入れたフォトリアリズム |
執筆ガイドライン
対象読者
- 多くのインテリジェントな教科書プロジェクトでは、中等学校の生徒(9〜12年生、14〜18歳)
- プロジェクトに合わせて読解レベルを調整します。このスキルでは、構成を変えずに語り口を変えることで、より年少または年長の読者にも対応できます
語り口
- 能動態を使い、生き生きと描写します
- 物語はすべて単独で理解できるものにします。物語の文章で短縮名を使う前に、登場する人物のフルネームと役割を紹介します
- 歴史的に適切な場合は、会話を含めます
- ドラマ性と教育的な正確さのバランスを取ります
- 発見の背景にある人間ドラマを強調します
- 苦闘、失敗、粘り強さを描きます
- 歴史的な出来事を現代のテクノロジーや今日的な意義と結び付けます
テーマの展開
対象読者の心に響く中心的なテーマを選びます。
- 懐疑的な人々や疑う人々を乗り越える
- 失敗を重ねても粘り強く取り組む
- 独学と好奇心
- 差別と闘う
- 他の人には見えなかったものを見抜く
- 成功しても謙虚さを保つ
- 目に見えないものを見えるようにする
歴史的な正確さ
- 重要な日付、出来事、人間関係を調査します
- 画像プロンプトでは、服装、建築、テクノロジー、タイポグラフィなど、歴史的に正確な詳細を使います
- Narrative Prompt ブロック内に、創作上の脚色があれば記載します
- 可能な場合は、出典を確認できる引用を含めます
スクリプト
generate-images.py(主要スクリプト)
Gemini API を介して、すべてのパネル画像を生成します。「ステップ 3.5:画像を生成する」を参照してください。
verify-images.py
読み取り専用の監査ツールです。必要なパネルがすべて存在すること、適切なアスペクト比であること、最小ファイルサイズを満たしていることを確認します。使い方:
python3 ~/.claude/skills/story-generator/scripts/verify-images.py \
docs/stories/{story-dir-name}
fix-references.py(旧形式の修正ツール)
古いストーリー内の (PLACEHOLDER) 参照 URL を後から置き換えるためのツールです。新しいストーリーには使用しないでください。新しいストーリーでは、初稿の段階で実際の URL を指定してください。上記の「参考文献に関するガイダンス」を参照してください。
uncomment-images.sh(代替ワークフロー)
画像生成を後回しにするワークフローでは、Markdown 内の画像参照を HTML コメント(``)で囲んで、画像が存在しないことを示すアイコンが表示されないようにします。このスクリプトは、何らかの方法で PNG が生成された後に、コメントを解除します。
使い方:
~/.claude/skills/story-generator/scripts/uncomment-images.sh \
docs/stories/{story-dir-name}/index.md
使用する場合:
- Markdown をすぐに公開し、後でバッチジョブで画像を生成する場合
generate-images.py以外の画像生成ツールを使用する場合- 古いワークフローから移行する場合
使用しない場合:
generate-images.pyを使用する場合。このスクリプトはindex.mdに記載されたファイル名で PNG を直接書き込むため、コメントを解除する必要はありません
チェックリスト
ストーリーの作成後、以下を確認してください。
コンテンツ:
- ストーリーのディレクトリを作成済み:
docs/stories/<name>/ -
index.mdに、物語の全文と N + 1 個の画像プロンプト(表紙 + N パネル。N は--panels引数の値、またはデフォルトの 12)が記載されている - パネル番号が
panel-01からpanel-NNまで連続しており、欠番がない - すべての「panel X of N」識別行で、このストーリーにおける実際の N が使われている(以前の 12 が残っていない)
- すべての画像参照に
.png拡張子が使われている(.jpgや.mdは不可) - YAML フロントマターにタイトル、説明、og/twitter 画像パスが含まれている
- N 個の番号付きパネルが、一貫した構成(画像 + プロンプト + 物語)になっている
- 登場人物は全員、物語で初めて言及される前に、フルネームと平易な言葉での役割が紹介されている。その人物を理解するために、過去のストーリー、画像プロンプト、キャラクターシートは必要ない
- エピローグに「課題/対応/教訓」の表が含まれている
- 2~3 件の対象者の引用がある(架空のストーリーの場合は、登場人物の口調に合った引用)
- 参考資料セクションに、実際に機能する URL が 5 件あり、最初の 3 件は Wikipedia を参照している。
(PLACEHOLDER)の文字列が含まれていない
画像生成(generate-images.py を使用する場合):
- 環境に
GEMINI_API_KEYを設定済み -
pip install google-genaiを実行済み -
generate-images.py --first-onlyを実行し、表紙がネイティブの 16:9(1344×768)であることを確認済み -
generate-images.pyの全体実行が致命的なエラーなしで完了済み - ストーリーのディレクトリに N + 1 個の PNG ファイルがすべて存在する
-
verify-images.pyが終了コード 0 で終了する - ストーリーごとのログが
logs/{story-name}-{YYYY-MM-DD}.mdに存在する - JSONL 使用ログが
logs/image-generation-usage.jsonlで更新されている
統合:
-
mkdocs.ymlのナビゲーションに、生年順に追加済み -
docs/stories/index.mdにグリッドカードを追加済み - 安全フィルターを緩和した箇所は、今後の再生成で元に戻らないようコミット済み
- 画像プロンプトに実在のブランド名、製品名、商標が含まれていない(物語の本文ではブランド名を使用可)
付録:IB Functions 教科書から得た教訓(2026-04-05)
2026-04 のスキル更新は、/Users/dan/Documents/ws/functions にある実際の16話の教科書プロジェクトをきっかけに行われました。決定版の事例研究は /Users/dan/Documents/ws/functions/logs/stories.md にあります。ここでは、得られた主な教訓を紹介します。
-
以前のワークフローでは正方形の画像が生成されていました。 ストーリーは Antigravity IDE エージェントの
generate_imageツールを使って生成していましたが、このツールではaspect_ratioを指定できず、既定値は 1:1 でした。回避策として、正方形の画像を 1280×1280 に拡大してから 1280×720 に中央クロップしていましたが、縦方向のコンテンツが約44%失われていました。解決策は Antigravity を介さず、google-genaiを使って Gemini を直接呼び出すことでした。現在のscripts/generate-images.pyはこの方法を採用しています。 -
無料枠は本当に無料です。(2026-04-06 訂正。) 元の Functions 教科書(画像208枚)は、無料枠での画像生成が機能していた時期に作成された可能性があります。しかし、2026年4月現在、新たに作成した無料枠のプロジェクトではgemini-2.5-flash-preview-imageのlimit: 0が返されます。画像を生成できるのは、クレジットカードが必要な Tier 1 Postpay プロジェクトのみです。14話の教科書(Theory of Knowledge、画像182枚)の費用は、Tier 1 Postpay で約 $11 でした。現時点では、無料枠は画像生成に利用できません。1話あたり約$0.50の予算を見込んでください。 -
セーフティフィルターに止められることはまれですが、注意が必要です。 生成した画像208枚のうち、完全にブロックされたものは1枚(Emmy Noether のパネル10。ナチスを明示的に描写していたため)、一時的にブロックされたものは1枚(Mirzakhani のパネル10。内容を変更せず再試行したところ生成できました)でした。スクリプトは現在、この両方に適切に対処し、Noether のケースのようなコンテンツを和らげるパターンについても前述のとおり記載しています。
-
プレースホルダーの参照先には注意が必要です。 16話すべてに、このスキルの以前のバージョンに由来する
(PLACEHOLDER)URL が当初含まれていました。後から修正するには、fix-references.pyスクリプトを書く必要がありました。新しいストーリーでは、最初の草稿から実際の URL を記載してください。このスキルでは、その点を明示的に案内するようになりました。 -
実行ごとの監査ログは、コードを書く価値があります。 JSONL 形式の監査ログにより、ほかの方法では分からなかった微妙な事実が判明しました。プロンプトの複雑さにかかわらず、画像1枚あたりの出力トークン数は常に正確に1,290でした。これにより、公表されている料金モデルが裏付けられ、大規模利用時の費用予測が正確であるという確信をユーザーに持ってもらえました。
-
この価格帯では、キャラクターの顔の一貫性はまだ解決されていません。 前述の「既知の問題」を参照してください。12枚のパネルを通じて、ピクセル単位で同一のキャラクターが描かれることを期待すべきではありません。現時点では、1枚あたり$0.039で、スタイルは一貫しているものの、キャラクターの見た目には個体差があります。大規模な教育用グラフィックノベルでは許容できるトレードオフですが、プロ向けの商業出版では許容できません。
-
画像生成で無料枠が利用できなくなりました(2026-04-06)。 Theory of Knowledge 教科書のプロジェクトでは、$10の支出上限に達するまでに Tier 1 Postpay で画像を78枚生成しました。生成を続けるため、新しい無料枠のプロジェクトを作成したところ、すべての無料枠プロジェクトで
gemini-2.5-flash-preview-imageのlimit: 0が設定されていることが分かりました。これは、上記の教訓#2(無料枠の画像生成が機能していた期間に作成された可能性のある Functions プロジェクトに基づく内容)と矛盾します。スキルのドキュメントは、画像生成には有料の課金設定が必要であるとユーザーに警告するよう更新されました。1話あたり約$0.50、教科書1冊あたり約$7~8の予算を見込んでください。
今後このスキルを更新する場合は、現在の設計に至った経緯やすべての判断を確認するため、Functions プロジェクトの logs/stories.md にあるセッションの完全な記録を読んでください。