Documentation menu

The manifest

[tools], [scripts] & [studio]

Last updated October 22, 2026

Three tables about the project's surroundings: the binaries it pins, the scripts it runs, and what it opens in Studio.

[tools]#

[tools]
rojo = "rojo-rbx/rojo@7.7.0"
stylua = "JohnnyMorganz/StyLua@2.3.0"

The key is the alias: the command name you type, and the name of the shim embr install puts on PATH. The value is a single string, always the full owner/repo@version:

  • owner/repo is the GitHub repository. Unlike package names, it may contain uppercase and dots (JohnnyMorganz/StyLua) — the shape just has to be exactly one / with both halves non-empty.
  • @version is an exact release version, no leading v, no ranges. Tools have no lockfile entries because the pin already is one.

No shorthands in the manifest. The names embr tool add accepts (create-chief-project, darklua, lest, luau-lsp, rojo, stylua) are conveniences of that command — it resolves them and writes the full owner/repo@version here. The file always spells everything out.

embr and embx are reserved aliases — a shim under either would shadow Ember's own binaries, so both embr tool add and a hand-written entry fail with Alias 'embx' is reserved for embr itself and can't name a tool.

[scripts]#

[scripts]
build = "rojo build -o game.rbxl"   # build/test/start/serve/dev/fmt drop the `run`
fmt = "stylua src"
serve = ["larvae process -w", "rojo serve"]   # a list runs at once
prebuild = "rm -rf build"           # hooks are just pre<name>/post<name> entries
postinstall = "embr build"           # commands hook their verb: install, add, publish

Values are shell strings, run with embr run <key> through the platform shell (sh -c on unix, cmd /C on Windows), forwarding the exit code. Pinned tools are on PATH inside scripts, at the project's pinned versions.

A value can also be a list, and then its commands run at once, with output tagged [1], [2] — no concurrently equivalent needed. Every command runs to its own end and Ember exits with the first non-zero code. An empty list (serve = []) is an error, not a script that does nothing. (embr run)

Two things the keys mean beyond "a script":

  • build, test, start, serve, dev and fmt can be run without run (embr build). Only those six, and embr format is an alias of embr fmt. A key that starts with one of them and a colon drops run too: embr build:prod or embr dev:gameplay. (embr run)
  • A key named pre<something> or post<something> is a hook, run around the script or command of that name — as long as something answers to that name. Nothing enables it; the name is the whole mechanism. (Lifecycle hooks)

Bare embr run lists everything in the table, grouped into scripts, lifecycle scripts, and hooks.

[studio]#

[studio]
universe = 13058
place = 1818
# file = "game.rbxl"     # the other form — never both

What embr studio open opens: either a published place (both universe and place, positive integers) or a local place file (file, a .rbxl/.rbxlx path relative to ember.toml) — one form only. embr studio init writes the table.

A typo'd [studio] key never breaks other commands — the manifest still parses; only studio open validates the table, and it names the unknown key (universeId gets called out, not silently ignored).