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_settingsand.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.