conformetry-configure について
conformetry のジェネレーター設定とテンプレート作成を説明するスキルです。入力、フック、インスタンスの照合、プレースホルダー、しきい値の動作を CLI ホストと Nx プラグイン別に解説します。
主な機能
- 01ジェネレーター設定と検証
- 02インスタンスグループとパス照合
- 03JSON Schema 入力設定
- 04生成フックとファイルシステム規則
- 05Mustache プレースホルダーと推論
- 06適合しきい値の指針
活用シーン
- 01ワークスペーステンプレートのジェネレーター定義
- 02Nx プロジェクトや glob による対象限定
- 03テンプレート生成前後のフック追加
- 04プレースホルダーや適合性の問題調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ organizzolini/ codebase --skill conformetry-configureインストール後、Claude Code で/conformetry-configureを入力して読み込まれたか確認します。
同梱ファイルreferences/languages.md
詳細
conformetry の設定とテンプレートの作成
ジェネレーターは、名前とテンプレート(通常のファイルを集めた通常のフォルダー)、およびそれをレンダリングするために必要な入力を組み合わせたものです。設定ではジェネレーターを宣言し、テンプレートフォルダーが生成物の定義全体を担います。同じテンプレートがインスタンスの照合基準にもなるため、テンプレートは出発点であると同時に標準でもあります。
設定
設定ファイルは、ジェネレーターごとに 1 つのエントリーを含む配列をデフォルトエクスポートします。必須フィールドは 2 つだけです。
| フィールド | 必須 | 意味 |
|---|---|---|
name | はい | ジェネレーターの呼び出し方法 |
templatePath | はい | ワークスペースのルートからの相対パスで指定するテンプレートフォルダー |
inputs | いいえ | JSON Schema の断片として指定する、テンプレートのレンダリングに使う値 |
instances | いいえ | このジェネレーターの出力がすでに存在する場所 |
description | いいえ | ジェネレーターの一覧表示時に表示されます |
hooks | いいえ | 生成の前後に実行される関数。フックを参照してください |
threshold | いいえ | このジェネレーターのインスタンスに許容される最低適合スコア。0 から 1 まで |
不明なキーは拒否されるため、フィールド名の誤記や、完全に削除された aliases を指定すると、何もせずに無視されるのではなく、読み込みに失敗します。ジェネレーターを一覧表示して、エントリーが反映されたことを確認してください。すべての conformetry コマンドで --config <path> が必要です。デフォルトの設定ファイルはありません。
conformetry templates --config configuration/conformetry.config.ts
パスを指定せずに実行すると、未設定のままになっているフラグまたはオプションを示す ConfigurationPathRequiredError が発生します。Nx では、nx.json の @conformetry/nx プラグインの configurationPath オプション、またはエグゼキューターと sync ジェネレーターの configuration オプションが該当します。
inputs も instances もないジェネレーターは有効です。この場合、固定テンプレートがレンダリングされますが、その後に検証されるものはありません。
設定の読み込みが拒否される 4 つの重複
- 2 つのジェネレーターで同じ
nameを使うことはできません。 ホストは最初に見つかったものを解決するため、もう一方には到達できなくなります。 - 2 つのジェネレーターで同じ
templatePathを指定することはできません。 一致するインスタンスがどちらのジェネレーターに属するのか、検証で判別できなくなります。 - 名前を空にしたり、パス区切り文字を含めたりすることはできません。 名前は生成される Nx プラグイン内でファイル名になります。
- 名前に
allを指定することはできません。validate --templates allはすでにすべてのテンプレートを意味しており、この語に応答するジェネレーターがあると、同じコマンドライン上で同じトークンが 2 つの意味を持つことになります。
インスタンスグループ:出力がすでに存在する場所
instances はグループのリストです。各グループには、任意で patterns、exclude、tags、substitutions、threshold を指定できます。グループを使うことで、パスのセットごとに置換内容や適合基準を変えられます。
exclude には、インスタンスとして扱わないパスをワークスペース相対のグロブで指定します。パターンで見つかったディレクトリまたはファイルは、tags の有無にかかわらず、exclude のグロブに一致すると除外されます。実際のインスタンスに混在しているベンダー提供コードや生成コードに使います。たとえば、shadcn のコンポーネント出力には次のように指定します。
exclude: ["projects/lexico/lexico-web/src/components/ui/**"]
Nx プラグインでは、グループの意味を変えるのは tags です。
- タグのあるグループは、プロジェクトセレクターです。 いずれかのタグを持つすべてのプロジェクトに適用され、
patternsは選択された各プロジェクトの内部で読み取られます。そのため、src/modules/*はどのプロジェクトでも同じ意味になります。 - タグのないグループは、ワークスペースのグロブとしてそのまま使われます。
- タグがあり、
patternsがないグループは、場所を特定せずにプロジェクトを選択します。 これは、何も検証せずに、ジェネレーターが対象にできるプロジェクトを絞り込む方法です。
ディレクトリパターンとファイルパターンでは動作が異なり、その違いによって、どのテンプレートが一致するかが決まります。各言語での比較内容については、references/languages.mdを参照してください。
入力
各入力は JSON Schema のフラグメントです。以下のキーが認識されます。それ以外は無視されます。
| キー | 効果 |
|---|---|
description | プロンプトのテキスト |
enum | プロンプトをリストにし、値を制限します |
minLength / maxLength | 長さの検証 |
pattern | Unicode 正規表現として照合されます |
入力が必須かどうかについて、2 つのホストの見解は異なり、設定で変更することはできません。 Nx プラグインは、宣言された入力をすべて必須にします。コマンドラインホストでは、必須の入力はありません。どちらの動作も前提とせず、値がない場合に出力から明らかにわかるようにテンプレートを作成してください。
4 つの入力名は、Nx プラグインで特別な意味を持つため、意図的に使う価値があります。project、module、type、directory は、いずれも出力先を制御します。グループにタグを持つジェネレーターで project という入力を宣言すると、プロジェクトピッカーとしても機能します。
config、help、instancePath、template は予約済みであり、入力として扱われることはありません。コマンドラインホストでレンダリングするテンプレートを選択するには、--template を使います。name は意図的に予約されていません。
フック
ジェネレーターでは、生成の前後にホストが実行する通常の関数として、preGenerate と postGenerate を含む hooks を宣言できます。生成前に不正な入力を拒否したり、テンプレートで編集できないファイル(インデックスや Helm の values ファイルなど)を編集したりする場合に使用します。
preGenerateは、ファイルが何も書き込まれる前に実行されます。この時点でgeneratedFilePathsは空です。実行を拒否するには、例外をスローします。postGenerateは、テンプレートのレンダリング後、フォーマット前に実行されます。generatedFilePathsはソート済みです。
JSON には関数を含められないため、設定の JSON でフックを宣言することはできません。JavaScript または TypeScript の設定であれば、どちらでも宣言できます。両方のホストでフックが正しく動作するよう、次の 3 つのルールに従ってください。
node:fsではなく、context.filesystemを通じて書き込みます。 Nx ではアダプターが仮想ツリーに書き込むため、--dry-runや実行失敗時も変更は残りません。context.configurationDirectoryPathを基に、ワークスペース内の絶対パスをcontext.filesystemに指定します。 Nx では、ワークスペース外のパスはワークスペース内をルートとするパスに変更されます。- 書き込んだパスを
context.generatedFilePathsに追加します。 そうすることで、ホストがそのファイルをフォーマットし、結果を報告します。
コマンドラインでは、postGenerate が例外をスローしても、レンダリング済みのファイルはディスクに残ります。生成に関する README には、コンテキストの全項目をまとめた表と、各ホストでのエラー時の動作が記載されています。また、hooks の例では両方のフックを実行します。
テンプレートの作成
フォルダーが定義そのものです。テンプレートのファイルを登録する必要はありません。
フォルダーを生成するテンプレートには、そのフォルダーを含めます。 その場合、インスタンスパスはそのフォルダーの 親 になります。単独のファイルを生成するテンプレートでは、ルートにファイルを配置します。これを間違えると、出力先が 1 階層ずれてしまいます。
プレースホルダー
レンダリングには Mustache を使用し、HTML エスケープは無効にしています。そのため、{{field}} と記述し、{{{field}}} は使用しないでください。パスにもコンテンツと同じ波括弧を使用します。たとえば、{{nameKebabCase}}.service.ts という名前のファイルは orders.service.ts にレンダリングされます。
名前から派生する、次の 4 種類の命名規則のバリエーションを常に使用できます。
| プレースホルダー | search bar の場合 |
|---|---|
{{nameCamelCase}} | searchBar |
{{nameKebabCase}} | search-bar |
{{namePascalCase}} | SearchBar |
{{nameSnakeCase}} | search_bar |
明示的な入力と設定済みの置換は 最後に 適用されるため、同じ名前の派生バリエーションより常に優先されます。
指定されていないプレースホルダーがあると、生成は拒否されます。 MissingSubstitutionError が発生し、プレースホルダー名とテンプレートファイル名が示されます。そのため、タイプミスがあれば、気付かれないまま空欄や空のパス要素が残るのではなく、明確にエラーになります。
指定されていないプレースホルダーの値は、検証時にインスタンスから読み取られます。 プレースホルダーをランダムな仮値に置き換えてレンダリングし、通常どおり比較します。仮値を含むテンプレートノードがインスタンスのノードと対応する場合、その箇所のインスタンスのテキストが取得されます。最初に取得された値が、ファイル順、次にドキュメント順で採用されます。その値を使ってテンプレートを再度レンダリングし、もう一度比較します。そのため、別の箇所で異なるテキストが使われている場合は、通常の差分として扱われます。対応する箇所がない場合、検証では Could not infer {{path}}: no instance node aligned with the template text that uses it と報告され、どのしきい値でもインスタンスは失敗します。
nameとそのバリエーションは推論されません。インスタンスのパスから取得されます。- 設定済みの
substitutionsの値は、常に推論より優先されます。 - 値の取得方法は、各言語固有のマッチングに従います。TypeScript のノードキー(文字列リテラル、
class {{commandName}}Commandのような宣言名、呼び出しの第 1 引数)、JSON の値、見出しなどの Markdown ノードのテキスト、プレーンテキストの行が対象です。プレースホルダーの前後にあるリテラルテキストは、完全に一致する必要があります。Python、Jupyter、コメント、ファイルパスからは値を取得しないため、それらの箇所にしか使われていないプレースホルダーは指定する必要があります。
省略可能なものをテンプレートで表す方法として、引き続き次の 2 つを使用できます。
- セクションタグ。
{{#owner}}Owner: {{owner}}{{/owner}}と{{^owner}}Unowned.{{/owner}}は条件式です。そのため、ownerが指定されていない場合もエラーにならず、何もレンダリングされません。セクション内で補間し、セクションの外では補間しないでください。 - 指定した空の値。
substitutions: { owner: "" }は値として扱われます。穴になるのはキーが存在しない場合のみです。
したがって、プレースホルダーをテンプレートに追加しても安全に検証できるのは、すべてのインスタンスで比較対象となる箇所にその値が現れる場合に限られます。そうでない場合は、同じ変更で置換も追加してください。
条件付きファイルの仕組みはありません
ファイルごとの条件判定、拡張子によるフィルタリング、スキップリストはありません。ツリー内のすべてのファイルがレンダリングされ、書き込まれます。Mustache のセクションはコンテンツ内では機能しますが、空のプレースホルダーからレンダリングされたパスは、ファイルがスキップされるのではなく、空のパス要素になります。ファイルを省略可能にする方法を探す必要はありません。そのような方法はありません。
値を自由記述として扱う方法
TODO を含むコメントはプレースホルダーとして扱われます。インスタンス内のどのコメントでも、この条件を満たします。インスタンスごとに変わることが正当な文章に使用してください。
文字列リテラルには同等の仕組みはありません。 テンプレート内の文字列は、一字一句そのまま必須です。そのため、プレースホルダーの説明やメッセージを記述すると、すべてのインスタンスに対する恒久的な要件になります。誰も求めていない文言を固定するより、その値をテンプレートに含めないようにしてください。
閾値
適合性は単に合否で判定するのではなく、スコアで評価します。閾値は、インスタンスに許容される最低スコアです。適用順は、最も範囲の狭いものから、インスタンスグループのthreshold、ジェネレーターのthreshold、実行レベルの--threshold、そして1です。
移行中でない限り、設定しないでください。 デフォルトの1は完全一致を意味し、これによってテンプレートは単なる提案ではなく標準となります。既存のインスタンスを新しいテンプレートへ段階的に移行するときは意図的に下げ、インスタンスが追いついたら元に戻してください。閾値を恒久的に下げたままにすることは、テンプレートがもはやインスタンスを表していないということです。
閾値を下げても、レポートは抑制されません。基準を満たしたインスタンスにも差異が表示されます。
設定を変更した後
Nx ジェネレーターの名前空間は設定から生成されます。conformetry のコマンドはすべて、古い定義を使って処理を続けるのではなく、設定からの生成結果が古い場合は実行を拒否します。
nx sync
この領域では、エラーが2種類発生します。どちらも、それぞれに必要な対処法が示されます。
- 設定に対してファイルが古い場合 —
nx syncを実行します。 - ジェネレーターが存在しないテンプレートフォルダーを指定している場合 —
templatePathを修正するか、フォルダーを作成します。
依存関係のインストール時は、生成に失敗してもエラーではなく警告が表示されるため、設定の編集中でも全員のインストールが失敗することはありません。そのため、警告が表示された場合は、実際に対処が必要な内容として確認してください。
作業内容を確認する
インスタンスを生成してから、適合性を確認します。新しく生成したインスタンスは生成時点で適合しているため、差異があればテンプレートと設定が一致していません。結果の読み方についてはconformetry-validateスキルを、生成手順についてはconformetry-generateを参照してください。
読むだけでなく、実際に確認する
conformetry-examplesには、ひとつずつ読み切れる規模の設定を備えた、自己完結型のサンプルが12個あります。設定に関する疑問に答えるサンプルは次のとおりです。
hello-template— 最小限必要なフィールドと、テンプレートの配置場所。case-variants— 派生バリアントと、そのうち1つを上書きする方法。scoring-thresholds— 2つの閾値を持つ2つのインスタンスグループと、3つのレベルのうちどれが優先されるか。ambiguous-attribution— 2つのテンプレートが1つのパスを主張した場合の報告内容と、同じ glob を2回宣言するのが誤りである理由。nx-host— タグでスコープされたインスタンスグループと、プロジェクトグラフを持たないホストがそれらをどう扱うか。hooks— 不正な名前を拒否するpreGenerateと、受領証を書き込むpostGenerate。failure-modes— 誰も値を指定していないプレースホルダーと、インスタンスのテキストからは明らかにならないプレースホルダーを、生成時に拒否し、検証時に報告する方法。
全項目の一覧については、AGENTS.mdを参照してください。