Scaffold a production-grade Roblox project in one command — even on a brand-new machine.
roinit "My Game" --yesThat's it. With --yes, RoInit will:
- Lay down the project skeleton (Rojo + Wally + Selene + StyLua + Lune + Order + CI + Cursor config).
git init+ initial commit.- Install Rokit for you if it's missing (official installer).
- Run
rokit installto fetch the pinned toolchain (rojo, wally, selene, stylua, lune). - Run
wally installto fetch packages (Promise, Signal, Janitor, ProfileStore, Jest). - Open the new project in Cursor if the
cursorCLI is on$PATH.
Drop the --yes and RoInit prompts before each step — same flow, more controlled.
Fresh machine? You only need
bash+curl. RoInit will install everything else.
Every new Roblox project starts with the same boring 90 minutes:
- Google "Rojo vs Argon vs Lync" and pick one.
- Find out about Rokit, install it, pin Rojo to a version that won't bit-rot.
- Discover Wally exists. Set up
Packages/,ServerPackages/,DevPackages/. - Decide on a folder layout. Get it wrong. Refactor it twice.
- Realize you need a module loader. Evaluate Knit vs Flamework vs rolling your own require-all script. Roll your own. Regret it six weeks in.
- Add Selene. Add StyLua. Fight
selene.tomluntilshared(...)stops trippingundefined_variable. - Write a
default.project.jsonthat mounts everything correctly. Find the one missing comma at 2am. - Set up GitHub Actions. Watch the first three runs fail because Wally wasn't installed before Selene ran.
- Configure Luau-LSP, point it at your sourcemap, set up StyLua format-on-save.
- Finally write some game code.
RoInit collapses all of that into one command. Every decision has been made for you by people who ship Roblox games, and every choice is the community-canonical one — not a custom snowflake you'll have to maintain.
my-game/
├── default.project.json # Rojo mount tree, ready to serve
├── rokit.toml # pinned tool versions
├── wally.toml # Promise, Signal, Janitor, Jest, ProfileStore
├── selene.toml + my-game.yml # linter + custom std for `shared(...)`
├── stylua.toml # opinionated formatter config
├── .github/workflows/ci.yml # Selene + StyLua + Lune + rojo build smoke
├── AGENTS.md # AI agent context (Cursor / Claude Code)
├── .cursor/
│ ├── rules/ # auto-applied rules: Order conventions + Luau gotchas
│ └── mcp.json # opt-in template for the Roblox Studio MCP
├── .vscode/
│ ├── settings.json # luau-lsp wired to Rojo, format-on-save, lint-on-save
│ └── extensions.json # recommends luau-lsp, stylua, selene
├── .gitignore
├── README.md
├── src/
│ ├── first/ # ReplicatedFirst splash (pre-Order)
│ ├── framework/ # Order framework, in-tree
│ ├── client/core/{tasks,lib}/ # auto-discovered by Order on the client
│ ├── server/core/{tasks,lib}/ # auto-discovered by Order on the server
│ └── shared/core/{tasks,lib}/ # auto-discovered by Order everywhere
├── tools/
│ ├── build.luau # `lune run tools/build` → .rbxlx
│ └── test.luau # `lune run tools/test` → spec runner
└── tests/
└── example.spec.luau # Jest-Lua sample
RoInit treats Cursor as the default editor and ships configuration so the Cursor agent is productive on day one:
A concise, opinionated summary of the stack, project layout, Order framework,
common commands, and hard rules for any code an agent writes. Cursor (and
Claude Code, and any other agent that reads AGENTS.md) gets the right
context the moment you open the repo.
Three Markdown rules ship pre-installed:
order-conventions.mdc(alwaysApply: true) — explains where code goes (tasks/vslib/vsexternal/), the:Prep()/:Init()lifecycle, theshared(...)global, multi-place routing, and hard security rules. Loaded into every Cursor request automatically.luau-no-chained-assignment.mdc— themyLabel = new("Frame", {...}).Parent = parentparse error that no LLM catches by default.luau-local-register-limit.mdc— the 200-locals-per-function cap that silently kills big UI scripts, with the IIFE and table-collapse escape hatches.
luau-lsp.sourcemap.enabled+autogenerate→ live type info from the Rojo tree, no manualrojo sourcemapruns.luau-lsp.types.roblox: true→ full Roblox API typings.luau-lsp.fflags.enableNewSolver: true→ the new Luau type solver.editor.formatOnSavefor.luauvia StyLua.selene.run: onSavefor inline lint diagnostics.- 100-column rulers, 4-space tabs,
Packages/excluded from search.
Recommends luau-lsp, stylua, and selene — Cursor pops a one-click
"Install All" notification on first open.
Template for wiring the Roblox Studio MCP
so Cursor's agent can talk directly to a running Studio session — read
selections, run commands, edit instances. Uncomment and point command at
your StudioMCP binary.
If the cursor CLI is on $PATH, RoInit offers to open the new project in
Cursor when scaffolding finishes. With --yes it just does it.
RoInit isn't a custom framework — it's a curated bundle of the best-in-class community tools, glued together so they work the moment you clone.
Rokit — toolchain pin
rokit.toml declares exact versions of every CLI tool. rokit install makes
your laptop and CI use the same Rojo, Selene, StyLua, Wally, and Lune binaries
forever. No more "works on my machine because I'm on Rojo 7.4 and you're on
7.6". This is the single biggest time-saver on the list. RoInit installs
Rokit for you on a fresh machine via the official installer script.
Rojo — source ↔ Studio sync
The de-facto standard for treating .luau files on disk as the source of
truth, with live two-way sync into Roblox Studio. Means your code lives in git,
your editor of choice (Cursor / VS Code / Zed), and your usual diff tools.
Wally — package manager
Cargo for Roblox. Pull in Promise,
Signal,
Janitor,
ProfileStore,
Jest-Lua — and version-pin them in
wally.toml. RoInit ships with a sensible default set; add or remove freely.
Selene — linter
Roblox-aware Luau linter. Catches undefined variables, shadowing, and dozens
of footguns before you rojo serve. Pre-configured to understand Roblox APIs
and the shared(...) global that Order installs.
StyLua — formatter
gofmt for Lua. End style debates forever. CI runs stylua --check src/ on
every push so nothing un-formatted hits main.
Lune — standalone Luau runtime
Run Luau scripts outside Roblox — no Node.js, no Python, no Bash gymnastics.
RoInit uses Lune for tools/build.luau (build a .rbxlx) and
tools/test.luau (discover and run Jest specs). Once you have Lune, you'll
write everything else in it too.
Order — module loader + lifecycle
The piece every Roblox project ends up needing and most reinvent. Order:
- Auto-discovers every module under
tasks/folders and runs them on boot. No more 80-lineinit.server.luauwithrequire(...)afterrequire(...). - Gives every task an optional
:Prep()(sync) and:Init()(async) lifecycle hook withPriorityordering. - Installs a global
shared(...)callable so any module can grab any other by short name —shared("Profile")findssrc/server/core/lib/Profile.luauno matter where it's required from. - Multi-place support built in. Map
PlaceId→PlaceTypeinframework/Settings.luau, then add code-group folders next tocore/(lobby/,arena/,tutorial/). Each place loads only the groups it needs. Ship a lobby + game from one repo withoutif game.PlaceId == ...branches scattered across your codebase.
RoInit ships a minimal in-tree implementation of Order so you have zero
external dependencies on day one. When the upstream Wally package lands, swap
the mount in default.project.json and delete src/framework/.
Jest-Lua — tests
Real describe / it / expect for Luau. Specs live in tests/*.spec.luau
and are discovered by lune run tools/test.
ProfileStore — saves
Pre-wired in wally.toml (server realm). The community-canonical wrapper
around DataStoreService — handles session locking, the auto-save loop, and
graceful shutdowns. You should not be writing to DataStoreService directly
in 2026.
curl -fsSL https://raw.githubusercontent.com/rib3ye/RoInit/main/roinit \
-o /usr/local/bin/roinit && chmod +x /usr/local/bin/roinitThen anywhere:
roinit "My Game" --yes # totally fresh machine? this is all you need.git clone https://github.com/rib3ye/RoInit ~/code/RoInit
ln -s ~/code/RoInit/roinit /usr/local/bin/roinitroinit is a single self-contained Bash script. Drop it anywhere on your
$PATH. The script itself only needs bash, curl, and standard Unix
tools (sed, awk, tr); git is optional. Everything else (Rokit, Rojo,
Wally, Selene, StyLua, Lune) is installed for you.
roinit <project-name> [--author <name>] [--dir <path>]
[--yes] [--skip-install] [--no-git] [--no-cursor]
| Flag | Behavior |
|---|---|
--yes, -y |
Assume yes to every prompt. Required for non-interactive use (CI, piped scripts). |
--skip-install |
Scaffold files only. Don't install Rokit, don't run rokit/wally install. |
--no-git |
Skip git init + initial commit. |
--no-cursor |
Don't auto-open in Cursor even if the CLI is on $PATH. |
--author <name> |
Author baked into wally.toml and the README (default "You"). |
--dir <path> |
Target directory (default ./<slug> in CWD). Refuses to overwrite a non-empty directory. |
# Fresh machine, fully automated:
roinit "My Game" --yes
# Interactive — RoInit prompts before installing tools / opening Cursor:
roinit "My Game"
# Just lay down files, decide what to install yourself:
roinit "My Game" --skip-install --no-cursor
# Customize for a studio:
roinit "Lobby" --author "Acme Studios" --dir ~/code/acme-lobby$ roinit "My Game" --yes
Scaffolding My Game
slug: my-game
pascal: MyGame
author: You (you)
target: /Users/.../my-game
Initialized git repo with initial commit.
Environment check:
✓ git git version 2.50.1
✗ rokit (not installed — needed for the pinned toolchain)
· wally (not installed — `rokit install` will install it)
· rojo (not installed — `rokit install` will install it)
· lune (not installed — `rokit install` will install it)
✓ cursor (CLI on PATH)
Rokit isn't installed. It's the toolchain manager that pins your
rojo / wally / selene / stylua / lune versions to what's in rokit.toml.
? Install Rokit now via the official installer? [Y/n] (auto-yes)
Installing Rokit (the toolchain manager)…
✓ Rokit installed: rokit 1.2.0
? Run `rokit install` to fetch the pinned toolchain? [Y/n] (auto-yes)
Running: rokit install
? Run `wally install` to fetch packages? [Y/n] (auto-yes)
Running: wally install
[INFO ] Downloaded 52 packages!
? Open my-game in Cursor now? [Y/n] (auto-yes)
Opening Cursor…
✓ Done. Project is at: /Users/.../my-game
You're now in Cursor with Luau-LSP wired up, ready to rojo serve.
cd my-game
rojo serve default.project.json # then Connect from the Rojo Studio plugin
# in other terminals as you work:
selene src/ # lint
stylua src/ # format
lune run tools/test # discover + run Jest specs
lune run tools/build # build a .rbxlx without serving- Tasks (auto-loaded on boot): drop a module under
src/<context>/core/tasks/. Optional:Prep()(sync) and:Init()(async) hooks fire inPriorityorder. Seesrc/framework/Settings.luaufor the lifecycle schema. - Libraries (loaded on demand): drop a module under
src/<context>/core/lib/. Pull it from anywhere withlocal M = shared("ModuleName"). - Multi-place: map
PlaceId→ place type inSettings.PlaceTypes, then add code-group folders (game/,lobby/, ...) next tocore/.
- A UI framework. Fusion,
Vide, and
React-Lua all have strong cases.
Pick one and add it:
wally add elttob/fusion@^0.3(etc.). - A networking layer. Zap, ByteNet, and BridgeNet2 all want different trade-offs. Add the one you want — RoInit doesn't pre-commit you.
- An ECS. Matter is great but highly opinionated; it belongs in projects that need it, not in every project.
- Game code. RoInit is scaffolding only. Zero gameplay assumptions.
I already have Rokit / Rojo / Wally installed. Will RoInit re-install them?
No. roinit detects existing tools and skips install steps for anything
already on $PATH. With --yes it runs rokit install (idempotent — pulls
only what's missing) and wally install.
Will this work on Windows?
The script is Bash. WSL works fine. Native Windows + Git Bash should work but
isn't tested — PRs welcome. On Windows-native, you can also install Rokit
manually via the PowerShell installer
and run roinit ... --skip-install.
Can I use RoInit without Cursor?
Yes. .cursor/rules/ and AGENTS.md are harmless to other tools. .vscode/
settings work in plain VS Code. Pass --no-cursor to skip the auto-open
prompt.
Can I customize what gets scaffolded?
roinit is a single ~900-line Bash script. Fork it, edit the heredocs, done.
There's no plugin system because Bash heredocs are the plugin system.
Why Order instead of Knit / Flamework / Sapphire?
Order is the smallest framework that covers the 90% case (auto-discovery, lifecycle, place-type routing) without imposing a service/controller metaphor. The in-tree implementation is ~340 lines of Luau — small enough to read in one sitting and patch when you need to.
Why bundle ProfileStore but not, say, Trove or DataLink?
ProfileStore solves the universal problem (player saves) and has no real
competitor in 2026. Trove/Janitor are duplicates — RoInit ships Janitor
because it's better-typed; swap to Trove in wally.toml if you prefer.
Can I publish to Wally with this layout?
Yes — the wally.toml [package] block is filled in with your slug and
author. Edit version and description, then wally publish.
MIT. See LICENSE.
Issues and PRs welcome. The bar is: does this make a brand-new Roblox project better, faster, or more reproducible without locking the user into RoInit?
If yes, ship it.