The Editor
The editor is where a project is authored: entities are spawned, components are attached and tuned, and the result is played back without leaving the window.
It is one program that runs in two arrangements, and the difference matters more than it looks.
Two arrangements, one editor
Embedded — the project’s own binary opens the editor:
cargo run # inside your project directory
The editor runs inside the project, so the project’s components are simply linked in. This is the simplest arrangement and needs no socket, no second process, and nothing to go wrong between them.
Standalone — the editor opens, and you point it at a project:
cargo run -p kooch_editor # from the engine repo
# then: Open Project
Here the editor is a separate program that does not have your project’s types compiled in. It gets them two ways at once:
- It loads the project’s
dylibto learn what components exist and what fields they have, which is what fills the Add Component menu and the Inspector. - It launches the project as a headless host (
--remote) and drives it over a local socket. That host is where the world actually lives, so a system you wrote runs in its process while you watch the result in the editor’s viewport.
Why the split exists. Rust has no stable ABI, so a pre-built editor cannot simply link a project compiled separately. The
dylibgets around that by requiring the same compiler for both — fine for code the editor itself built. The remote host covers the rest: running your systems against a live world. Seedocs/MEMORY.mdfor the full reasoning.
The Hub — the window you get from cargo run -p kooch_editor — is where projects are created
and opened.

The panels
| Panel | What it is for |
|---|---|
| View | The 3D viewport. Selection, transform gizmos, the physics debug overlay, and the meshlet debug-view dropdown. Owns the editor camera. |
| Game | What the game’s own camera sees — no gizmos, no selection outlines. A sibling tab of View, and only rendered while its tab is visible. Play does not switch you here or take the editor camera away; the two views coexist because a frame is a list of views. |
| World | The entity hierarchy of every loaded scene. Selecting here selects in View. |
| Inspector | The selected entity’s components and their fields. Where authoring happens. Hover a field name and its doc comment appears as a tooltip — units included, which is how you find out that a directional light’s intensity is in lux and a point light’s is in lumens. |
| Components | Every component type the engine and your project registered. |
| Archetypes | Which combinations of components actually exist, and how many entities are in each. A debugging view of how the ECS stored your scene. |
| Asset Browser | The project’s assets and the engine’s, as two roots. |
| Input Map | Edits a .inputaction asset: bindings, the five composites, processors. An action is an asset, not an entry in a map — see Writing a System. |
| Console | Structured logs from the editor and the launched project, filterable. Text is selectable and copyable. |
| Performance | Frame timings, and per-stage counters where they exist. |
Play
Play does not rebuild anything and does not open a second window.
Pressing Play snapshots the authored world, flips the Playing gate so gameplay systems
start running, and simulates in the editor’s own viewport. Stop lowers the gate and restores
the snapshot, so the world goes back exactly as authored — you do not lose your scene by
testing it.
#![allow(unused)]
fn main() {
// kooch_remote::handlers::set_playing, in essence
if playing {
resources.insert(PlaySnapshot(WorldSnapshot::capture(resources)));
Playing::set(resources, true);
}
// Stop: the gate goes down *before* the restore, so no system
// observes a half-rebuilt world.
Playing::set(resources, false);
if let Some(snapshot) = resources.remove::<PlaySnapshot>() {
snapshot.0.restore(resources);
}
}
This is why your project’s systems register with run_systems: false while authoring: they
are registered either way and skipped per frame, so Play can flip them on live rather than
recompiling.
Known rough edge. A locally-opened project’s Play button still has an older path that shells out to
cargo run -- --game, which builds the project and opens a second window — minutes of nothing, and no snapshot. Tracked in #633.
What the editor does not do yet
Honest list, so nothing below is mistaken for a bug in your setup:
- No build button. Changing Rust code means running
cargo buildyourself (#158). - No reload. The project’s
dylibloads once, when the project opens. Seeing a code change means reopening the editor (#648). - No New Scene. Scenes have to exist on disk already (#619).
- Exposure and ambient light have no panel. Both are engine
Resourceswith sane defaults and no way to change them from the editor, so a scene that reads too bright or too flat cannot be corrected without editing code. See Lighting. - Reconnecting discards unsaved changes silently. Relaunching the host reloads the scene from disk; anything not saved is gone, and nothing warns first.