Log inGet started

The filesystem (VFS)

The engine's state is exposed as a filesystem under /zero. This is a genuine superpower for understanding what exists — you navigate entities, components, assets, and live runtime state with the same…

The two trees

  • /zero/source/… — the authored world: your assets, scenes, components, code, plus .world_settings and .world_entrypoint.luau. Durable and shared (the engine + worlds guides).
  • /zero/runtime/… — live engine state: the loaded scene layers and their entities, lighting, generated meshes, render surfaces, logs. Transient — it reflects the running world, not saved content.

Reading runtime state

Entities are folders under /zero/runtime/layers/<layer>/entities/. Read them like files:

ls  /zero/runtime/layers/main/entities/              # every entity in the layer
cat /zero/runtime/layers/main/entities/lantern       # summary: name, id, transform
cat /zero/runtime/layers/main/entities/lantern/position   # {"x":..,"y":..,"z":..}
ls  /zero/runtime/layers/main/entities/lantern/components  # what's attached

This is the fastest way to answer "what's in the scene right now," "where is this entity," "what components does it have" — and it composes with the shell: grep, find, pipes, and .sh scripts all work over /zero.

Reading source

/zero/source is your authored content as files. Asset folders carry a type suffix (Foo.component/, Bar.material/); cat one for its summary, ls it for its contents, and edit files inside to change them — components, materials, modules, and the like hot-reload.

ls  /zero/source                                     # libs, scenes, .world_settings, …
cat /zero/source/Spinner.component                   # asset summary

Mutation applies on the next frame

The filesystem isn't read-only — writes to runtime state take effect, but asynchronously, applied on the next frame. Writing an entity's position file moves it; removing its folder despawns it. The Luau API does the same things synchronously (visible the same frame), which is why it's what you reach for in code — but the filesystem is a genuine write surface too, useful from the shell and scripts.

entity(id).position = { 0, 5, 0 }   -- API: applies this frame
echo '{"x":0,"y":5,"z":0}' > /zero/runtime/layers/main/entities/lantern/position   # VFS write: applies next frame
rm -rf /zero/runtime/layers/main/entities/lantern                                   # despawns it (next frame)

One practical consequence of the async path: right after a VFS write, a same-call API read can still see the old value — it settles on the next frame. Read it back a frame later, or mutate through the API when you need same-frame certainty.

The shape of /zero

/zero/
  source/      authored world — assets, scenes, code, .world_settings, .world_entrypoint.luau (durable, shared)
  runtime/     live state — layers/<layer>/entities/, lighting, generated_*, render_surfaces, logs, events/ (component-event publishers + subscriptions)
  docs/        API reference + guides

The model to carry: the engine describes itself as a filesystem you can read — use it to inspect and discover (alongside lsp.* and the registries, the discovering guide), and use the API to change things.

  • documentation
  • guide