はじめに
Codex 系の開発で Plugin を扱うとき、最初につまずきやすいのが
「最低限どんな構造で作ればよいのか」 です。
たとえば、次のような疑問が出てきます。
- Plugin のディレクトリはどう切るべきか
-
.codex-plugin/plugin.jsonには何を書くべきか -
skills/hooks/scripts/assets/はいつ作るべきか -
.mcp.jsonや.app.jsonはどう扱うべきか -
marketplace.jsonにどう登録するべきか - Plugin 名の命名規則はどうするべきか
こうした「Plugin を作るときの土台」を、自動で安全に整えてくれるのが今回の plugin-creator です。
このコードは一見すると小さな scaffold ツールです。
ですが、実際にはかなりよく考えられています。
- Plugin 名の正規化
- 必須 manifest の生成
- optional 構造の追加
-
marketplace.jsonの自動更新 - 既存データとの衝突回避
- 規約を壊しにくい CLI 設計
まで、コンパクトにまとまっています。
この記事では、この plugin-creator を題材にして、
コードを読みながら「Plugin をどう設計し、どう生成するのか」をきちんと理解することを目指します。
この記事で分かること
この記事を読み終えると、次のことが分かるようになります。
-
plugin-creatorが何を自動化しているのか - Codex Plugin の基本構造はどうあるべきか
-
.codex-plugin/plugin.jsonの役割 -
marketplace.jsonの役割 -
create_basic_plugin.pyの処理の流れ - Python で小さな scaffold CLI をどう設計すると読みやすくなるか
対象読者
この記事は、次のような方に向いています。
- Codex 用 Plugin の基本構造をちゃんと理解したい方
-
plugin.jsonとmarketplace.jsonの違いを整理したい方 - Python で scaffold ツールを書く実例を見たい方
- 小さいけれど筋の良い CLI コードを読みたい方
- Plugin 開発を始めるためのたたき台が欲しい方
まず結論:plugin-creator は何をするツールなのか
一言でいうと、plugin-creator は次のためのツールです。
Codex 用 Plugin のディレクトリ構造と必須 manifest を安全に scaffold するツール
さらにもう少し具体的に言うと、主に次の 3 つを担当しています。
1. Plugin の基本ディレクトリを作る
たとえば、
plugins/my-plugin/plugins/my-plugin/.codex-plugin/plugin.json
のような構造を生成します。
ここで重要なのは、.codex-plugin/plugin.json は必須として扱われていることです。
2. 必要に応じて optional 構造を作る
必要なら次のようなものも一緒に作れます。
skills/hooks/scripts/assets/.mcp.json.app.json
つまり、「最小構成」から「少し本格的な Plugin 構成」まで段階的に作れます。
3. marketplace.json を作成・更新する
Plugin を Codex UI の ordering や availability に出したい場合、
marketplace.json を更新する必要があります。
plugin-creator はここも面倒を見ます。
- まだ
marketplace.jsonが存在しないなら初期化 - 既存なら
plugins[]にエントリ追加 - 同名 Plugin があれば
--forceなしでは上書きしない
という安全な挙動です。
ディレクトリ構成を見てみる
まずは、今回の plugin-creator 自体の構成を見てみます。
plugin-creator/
├── SKILL.md
├── agents/
│ └── openai.yaml
├── assets/
│ ├── plugin-creator-small.svg
│ └── plugin-creator.png
├── references/
│ └── plugin-json-spec.md
└── scripts/
└── create_basic_plugin.py
この構成だけでも、かなり整理されています。
この構成の役割
SKILL.md
この Skill が何をするのか、どう使うのか、どんなルールがあるのかを書いています。
agents/openai.yaml
UI 用の metadata です。
references/plugin-json-spec.md
plugin.json や marketplace.json のサンプル仕様がまとまっています。
scripts/create_basic_plugin.py
今回の主役です。
Plugin scaffold の実処理はこの 1 本に集約されています。
SKILL.md を読むと、この Skill の思想が見える
まず SKILL.md の frontmatter を見ると、こうなっています。
---
name: plugin-creator
description: Create and scaffold plugin directories for Codex with a required `.codex-plugin/plugin.json`, optional plugin folders/files, and baseline placeholders you can edit before publishing or testing. Use when Codex needs to create a new local plugin, add optional plugin structure, or generate or update repo-root `.agents/plugins/marketplace.json` entries for plugin ordering and availability metadata.
---
ここでまず分かるのは、この Skill の対象範囲です。
- local plugin を作る
- optional 構造を追加する
-
marketplace.jsonを作る / 更新する
つまりこの Skill は、
「Plugin の最初の土台を整える」ことに特化しているわけです。
Quick Start がかなり実用的
本文の冒頭では、すぐ使える形で CLI 実行例が示されています。
たとえば最小の作成例はこうです。
python3 .agents/skills/plugin-creator/scripts/create_basic_plugin.py <plugin-name>
marketplace.json も作るならこうです。
python3 .agents/skills/plugin-creator/scripts/create_basic_plugin.py my-plugin --with-marketplace
さらに optional 構造まで一気に作るならこうです。
python3 .agents/skills/plugin-creator/scripts/create_basic_plugin.py my-plugin \
--with-skills --with-hooks --with-scripts --with-assets --with-mcp --with-apps --with-marketplace
これだけでも、使い方がかなり明確です。
plugin-creator が作るものを整理する
SKILL.md に書かれている内容を整理すると、このツールが作るものは次の通りです。
必須で作るもの
必ず作るのはこの 2 つです。
<parent-plugin-directory>/<plugin-name>/
<parent-plugin-directory>/<plugin-name>/.codex-plugin/plugin.json
つまり、.codex-plugin/plugin.json は常に存在させる設計です。
これはとても大事です。
Plugin の本体 manifest がない Plugin は成立しないので、
最初からそこを必須にしているのは正しい判断です。
オプションで作るもの
必要に応じて、次を追加できます。
skills/
hooks/
scripts/
assets/
.mcp.json
.app.json
つまりこのツールは、
- ただ manifest だけ欲しい最小構成
- 将来的に Skill や Hook や MCP を持つ構成
の両方に対応できます。
Marketplace エントリも作れる
さらに、--with-marketplace を付けると
marketplace.json 側にもエントリを作れます。
生成されるエントリの形は、概ね次のようになります。
{
"name": "plugin-name",
"source": {
"source": "local",
"path": "./plugins/plugin-name"
},
"policy": {
"installation": "AVAILABLE",
"authentication": "ON_INSTALL"
},
"category": "Productivity"
}
この形を毎回手で書くのは意外と面倒なので、自動化の価値が高いです。
plugin.json と marketplace.json の違いを先に整理しておく
ここは混乱しやすいので、先に整理しておきます。
.codex-plugin/plugin.json とは
これは Plugin 自身の manifest です。
つまり、
- Plugin 名
- バージョン
- 説明
- author
- skills / hooks / mcpServers / apps への参照
- interface 情報
など、Plugin 本体の定義を持っています。
marketplace.json とは
こちらは Plugin 一覧側の定義です。
つまり、
- どの Plugin が並ぶか
- どの順番で並ぶか
- install policy
- authentication policy
- category
- source.path
など、Plugin を UI 側でどう扱うか を持っています。
役割の違いを一言でいうと
-
plugin.jsonは Plugin の自己紹介 -
marketplace.jsonは Plugin の陳列棚
です。
この 2 つを分けて考えると、かなり理解しやすくなります。
references/plugin-json-spec.md がとても大事
references/plugin-json-spec.md には、plugin.json と marketplace.json のサンプル仕様がまとまっています。
たとえば plugin.json のサンプルはこうです。
{
"name": "plugin-name",
"version": "1.2.0",
"description": "Brief plugin description",
"author": {
"name": "Author Name",
"email": "author@example.com",
"url": "https://github.com/author"
},
"homepage": "https://docs.example.com/plugin",
"repository": "https://github.com/author/plugin",
"license": "MIT",
"keywords": ["keyword1", "keyword2"],
"skills": "./skills/",
"hooks": "./hooks.json",
"mcpServers": "./.mcp.json",
"apps": "./.app.json",
"interface": {
"displayName": "Plugin Display Name",
"shortDescription": "Short description for subtitle",
"longDescription": "Long description for details page",
"developerName": "OpenAI",
"category": "Productivity"
}
}
これがあることで、create_basic_plugin.py の placeholder 設計がどこから来ているかが分かります。
ここからコードを読む
この plugin-creator の実装の中心は、次の 1 本です。
scripts/create_basic_plugin.py
このファイルは、役割が非常に明確です。
Plugin の scaffold を作り、必要なら marketplace も更新する
では中身を順に見ていきます。
1. 定数定義を見るだけで、ツールの方針が分かる
冒頭には次のような定数があります。
MAX_PLUGIN_NAME_LENGTH = 64
DEFAULT_PLUGIN_PARENT = Path.cwd() / "plugins"
DEFAULT_MARKETPLACE_PATH = Path.cwd() / ".agents" / "plugins" / "marketplace.json"
DEFAULT_INSTALL_POLICY = "AVAILABLE"
DEFAULT_AUTH_POLICY = "ON_INSTALL"
DEFAULT_CATEGORY = "Productivity"
DEFAULT_MARKETPLACE_DISPLAY_NAME = "[TODO: Marketplace Display Name]"
VALID_INSTALL_POLICIES = {"NOT_AVAILABLE", "AVAILABLE", "INSTALLED_BY_DEFAULT"}
VALID_AUTH_POLICIES = {"ON_INSTALL", "ON_USE"}
この定数群から、かなり多くのことが読み取れます。
読み取れる設計方針
Plugin 名は 64 文字以内
長すぎる名前を最初から防ぎます。
デフォルトでは <cwd>/plugins 配下に作る
repo-local plugin を基本にしていることが分かります。
marketplace は <cwd>/.agents/plugins/marketplace.json
repo-root 基準の marketplace を想定しています。
install policy / auth policy / category に default がある
毎回全部を指定しなくても、最低限まともな marketplace entry を作れるようにしています。
2. Plugin 名の正規化がきれい
まず重要なのが normalize_plugin_name() です。
def normalize_plugin_name(plugin_name: str) -> str:
normalized = plugin_name.strip().lower()
normalized = re.sub(r"[^a-z0-9]+", "-", normalized)
normalized = normalized.strip("-")
normalized = re.sub(r"-{2,}", "-", normalized)
return normalized
これは skill-creator とよく似た設計です。
何をしているのか
- 前後の空白を削除
- 小文字化
- 英数字以外を
-に変換 - 先頭末尾の
-を削除 -
---のような連続ハイフンを 1 個に圧縮
実際の変換例
normalize_plugin_name("My Plugin")
# "my-plugin"
normalize_plugin_name("My__Plugin!!")
# "my-plugin"
normalize_plugin_name(" Plugin Creator Tool ")
# "plugin-creator-tool"
このように、多少雑な入力でも
規約に沿った kebab-case 名に自動で寄せるようになっています。
CLI ツールとして非常に親切です。
3. validate では「空」と「長すぎる」を止める
続いて validate_plugin_name() です。
def validate_plugin_name(plugin_name: str) -> None:
if not plugin_name:
raise ValueError("Plugin name must include at least one letter or digit.")
if len(plugin_name) > MAX_PLUGIN_NAME_LENGTH:
raise ValueError(
f"Plugin name '{plugin_name}' is too long ({len(plugin_name)} characters). "
f"Maximum is {MAX_PLUGIN_NAME_LENGTH} characters."
)
ここではシンプルに、
- 空になっていないか
- 長すぎないか
を見ています。
重要なのは、
正規化できるものは normalize し、どうしてもダメなものだけ validate で止める
という設計になっていることです。
これはツール設計として非常に良いバランスです。
4. build_plugin_json() は placeholder 付きの manifest を作る
この関数が、生成される .codex-plugin/plugin.json の中身を定義しています。
def build_plugin_json(plugin_name: str) -> dict:
return {
"name": plugin_name,
"version": "[TODO: 1.2.0]",
"description": "[TODO: Brief plugin description]",
"author": {
"name": "[TODO: Author Name]",
"email": "[TODO: author@example.com]",
"url": "[TODO: https://github.com/author]",
},
...
}
ここで大事なのは、空欄ではなく placeholder を入れていることです。
なぜ placeholder が良いのか
もし空文字や空 object だけを入れると、
何を埋めるべきかが分かりにくくなります。
一方でこのコードは、次のようにしています。
{
"version": "[TODO: 1.2.0]",
"description": "[TODO: Brief plugin description]"
}
これなら、作ったあとに人が見たとき、
- 何を埋めるべきか
- どんな形式が期待されているか
がすぐ分かります。
scaffold ツールとして非常に良い設計です。
interface セクションも最初から全部入れている
plugin.json の中には、interface ブロックも最初から含まれています。
"interface": {
"displayName": "[TODO: Plugin Display Name]",
"shortDescription": "[TODO: Short description for subtitle]",
"longDescription": "[TODO: Long description for details page]",
"developerName": "[TODO: OpenAI]",
"category": "[TODO: Productivity]",
"capabilities": ["[TODO: Interactive]", "[TODO: Write]"],
...
}
この設計の良いところは、
「最終的に必要になりそうな形」を最初から見せていることです。
つまり、
- 最低限の manifest だけ作る
- でも将来必要になる UI 項目も見える
という状態になります。
これは学習コストを下げます。
5. build_marketplace_entry() は marketplace 側の最小エントリを作る
Plugin 本体とは別に、marketplace entry も生成できます。
その形を定義しているのが build_marketplace_entry() です。
def build_marketplace_entry(
plugin_name: str,
install_policy: str,
auth_policy: str,
category: str,
) -> dict[str, Any]:
return {
"name": plugin_name,
"source": {
"source": "local",
"path": f"./plugins/{plugin_name}",
},
"policy": {
"installation": install_policy,
"authentication": auth_policy,
},
"category": category,
}
ここが良いのは、marketplace entry の shape を 1 か所に閉じ込めていることです。
もし後で、
- category を追加で調整したい
- source の形を変えたい
- policy を増やしたい
となっても、この関数を見れば済みます。
6. marketplace 初期化の考え方もきれい
marketplace.json が存在しない場合は、
build_default_marketplace() で雛形を作ります。
def build_default_marketplace() -> dict[str, Any]:
return {
"name": "[TODO: marketplace-name]",
"interface": {
"displayName": DEFAULT_MARKETPLACE_DISPLAY_NAME,
},
"plugins": [],
}
これもとても良いです。
良いポイント
- いきなり
plugins配列だけではない - top-level
nameも placeholder で用意する -
interface.displayNameも最初から seed する
つまり、marketplace 自体も
「あとでちゃんと育てられる雛形」 として生成しています。
7. update_marketplace_json() がかなり実務的
この関数が、marketplace の更新処理の中心です。
概ね次のような流れです。
def update_marketplace_json(...):
if marketplace_path.exists():
payload = load_json(marketplace_path)
else:
payload = build_default_marketplace()
plugins = payload.setdefault("plugins", [])
new_entry = build_marketplace_entry(...)
for index, entry in enumerate(plugins):
if isinstance(entry, dict) and entry.get("name") == plugin_name:
if not force:
raise FileExistsError(...)
plugins[index] = new_entry
break
else:
plugins.append(new_entry)
write_json(marketplace_path, payload, force=True)
この設計の良いところ
1. marketplace がなければ初期化する
初回実行でも困りません。
2. 既存の plugins[] を保つ
全部書き換えず、対象 plugin だけを見る設計です。
3. 同名 plugin は --force なしでは上書きしない
事故防止になります。
4. 新規なら append
SKILL.md に書かれていた「plugin order は render order」という思想に沿っています。
つまりこの処理は、
安全性と実用性のバランスがよいです。
8. write_json() と create_stub_file() の責務分離も良い
ファイル出力系の処理も分かれています。
JSON を確実に上書き / 作成する write_json()
def write_json(path: Path, data: dict, force: bool) -> None:
if path.exists() and not force:
raise FileExistsError(f"{path} already exists. Use --force to overwrite.")
path.parent.mkdir(parents=True, exist_ok=True)
with path.open("w") as handle:
json.dump(data, handle, indent=2)
handle.write("\n")
これは「必ず書きたい JSON」を扱う関数です。
既存ならそのままにする create_stub_file()
def create_stub_file(path: Path, payload: dict, force: bool) -> None:
if path.exists() and not force:
return
path.parent.mkdir(parents=True, exist_ok=True)
with path.open("w") as handle:
json.dump(payload, handle, indent=2)
handle.write("\n")
こちらは .mcp.json や .app.json のような
optional な stub 向けです。
この分離は地味ですが大事です。
-
plugin.jsonやmarketplace.jsonは厳密に扱う - stub は既存なら邪魔しない
という意図が見えます。
9. CLI 設計がかなり分かりやすい
parse_args() もよくできています。
parser.add_argument("plugin_name")
parser.add_argument("--path", default=str(DEFAULT_PLUGIN_PARENT))
parser.add_argument("--with-skills", action="store_true")
parser.add_argument("--with-hooks", action="store_true")
parser.add_argument("--with-scripts", action="store_true")
parser.add_argument("--with-assets", action="store_true")
parser.add_argument("--with-mcp", action="store_true")
parser.add_argument("--with-apps", action="store_true")
parser.add_argument("--with-marketplace", action="store_true")
parser.add_argument("--marketplace-path", default=str(DEFAULT_MARKETPLACE_PATH))
parser.add_argument("--install-policy", default=DEFAULT_INSTALL_POLICY, choices=sorted(VALID_INSTALL_POLICIES))
parser.add_argument("--auth-policy", default=DEFAULT_AUTH_POLICY, choices=sorted(VALID_AUTH_POLICIES))
parser.add_argument("--category", default=DEFAULT_CATEGORY)
parser.add_argument("--force", action="store_true")
使い方が頭の中で自然に組み立てられる
たとえば、これを見るだけで次の実行が想像できます。
最小構成
python3 create_basic_plugin.py my-plugin
skills と assets を付ける
python3 create_basic_plugin.py my-plugin --with-skills --with-assets
marketplace も作る
python3 create_basic_plugin.py my-plugin --with-marketplace
marketplace policy を変える
python3 create_basic_plugin.py my-plugin \
--with-marketplace \
--install-policy INSTALLED_BY_DEFAULT \
--auth-policy ON_USE \
--category "Developer Tools"
CLI は、読んだ瞬間に使い方が分かることが大事です。
このコードはそこが素直です。
10. main() を読むと、全体の流れが一気につかめる
最後に main() を見ると、このツールの全体像がきれいにまとまっています。
def main() -> None:
args = parse_args()
raw_plugin_name = args.plugin_name
plugin_name = normalize_plugin_name(raw_plugin_name)
if plugin_name != raw_plugin_name:
print(f"Note: Normalized plugin name from '{raw_plugin_name}' to '{plugin_name}'.")
validate_plugin_name(plugin_name)
plugin_root = (Path(args.path).expanduser().resolve() / plugin_name)
plugin_root.mkdir(parents=True, exist_ok=True)
plugin_json_path = plugin_root / ".codex-plugin" / "plugin.json"
write_json(plugin_json_path, build_plugin_json(plugin_name), args.force)
...
この後に、
- optional directories 作成
-
.mcp.json作成 -
.app.json作成 - marketplace 更新
- 出力先表示
が続きます。
処理の流れを日本語で言うと
- 引数を読む
- Plugin 名を正規化する
- 妥当性を確認する
- Plugin root を作る
-
.codex-plugin/plugin.jsonを書く - 必要なら optional directory を作る
- 必要なら
.mcp.jsonと.app.jsonを作る - 必要なら
marketplace.jsonを更新する - 最後に作成結果を表示する
この順番が自然なので、コードがとても読みやすいです。
実際に使うとどうなるか
ここで、いくつか具体例を見てみます。
例1: 最小構成の Plugin を作る
python3 .agents/skills/plugin-creator/scripts/create_basic_plugin.py my-plugin
生成イメージ:
plugins/
└── my-plugin/
└── .codex-plugin/
└── plugin.json
これは最小構成です。
例2: skills と scripts と assets を持つ Plugin を作る
python3 .agents/skills/plugin-creator/scripts/create_basic_plugin.py my-plugin \
--with-skills --with-scripts --with-assets
生成イメージ:
plugins/
└── my-plugin/
├── .codex-plugin/
│ └── plugin.json
├── skills/
├── scripts/
└── assets/
例3: MCP / App 用 stub も作る
python3 .agents/skills/plugin-creator/scripts/create_basic_plugin.py my-plugin \
--with-mcp --with-apps
生成イメージ:
plugins/
└── my-plugin/
├── .codex-plugin/
│ └── plugin.json
├── .mcp.json
└── .app.json
例4: marketplace も同時に作る
python3 .agents/skills/plugin-creator/scripts/create_basic_plugin.py my-plugin \
--with-marketplace
すると、Plugin 本体に加えて、次も更新されます。
.agents/
└── plugins/
└── marketplace.json
このコード全体の設計が良い理由
ここで、設計の良さを整理します。
1. 最小構成と拡張構成の両方に対応している
- まずは
plugin.jsonだけ作る - 必要なら skills / hooks / scripts / assets を足す
- さらに marketplace も管理する
この段階性がよいです。
2. 必須 manifest を絶対に外さない
.codex-plugin/plugin.json は常に作られます。
つまり、Plugin として最低限成立する形を必ず保つ設計です。
3. placeholder が教育的
生成される plugin.json は、空白ではなく [TODO: ...] が埋まっています。
これにより、
- 何を直すべきか
- どういう形式が期待されるか
が明確になります。
4. marketplace 更新が安全
- 既存 entry は勝手に壊さない
- 同名があれば
--forceを要求 - 初回なら marketplace を seed する
この安全性は実務上かなり大事です。
5. CLI が素直
引数名がそのまま意味を表していて、初見でも使いやすいです。
改善ポイントもある
かなり良いコードですが、改善の余地もあります。
ここも学びとして大事なので挙げておきます。
1. validator がまだない
skill-creator には quick_validate.py がありましたが、
今回の plugin-creator には validator がありません。
これは少し惜しいです。
たとえば将来的には、次のようなチェックがあると便利です。
-
plugin.jsonが JSON として正しいか -
nameが plugin folder と一致するか -
interface.defaultPromptが 3 件以内か -
marketplace.jsonの policy 値が allowed set に入っているか -
source.pathが./plugins/<plugin-name>になっているか
2. plugin.json は全部 placeholder なので、実運用前の埋め忘れが起きうる
これは scaffold としては正しいのですが、
そのまま publish してしまう事故は起きえます。
改善案
-
validate_plugin.pyを作る -
[TODO:を含んでいたら warning を出す
3. encoding を明示するとさらに安心
path.open() に encoding 指定がありません。
多くの環境では問題ありませんが、encoding="utf-8" を入れるとさらに堅いです。
4. optional directory の中身は空のまま
これはシンプルで良い反面、初心者には少し不親切かもしれません。
改善案
-
skills/README.mdのような軽い説明ファイルを optional で置く - あるいは
.gitkeepを置く
このコードから学べること
この plugin-creator は、Plugin scaffold の実例であると同時に、
小さな CLI ツールの設計教材としても優秀です。
学べることを整理すると、次の通りです。
1. 正規化と生成をきれいに分ける
- 名前は normalize する
- そのあと validate する
- そのうえで manifest を作る
流れが明確です。
2. scaffold は「空」ではなく「埋め方のヒント」を作るべき
placeholder を丁寧に入れることで、
使う人が次に何をすべきか分かります。
3. optional 構造は flag で足せると使いやすい
--with-skills のように明示的なフラグで足せる設計は、
柔軟で分かりやすいです。
4. marketplace のような共有ファイルは安全に更新するべき
- append を基本にする
- 上書きには
--force - 初回生成にも対応する
この設計は実務的です。
まとめ
plugin-creator は小さなツールですが、かなりよくできています。
このツールの本質は、単に Plugin 用フォルダを作ることではありません。
本当の価値は次の点にあります。
Codex Plugin の基本構造と運用ルールを、コードと scaffold に落とし込んでいること
特に良かった点は、次の通りです。
-
.codex-plugin/plugin.jsonを必須にしている - Plugin 名の正規化がきれい
-
plugin.jsonの placeholder が教育的 - optional 構造を flag で足せる
-
marketplace.jsonを安全に生成 / 更新できる - CLI が素直で分かりやすい
一方で、今後の改善余地としては次がありそうです。
- validator の追加
- TODO 埋め忘れ検知
-
plugin.json/marketplace.jsonの妥当性チェック - optional directory への軽い説明ファイル追加
とはいえ全体としては、
「最初の一歩をかなり滑らかにしてくれる scaffold ツール」 として、とても良い設計だと思います。
おわりに
Plugin 開発は、最初の 1 回目がいちばん面倒です。
- どこに置くのか
- 何が必須なのか
- manifest をどう書くのか
- marketplace とどうつなぐのか
この辺りで迷いやすいです。
plugin-creator は、その「最初の面倒」をかなりきれいに吸収してくれます。
しかも単に自動生成するだけでなく、
- 規約を守りやすくする
- 何を埋めるべきか分かるようにする
- 共有ファイルを安全に更新する
という意味で、かなり実務的です。
Codex Plugin をこれから作る方にとってはもちろん、
Python で scaffold CLI を書いてみたい方にも、かなり参考になるコードでした。