mcpField
R
roblox-toolchain

roblox-toolchain

github.com/afrxo開発1259 回インストール26 週間前に更新
リポジトリ

roblox-toolchain について

roblox-toolchainは、ファイルを中心にRobloxゲームを開発するためのエージェントスキルです。Rojo、Rokit、WallyまたはPesdeによるプロジェクト設定、ファイルとDataModelの対応、ツールのバージョン固定、Luau LSPの設定を解説します。

主な機能

  1. 01Rojoによるファイルベース開発ガイド
  2. 02Rokitでツールのバージョン固定
  3. 03WallyまたはPesdeで依存関係を管理
  4. 04プロジェクトファイルとDataModelの対応付け
  5. 05Luau LSPのsourcemap設定
  6. 06既存コードベースに合わせた統合ルール

活用シーン

  1. 01ファイルからRobloxゲームを開発
  2. 02チームでRojoなどのツール版を固定
  3. 03WallyまたはPesdeの依存関係を設定
  4. 04Luau LSPの補完を設定

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/afrxo/roblox-agent-skills --skill roblox-toolchain

インストール後、Claude Code で/roblox-toolchainを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

examples/
.gitkeep
ci.yml
default.project.json
file-tree.md
pesde.toml
rokit.toml
wally.toml
references/
luau-lsp-setup.md
pesde-manifest.md
project-format.md
sync-mapping.md
wally-manifest.md

詳細

Roblox Rojo(ファイルシステムを使ったワークフロー)

Studio 内ではなくディスク上のファイルを使って Roblox ゲームを開発する方法です。情報源:rojo.space(Rojo 公式ドキュメント)、github.com/rojo-rbx/rojo(Rojo のソース)、github.com/rojo-rbx/rokit(Rokit ツールチェーンマネージャー。Aftman/Foreman ではなくこちらを使用)、github.com/UpliftGames/wally(Wally パッケージマネージャー)、github.com/pesde-pkg/pesde(Pesde。新しい代替パッケージマネージャー)。ツール:stylua、selene、luau-lsp。

詳しくは、以下を参照してください。


統合ポリシー

このスキルでは推奨パターンを説明していますが、既存のコードを書き換えることを許可するものではありません。ルールは新しいコードと、ユーザーが明示的に依頼した変更に適用してください。**コードベースで既に使われているツールチェーンに合わせてください。**プロジェクトで Aftman が使われている場合は、求められていない限り Rokit への移行を行わないでください。Wally が使われている場合は、Pesde を提案しないでください。default.project.json が特定の構造に従っている場合は、書き換えずに拡張してください。競合があれば一度だけ指摘し、既存の設定を優先してください。

ルールの全文:../../shared/integration-policy.md。


原則

  • **唯一の信頼できる情報源はファイルシステムです。**リポジトリが正本で、Studio はビルド対象です。
  • ツールチェーンのバージョンはプロジェクトごとに固定します。rokit.toml には rojo、wally(または pesde)、stylua、selene、luau-lsp の正確なバージョンを記載します。「自分の環境では動く」より、再現可能なビルドを優先してください。
  • **sourcemap はコミットせず、再生成します。**生成される出力です。依存関係が変更されたら再生成してください。
  • CI でビルドと lint を実行します。main がグリーンなら、rojo build が有効な .rbxl を生成し、lint も合格していることを意味します。
  • **Packages/ は生成物です。**Wally が生成するもので、手動編集はしません。また、.gitignore に含めます。

Rojo の基本

インストール

Rokit(Foreman/Aftman の後継となるツールチェーンマネージャー)を使い、プロジェクトごとにバージョンを固定します。

# rokit.toml — drop-in compatible with foreman.toml / aftman.toml format
[tools]
rojo = "rojo-rbx/[email protected]"
wally = "UpliftGames/[email protected]"
stylua = "JohnnyMorganz/[email protected]"
selene = "Kampfkarren/[email protected]"

その後、プロジェクトのルートで rokit install を実行すると、指定した正確なバージョンが取得されます。グローバルにインストールされたツールに頼らないでください。マシンごとにバージョンがずれていきます。

**Aftman ではなく Rokit を使う理由:**Aftman はメンテナンスされていません(サードパーティの作者は Roblox での業務を終了しています)。Foreman は Roblox によってメンテナンスされていますが、内部利用向けです。Rokit はコミュニティによってメンテナンスされており、どちらのマニフェスト形式ともそのまま互換性があり、インストールも大幅に高速です。移行するには、aftman.toml を rokit.toml に名前変更します。

Rokit の一般的なコマンド:rokit init、rokit add OWNER/REPO、rokit install、rokit update、rokit list、rokit self-update。

2 つのモード
# Live sync — Studio plugin connects to this server, applies changes as you save.
rojo serve [path/to/project.json]

# One-shot build — produces a .rbxl (place) or .rbxm (model).
rojo build [path/to/project.json] --output build/place.rbxl

rojo serve は開発用です。rojo build は CI と最終的な公開用です。ライブ変更を実際に適用するのは、Studio のプラグインタブからインストールする、CLI とバージョンを合わせた Studio プラグインです。

プロジェクトファイルの場所

Rojo は現在のディレクトリにある default.project.json を探します。別の .project.json ファイルを使うには、明示的にパスを指定してください。複数のビルド対象(ゲーム、プラグイン、ライブラリ)があるリポジトリでは、通常、対象ごとにプロジェクトを 1 つ用意します。

default.project.json の構造

{
  "name": "MyGame",
  "tree": {
    "$className": "DataModel",

    "ReplicatedStorage": {
      "$className": "ReplicatedStorage",
      "$path": "src/ReplicatedStorage"
    },

    "ServerScriptService": {
      "$className": "ServerScriptService",
      "$path": "src/ServerScriptService"
    },

    "StarterPlayer": {
      "$className": "StarterPlayer",
      "StarterPlayerScripts": {
        "$className": "StarterPlayerScripts",
        "$path": "src/StarterPlayerScripts"
      }
    },

    "Workspace": {
      "$className": "Workspace",
      "$properties": {
        "Gravity": 196.2
      }
    }
  }
}
  • name(必須)— ビルド成果物の名前として使用されます。
  • tree(必須)— ルート Instance の記述です。
  • tree 内:
    • $className — Instance のクラスです。$path で解決される場合、またはキーがサービス名の場合は省略可能です。
    • $path — この Instance の下にマウントするディスク上のフォルダー/ファイルです。
    • $properties — 設定するプロパティです(例:Gravity、HttpEnabled)。
    • $ignoreUnknownInstances — true の場合、Rojo は同期しなかった Instance を削除せず、そのまま残します。
    • その他のキー — 子 Instance の記述です。

その他のトップレベルフィールド:servePort(デフォルトは 34872)、servePlaceIds(誤って別のゲームに同期しないようにするための place ID の許可リスト)、placeId、gameId、serveAddress、globIgnorePaths、emitLegacyScripts。

emitLegacyScripts は、*.server.luau/*.client.luau が、レガシーな Script/LocalScript Instance を生成するか、RunContext が設定された Script Instance を生成するかを制御します。ドキュメントに記載されているデフォルトは true です。決めつける前に、インストール済みの Rojo のバージョン(rojo --version とリリースノート)を確認してください。新しいプロジェクトでは、最新の RunContext を使用するために false を設定してください。roblox-dev の script-types セクションを参照してください。

スキーマの全容:references/project-format.md。


ファイルシステムから DataModel へのマッピング

これは頻繁に参照するルールです。よく使うものを覚えておきましょう。

ディスク上のパス変換後
dir/(任意のディレクトリ)Folder
foo.luaufoo という名前の ModuleScript(Rojo はレガシーな .lua も受け付けます)
foo.server.luaufoo という名前の Script(サーバー)
foo.client.luaufoo という名前の LocalScript(クライアント)
dir/init.luaudir という名前の ModuleScript(ディレクトリがスクリプトになります)
dir/init.server.luaudir という名前の Script(ディレクトリがサーバースクリプトになります)
dir/init.client.luaudir という名前の LocalScript(ディレクトリがローカルスクリプトになります)
foo.rbxm/foo.rbxmxバイナリ/XML 形式のモデル
foo.csvLocalizationTable
foo.txtStringValue
foo.json(.model.json/.project.json 以外)テーブルを返す ModuleScript
foo.tomlテーブルを返す ModuleScript
foo.model.jsonJSON で記述されたモデル(手書き用。RemoteEvent などに便利)
foo.project.jsonネストされたプロジェクト(親に合成されます)
foo.meta.json対応するファイル/ディレクトリに付加されるメタデータのサイドカーファイル
init.luau のセマンティクス

ディレクトリと init.luau は 1 つの ModuleScript になり、そのディレクトリ内のほかの子要素は、そのスクリプトの子要素になります。別のフォルダーを作らずに、スクリプトにサブモジュールを持たせることができます。

src/Inventory/
├── init.luau          # ModuleScript "Inventory"
├── add.luau           #   ModuleScript "add" (child of Inventory)
├── remove.luau        #   ModuleScript "remove"
└── types.luau         #   ModuleScript "types"

各ディレクトリに置ける init.* ファイルは 1 つだけです(init.luau、init.server.luau、init.client.luau のいずれか 1 つ)。

Meta ファイル

foo.meta.json は、Rojo 固有のメタデータを foo.* に付加します。一般的な用途:

// init.meta.json — turn the parent folder into a Tool with a Grip
{
  "className": "Tool",
  "properties": {
    "Grip": [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1]
  }
}
// foo.meta.json — disable a script
{
  "properties": { "Disabled": true }
}
// hello.meta.json — let Rojo leave Instances under hello.txt alone
{
  "ignoreUnknownInstances": true
}

className が機能するのは init.meta.json のみです。properties はモデル以外の任意のファイルで機能します。

マッピング表の全容:references/sync-mapping.md。


推奨されるプロジェクト構成

my-game/
├── rokit.toml                # toolchain pinning
├── default.project.json       # Rojo project file
├── wally.toml                 # package manifest
├── wally.lock                 # lockfile (committed)
├── stylua.toml                # formatter config
├── selene.toml                # linter config
├── sourcemap.json             # generated; .gitignore'd
├── Packages/                  # wally output; .gitignore'd
├── ServerPackages/            # wally output; .gitignore'd
├── DevPackages/               # wally output; .gitignore'd
├── .github/workflows/ci.yml   # CI
├── (editor config)            # .vscode/settings.json, .nvim, etc. — editor-specific
├── .gitignore
├── README.md
└── src/
    ├── ReplicatedStorage/
    │   ├── Shared/
    │   │   ├── init.luau
    │   │   └── ...
    │   └── Client/             # (optional) client-only scripts via RunContext
    ├── ServerScriptService/
    │   ├── init.server.luau
    │   └── Systems/
    └── StarterPlayer/
        └── StarterPlayerScripts/
            └── init.client.luau

src/ のディレクトリ名を DataModel のマウント先に合わせてください。パスを見れば、コードがどこで実行されるか正確に分かります。


Wally(パッケージ)

Rokit 経由でインストールしてください(グローバルから取得しないでください)。rokit.toml に追加します。

[tools]
wally = "UpliftGames/[email protected]"

次に rokit install を実行します。コマンド:

wally init               # scaffold wally.toml
wally install            # download deps into Packages/
wally install --locked   # CI; fail if lockfile is stale
wally update [name...]   # bump deps
wally publish            # push your package to the registry
wally search <query>     # find packages
wally.toml
[package]
name = "yourname/coolpkg"        # SCOPE/NAME, lowercase, dashes ok
version = "1.0.0"                # SemVer
license = "MIT"                  # SPDX
authors = ["Your Name <[email protected]>"]
realm = "shared"                 # "shared" or "server"
registry = "https://github.com/UpliftGames/wally-index"

[dependencies]
React = "jsdotlua/[email protected]"
Promise = "evaera/[email protected]"

[server-dependencies]
ProfileService = "loleris/[email protected]"

[dev-dependencies]
Jest = "jsdotlua/[email protected]"
Realm
  • shared — クライアントに複製されます。ReplicatedStorage の下にマウントします。
  • server — サーバー専用です。ServerStorage または ServerScriptService の下にマウントします。
  • client realm はありません。クライアント専用の依存関係は shared に配置し、インポートによってクライアント上で実行します。
Rojo での Wally 出力のマウント
"ReplicatedStorage": {
  "$className": "ReplicatedStorage",
  "Packages": {
    "$path": "Packages"
  }
},
"ServerScriptService": {
  "$className": "ServerScriptService",
  "Packages": {
    "$path": "ServerPackages"
  }
}

パッケージは realm ごとに別のフォルダーにインストールされます。Shared は Packages/、server は ServerPackages/、dev は DevPackages/ に配置されます。

Lockfile

wally.lock には、すべての依存関係(推移的依存関係を含む)の正確なバージョンが固定されます。コミットしてください。 CI で wally install --locked を実行すると、全員が同じものをビルドできます。

マニフェストの全フィールド、ロックファイルの形式、コマンド一覧については、references/wally-manifest.md を参照してください。


Pesde(代替パッケージマネージャー)

Pesde は、新しい Luau ファーストのパッケージマネージャーです。ランタイムのロックインを防ぐよう設計されています。1 つのツールで複数の Luau ランタイム(luau、lune、roblox、roblox_server)を対象にでき、ブリッジ経由で既存の Wally レジストリからパッケージを取得できます。次のような場合におすすめです。

  • 純粋な Luau、Lune、Roblox のプロジェクト全体で、パッケージマネージャーを統一したい場合。
  • 同じプロジェクトで Wally パッケージとネイティブの pesde パッケージの両方が必要な場合。
  • Wally の Cargo 風の操作性よりも、npm/pnpm 風の操作性を好む場合。
pesde.toml
name = "yourname/coolpkg"
version = "1.0.0"
license = "MIT"

[target]
environment = "roblox"     # luau | lune | roblox | roblox_server
lib = "src/init.luau"

[indices]
default = "https://github.com/pesde-pkg/index"

[wally_indices]
default = "https://github.com/UpliftGames/wally-index"

[dependencies]
# Native pesde dep
hello = { name = "pesde/hello", version = "^1.0.0" }
# Wally dep via the bridge
React = { wally = "jsdotlua/react", version = "^17.1.0" }

[dev_dependencies]
Jest = { wally = "jsdotlua/jest", version = "^3.10.0" }
コマンド
pesde init        # scaffold pesde.toml
pesde add SCOPE/NAME   # add + install a dep
pesde install     # install all deps; writes pesde.lock
pesde run         # run [scripts] entries (uses Lune)
pesde publish
ディレクトリ構成
  • ネイティブの pesde 依存関係は、ターゲット名のフォルダー(roblox_packages/、luau_packages/ など)にインストールされます。
  • Wally ブリッジの依存関係は、引き続き wally-index リポジトリ経由で解決されます。
  • pesde.lock がロックファイルです。コミットしてください。
  • Roblox プロジェクトでは、pesde はスクリプトパッケージ経由で Rojo 互換のソースマップを生成します。rojo sourcemap と組み合わせてください。
どちらを選ぶか
必要なもの選択肢
成熟していて、Roblox 専用で、大規模な既存エコシステムWally
複数のランタイム(Lune CLI ツール、Roblox、プレーンな Luau)Pesde
Cargo 風の操作性Wally
npm/pnpm 風の操作性と Wally ブリッジPesde
Wally を使っている既存のプロジェクトで、特に問題がないそのまま使う

Wally と Pesde は、そのまま置き換えられるものではありません。マニフェスト形式と依存関係の解決方法が異なります。理由もなく、プロジェクトの途中で切り替えないでください。


ソースマップ(Luau LSP)

Luau LSP が適切な自動補完と require() の解決を行うには、ファイルが DataModel 内のどこに対応するかを把握する必要があります。Rojo がマップを生成します。

# Watch mode — regenerates on filesystem change
rojo sourcemap --watch --output sourcemap.json default.project.json

# One-shot
rojo sourcemap --output sourcemap.json default.project.json

次に、luau-lsp にマップを指定します。エディターごとの設定は次のとおりです。

  • VS Code(luau-lsp 拡張機能): .vscode/settings.json(またはワークスペースレベルの設定)に "luau-lsp.sourcemap.sourcemapFile": "sourcemap.json" を記述します。
  • Neovim / Helix / Sublime: LSP の起動引数(--definitions=... / --sourcemap=...)または LSP クライアントの設定から、ソースマップのパスを渡します。luau-lsp バイナリのドキュメントにフラグが記載されています。
  • CLI モード: luau-lsp analyze --sourcemap sourcemap.json ... を実行します。正確なフラグは、インストール済みの luau-lsp --help で確認してください。

次の後に再生成してください。

  • プロジェクト内のファイルを追加または削除したとき。
  • wally install を実行したとき(新しいパッケージパスが追加されます)。
  • default.project.json のマウントを変更したとき。

一般的なワークフローでは、ターミナルで rojo sourcemap --watch を実行しながら、rojo serve も実行します。どちらもセッション中は実行し続けます。

sourcemap.json は生成物なので、.gitignore に追加してください。

LSP の設定の詳細については、references/luau-lsp-setup.md を参照してください。


リントとフォーマット

StyLua(フォーマッター)
# stylua.toml
column_width = 100
line_endings = "Unix"
indent_type = "Tabs"          # or "Spaces" with indent_width = 4
quote_style = "AutoPreferDouble"
call_parentheses = "Always"

[sort_requires]
enabled = true                # alphabetize the require block; pairs with luau-expert guidance

stylua src/ で実行します。StyLua 拡張機能をインストールすれば、ほとんどのエディターで保存時に自動フォーマットできます。

selene(リンター)
# selene.toml
std = "roblox"                # roblox stdlib definitions

# Optional: per-rule tweaks
[config]
incorrect_standard_library_use = "warn"

重要なのは std = "roblox" の指定です。これがないと、selene はすべての Instance.new と task.wait に警告を出します。selene src/ で実行します。

Luau LSP(型チェッカー)

luau-lsp は、エディター内での型チェック、ホバー情報、自動補完を提供します。網羅性を最大限に高めるには、ファイルごとに --!strict と組み合わせてください(luau-expert スキルを参照)。

プロジェクトレベルの設定(.luaurc):

{
  "languageMode": "strict",
  "lint": {
    "*": true
  }
}

スキーマは luau.org/lint で確認してください。.luaurc のフィールドは変更される場合があります。


CI

最小限の CI 実行手順:

  1. Rokit をセットアップ(rokit install)して、固定されたバージョンのツールをインストールします。
  2. wally install --locked — ロックファイルに差異があれば失敗します。
  3. stylua --check src/ — フォーマットに差異があれば失敗します。
  4. selene src/ — lint を実行します。
  5. rojo sourcemap --output sourcemap.json default.project.json — マップを生成します。
  6. ソースマップを使用して luau-lsp analyze — 型チェックを行います。正確なフラグはインストールされているバージョンによって異なります(--sourcemap または --definitions)。luau-lsp --help を確認してください。
  7. rojo build default.project.json --output build/place.rbxl — ビルド成果物を生成します。
  8. (任意) place.rbxl を成果物としてアップロード/公開します。

各ステップで失敗すると、次のステップには進みません。CI が成功すれば、ツールのバージョンが固定され、依存関係がロックされ、フォーマットと lint、型チェックに問題がなく、ビルドも成功したことを意味します。

GitHub Actions の例は examples/ci.yml にあります。


検証ルール

  • .project.json のフィールド名は、name、tree、$className、$path、$properties 以外を記憶に頼って記載しないでください。スキーマ全体は短いため、あまり一般的でないフィールドを使用する前に references/project-format.md を確認してください。
  • Wally のバージョン指定の仕様を記憶に頼って説明しないでください。Wally はデフォルトで ^ を使用し、Cargo 方式の SemVer に従います。~、=、* の詳細を確認し、デフォルト以外のバージョン指定子を推奨する前に Wally のドキュメント を参照してください。
  • emitLegacyScripts のデフォルト値はリリースによって変わっています。 Script と Script(RunContext=Server) の違いを前提とする前に、プロジェクトで使用している Rojo のバージョン(rojo --version)を確認してください。
  • エディターの設定は異なります。 このスキルが対象とするのは Luau LSP レイヤーです。参考資料にある .vscode/settings.json の例は説明用です。Neovim/Helix/Sublime を使用する場合は、対応する設定項目を設定してください。
  • Rojo とエンジンを混同しないでください。 RunContext の配置、レプリケーション、DataModel の仕様は roblox-dev の対象です。このスキルの対象は「ファイルがこの DataModel パスに配置される」までです。

アンチパターン

❌ やってはいけないこと✅ こうしましょう
グローバルにインストールした rojo/wally/stylua を使うrokit.toml でプロジェクトごとにバージョンを固定する
新しいプロジェクトで Aftman または Foreman を使うRokit を使う(ドロップインの後継で、コミュニティによって保守されており、より高速です)
Packages/ を手動で編集する生成物として扱う。wally install で再生成されます
Packages//ServerPackages//DevPackages/ をコミットする.gitignore に追加する
sourcemap.json をコミットする.gitignore に追加し、必要に応じて再生成する
wally.lock を Git に追加し忘れるコミットする。CI では --locked を使用します
1 つのフォルダーに複数の init.* を置くディレクトリごとに init スクリプトを 1 つだけ置き、代わりにサブモジュールを使う
ServerScriptService のマウント先に init.client.luau を置くスクリプトの種類をコンテナーに合わせる
std = "roblox" を設定せずに selene を使う必ず設定する。設定しないと、Roblox API のすべてで lint エラーになります
Studio とファイルシステムを同時に編集するファイルシステムを正とする。rojo serve を実行していないときは Studio を閉じる
rojo build で生成した place ファイルをチェックインするCI の成果物のみとする。バイナリの place ファイルは差分を確認できません
Packages を ReplicatedStorage のみにマウントし、サーバー用依存関係も使用するServerPackages をサーバーコンテナーに個別にマウントする
クライアント動作を期待して、StarterPlayerScripts のマウント先に通常の *.luau を置く*.client.luau(レガシー)または RunContext=Client の Script を使う
保存のたびに rojo sourcemap を手動で再実行する長時間実行するターミナルで --watch を使う
作業ツリーが汚れた状態で wally publish を実行するクリーンなコミットにタグを付け、CI から公開する
ソースマップなしで luau-lsp を使うソースマップを生成する。LSP は require() の解決にソースマップを必要とします

例

  • examples/default.project.json — 標準的なマウントをすべて網羅した、一般的な配置のプロジェクトです。
  • examples/wally.toml — [dependencies]、[server-dependencies]、[dev-dependencies] を含む、注釈付きの Wally マニフェストです。
  • examples/pesde.toml — [target]、[indices]、[wally_indices]、[dependencies] を含む、注釈付きの Pesde マニフェストです。
  • examples/rokit.toml — ツールチェーンのバージョン固定です。
  • examples/file-tree.md — ファイルシステムと DataModel の対応を示す、リポジトリ全体のレイアウトです。
  • examples/ci.yml — GitHub Actions ワークフローです。Rokit のインストール → wally install --locked → stylua check → selene → rojo build の順に実行します。

コメント