The debugger
The debugger follows the shape of React DevTools and Unity’s custom inspectors: a generic tool the engine knows nothing about, extended per game. The engine exposes the devtools API, which draws nothing. @spawnite/devtools draws the generic overlay. A game adds its own sections to the rail, each with an id, a title, an icon and a component: through registerPanel on the devtools API, or as <Devtools panels={[{ title: "Hand", icon: Spade, component: HandInspector }]} />. A game mounts <Devtools /> inside <Game> in development, and published bundles never include it.
This page is the design draft for the overlay; the devtools pages describe what ships. Claude Design’s export fills the screenshots section below. The prompt that produced it is on the internal claude-design pages, which public pages never link.
- The rail is a column of icons down the left edge, and the one sidebar beside it shows the section whose icon is pressed. Nothing stands on the right edge or along the bottom, so the game keeps the rest of the screen. The top of the rail holds what a creator builds with: Entities, Map, Assets, Favorites, Clips, then each section a game or its agent registered, and the column scrolls once they outgrow it. A drag moves an icon up or down the top of the rail, the icons it passes sliding aside to make room, and the release keeps the new order; the foot’s icons and Console stay where they are. A section the kept order does not name, such as one a game registered since, stands after the icon that comes before it by default, and Reset rail order at the foot of Shortcuts puts the default order back. VS Code’s activity bar moves its icons the same way. Its foot holds what they look things up in, Wiki, Performance and Shortcuts, and under a line at the very bottom Console, whose circle reads as the page’s status there, where Unity and VS Code keep their count of errors.
⌘1to⌘9open the top’s sections in the order the rail shows them, so⌘1opens Entities to start, with its filter focused, and each icon’s tooltip names its key;⌘Jopens or folds Console,⌘Gopens the game’s next section, and⌘[folds or opens the sidebar. A press on the icon of the open section folds the sidebar to the rail alone, narrowing into the rail with what it holds sliding along its edge, never fading, since glass does not fade, and a press on any icon opens it again. Each icon names its section in a tooltip. The sidebar has one width for every section, 372 px to start, and a drag on its edge sets it between 288 px and 560 px; the console’s section springs it out to at least 520 px, since a log line reads across, and back as another section opens. The browser keeps the open section, the width, the fold and the rail’s order for the next page load. VS Code, Figma and Spline switch one sidebar from a rail the same way. Unity, Unreal, Godot and Roblox dock every panel freely, and a newcomer closes one and cannot find it again; this layout is fixed, so it has nothing to lose. - Every section opens with the same header, its title and its actions at the right, and a section with a search, Entities, Assets, Wiki and Shortcuts, has it at the header’s right: a magnifier that widens into the field while it holds focus or text, as the searches in VS Code’s and Figma’s panel headers do. The console keeps its filter under its header, beside Clear.
- A registered section has an id, a title, an order among the registered ones, and an icon, which is a component such as one of lucide’s. The rail lists them in that order, lowest first, until a creator drags them into another.
- Entities holds the tree, and the inspector under it once a row it can show is selected: an entity, a scattered instance, a HUD’s row or the World’s. A divider between them moves on a drag. The inspector rises in from below as the tree springs to its share, and falls away as the tree springs back to the whole height; a drag on the divider follows the pointer with no spring. A scene’s or a group’s row leaves the tree whole. A selection made in the game, or Inspect on a frame, opens Entities.
- The tree is the developer’s component tree: Scene, World, Player, Camera and each game component by its name, behaviours as leaves, entity ids beside names. A group appears only where one game component renders several entities. No invented groups, with one exception: the map’s scatter reads as one Scatter row under the World with a row per kind in it, since a kind stands hundreds of trees and none is a component.
- The wiki is the last section of the rail. A map sits at the top of the pane and stays in view, as tall as its drawing up to 40% of the pane, and the page scrolls under it. The wiki explains structure only: it shows no code, no timings and no run order, which stay in Performance. On a phone, Wiki is a tab of its own in the bar, and a press on an entity opens the inspector, as a tap in the tree does. The tab holds the following:
- The map is a mermaid flowchart with the page that shows in the centre, in the accent colour: the game, a kind or an entry. Its left side is the chain up to the game, such as Game, Input, Jump, then Space. Its right side holds what the centre is made of, what it refers to and the entities that use it, grouped by their names in the tree, such as Yeti ×4. A link that says how it connects goes in a group titled by that word, such as Potion’s Changes, which holds Health, and Held by, which holds Inventory. Each entry there shows its own parts one column further out, faded, 3 at most and then +N. The home’s map holds each kind with an entry, with its count. The running scene’s map holds the rows under its row in the tree, such as the Lobby’s World, Player, Scatter and Camera, and one column further out what each holds, such as Player’s Movement. A scene that is not running shows alone, and its page says it holds nothing until it runs. A group of more than 8 shows 8 and a node, such as 2 more, that unfolds the rest. Each column lists its entries by name, the game’s and the engine’s together, and the engine’s draw muted. Its theme comes from the debugger’s palette, and the site’s own diagrams use the same theme.
- A press on the map opens the page of an entry, a kind or the game, and the map centres on it. A press on an entity or a row opens Entities and selects it, and a press on a behaviour opens its entry.
- The home holds a search over names, kinds and descriptions, then Your game, which holds a section for each kind with an entry, then the game’s overview. Each kind lists by name the game’s entries and the engine’s entries the game uses, the engine’s muted: one an entity carries, such as Movement on the Player, or one a game entry links to or sits under. The engine’s entries that nothing uses fold into one section at the end of their kind, such as 12 more from the engine, and a kind with only those shows that section alone. Each kind’s header shows its count and an arrow that opens the kind’s page, and each entry shows how many entities use it. A search lists each kind’s matches, the engine’s unused ones among them.
- An entry’s page opens with a header: its name and kind, with icons at the right, each named in a tooltip. A copy icon copies its code name, a book opens its wiki page in a new tab, and a file opens its source in the developer’s editor. Its description sits under the header, and a scene that is not running says there that it holds nothing until it runs. Properties follows where the entry has any: its own data in the inspector’s read-only card, each key as written, and a nested value indented under its key. Used by follows on a behaviour or a trait that entities carry: each entity, with its value of that trait in the same card, read as the section opens. Page follows, with the opening of its page, and Read more shows the whole page there, with Show less at its top.
- A kind’s page opens with the same header, its wiki page as a book at the right, then its description, then its entries, listed as the home lists them.
- Every section folds on a press on its header: Your game, each kind, each kind’s engine entries, the overview, Properties, Used by and Page. A section’s items sit in under its header, and a section inside another sits one step further in. Each starts open except the overview, an entry’s Page and each kind’s engine entries. The pane keeps which are folded, the search and the open page while another section shows.
- Map is the rail’s second section, opened with
⌘2to start, the key following the icon’s place on the rail: the map’s editor, apart from the placeables in Assets, as Unreal keeps Landscape apart from its content browser. Its Terrain section edits the map’s ground, as the map editor designs it, the toolbar first and the rest in sections that fold: Brush, the chosen material, one per family of materials and Map. Its header names the map it edits, with a chevron that lists every map the game registered, the one on screen marked, and opens another alone as?map=does; at the header’s right stand Saved or Unsaved, Undo, Redo, Reset and Save, and the moved base’s two ways out when an agent moved it; the header and the tools stay pinned as the section scrolls. Under the header: Sculpt, Smooth, Flatten, Paint, Fill, Scatter and Clear as icons, each naming itself and what it does in a tooltip, the one in hand filled with the accent; in Brush, the brush’s size, in steps of 0.1 m up to 30 m, Sculpt’s Raise or Lower beside it while Sculpt is in hand, and the strength, which the browser keeps; Flatten’s Level field, which takes a typed height or a drag of its label in 0.1 m steps, reads “auto” when empty and offers “auto ×” beside a set level, a region to fill with Fill, and with Scatter the families as chips and More, Thin and Erase; in the chosen material’s section, headed by its name with Duplicate as an icon, its tint and its amount, tile, bumps and Wet; a section per family of materials, such as grass and dry grass, each family of one under Other, with a tile of each material’s colour texture, wrapping to the pane’s width; and last, in Map, the Sea field, a field like Level’s that always shows the sea’s height, which Alt and a click on the ground with no tool in hand also sets. Each section folds on a press on its header, growing out of it and back in, starts open, and stays as it was left while another section of the sidebar shows. A tile chosen holds Paint, unless Fill is in hand. A tool pressed is in hand until it is pressed again or Escape puts it down, and it turns the map camera on unless the map or the free camera is on already: a left drag or one finger paints, a middle drag grabs the ground, a right drag or two fingers turn, the wheel zooms, and the brush cursor shows the brush on the ground under the pointer, a faint fill with a wide outline and an inner ring where the stroke is full, one shape for every tool whose fill says the tool: the accent for Sculpt, warm while it lowers, grey for Smooth, the accent with a grid plane at the level over the whole map for Flatten, and the chosen material’s swatch for Paint. Ctrl flips Raise or Lower while held, Shift smooths while held, Alt and a click samples the height into Flatten’s level with Flatten in hand and picks the material under the cursor otherwise, a brush held still keeps working,[and]resize, and B or Shift and B held turn a drag into a change of size or strength. The ground follows the stroke as it is drawn, and the stroke stays in memory as an unsaved edit when the pointer lifts.⌘Zand⇧⌘Zundo and redo a stroke, a material’s slider drag or a Duplicate on the page.⌘Sor Save writes the edits through the dev server, Reset drops them, and the map picker asks before another map opens over them and ends in Reset to base. A write from outside, such as an agent’sspawnite map terrain, reloads the terrain and says so under the tools, or over unsaved edits shows Changed on disk with Reload and Save anyway. A Save over edits whose base moved offers Keep my heights and Move my edits with the ground. Leaving Map for another section puts the tool down; folding the sidebar keeps it. The round Map camera button opens the section as the camera comes on. On a phone, Map is a tab of its own in the bar. - Assets is the rail’s third section: what a creator can place, as cards in four groups, Models, Avatars, Scatter and Shapes, under a search that filters the cards by name and drops a group with no match. Models, Avatars and Scatter never fold; Shapes starts folded while none stands in the map, and a press on its label unfolds it. A model’s card is a picture of the model rendered once on a transparent ground, its name in words, its height from the manifest and how many entities draw it now; an avatar’s its name in words and how many characters wear it, an NPC or a player’s character alike; a scatter kind’s the same with the count the Scatter rows hold; a shape’s a glyph and no count. A press on a card selects every entity that draws it, and with Shift, Cmd or Ctrl held adds them, the keys a click on the canvas uses, so the outlines show them as any selection. A press on a model’s, a scatter kind’s or a shape’s card also picks the card up, ringed in the accent, and the section stays open: the brush cursor shows the card’s footprint on the ground under the pointer, a still click stands it there as a prop of the map named after the card and selects it, and the card stays in hand for the next click, until a second press on it, Escape or leaving Assets puts it down. The map editor says what a placing writes. An avatar’s card only selects, since a character is placed as an NPC, and one none wears takes no press and says so. The pictures render lazily, only for cards scrolled into view and two a frame, so a hundred models cost no frame more than two small draws. On a phone, Assets is a tab of its own in the bar, and the Map button sits in the toolbar. The section does not draw the map itself: the canvas, flown over by the Map button, is the map. PlayCanvas, Figma and Spline name this section Assets too.
- Favorites is the rail’s fourth section, under a star: the fields a creator starred, gathered in one place while they tune a feel, gravity one day and the daylight the next. Every editable field in the inspector carries a star before its name: a behaviour’s prop, a stat’s base and the World row’s gravity, hour and day length. The star shows as a grey outline while the pointer is on the row, and always where nothing hovers, as on a phone; a press fills it orange with a small pop, and a starred field’s star stays shown. A read-only card’s fields carry none. The section shows the world’s starred settings first, then a card per component, each field edited live as the inspector edits it and written to every entity of that component, since a star on one Coin’s speed stars every Coin’s; a card for several says how many it edits. A component not in the scene shows its fields muted, saying so, and each field keeps its star to take it off. With nothing starred, the section says how to add a field. A game starts with the World’s gravity and hour and the Player’s speed and jump height starred, and the creator can take any of them off. The browser keeps the stars per game, by component and field, as it keeps presets. A star means a favourite everywhere, and the pin keeps its own meaning, holding an entity’s buttons and its world panel. Unreal’s Details panel stars properties into a Favorites group, and Godot 4.4’s inspector does the same.
- Clips is the rail’s fifth section, under a clapperboard: the short videos a creator records of the game, a mechanic, a move or a fly-over, for marketing. Record, or F9, starts a clip and a second press stops it, and a clip stops by itself at 30 seconds. The dev tools close once a clip records, so the game plays with nothing over it, and Record waits beside the Spawnite toggle, where a press, or F9, stops the clip and opens the dev tools on Clips again. Record is disabled while a clip starts and while it saves. The section shows the clip under way, with its time, its limit and its shape; the shape the next clip records in, 16:9 or 9:16, to which the canvas letterboxes while it records; and every clip the game keeps, newest first. Each clip shows its first still, the time it started, its length, size and shape, and three actions: Play, which plays it in the section, Send to agent, which sends its contact sheet with where to read the rest, and Delete. The video holds the game’s canvas alone, with no devtools, no HUD and no editor drawing such as the brush’s cursor. Past 50 clips Record is refused with the reason, and nothing is deleted on its own. A browser that cannot encode H.264, or a page that plays a replay back, disables Record and says why in its tooltip. The dev server says what a clip’s folder holds. Unity’s Recorder and Godot’s Movie Maker record play to a file the same way, and Roblox records with F12.
- Edit mode never dims, blurs or covers the scene. The developer sees exactly what the game is doing.
- Panels are neutral dark glass, never tinted by the scene. The rail and its sidebar stay to the left edge.
- The corner row stands in the screen’s top-left slot, before the engine’s corner buttons and a game’s own panels, so they flow under it: the Spawnite toggle, which shows the Spawnite wordmark, turns edit mode on and names ⌘E in its tooltip, and with edit mode off Record while a clip records, then the frame rate. The top bar, with edit mode on: pause (Space), step (period), step back (comma), speed at 0.25x, 1x and 2x with no key, a 10-second replay scrubber, then fps. Two round buttons sit just left of the bar, Record and then Screenshot. Record shows a red dot; while it records, a stop square on a red tint with a pulsing dot, which reduced motion holds still, and its tooltip shows the time recorded and the limit, such as 0:07 of 0:30. While the clip saves it reads Saving the clip and is disabled. A press, to start or to stop, opens Clips, which holds the rest, so the bar stays clean, and the dev tools close once the clip records. Screenshot copies what the player sees to the clipboard as a PNG, the game’s canvas alone with no devtools and no HUD, for a paste into an agent’s chat. Its camera turns into a check once the copy lands, or a cross where the browser refused it, and turns back after a moment. A round camera button sits just right of the bar: it flies the free camera in place of the scene’s, and a second press gives the scene’s camera back. The free camera flies at 12 m/s, twice that with Shift held, and a drag turns it about itself as Unreal’s spectator does. A round Map button sits beside it: it puts the map camera in the scene’s place, a city builder’s camera whose pivot sits on the ground, and flies it up over the player’s character in one eased move until the whole map is in view, landing at a third of the distance of the frame that fits every corner, where the map fills the view, so a wider map lands higher at the same share of its span; a zoom goes no further out than that. Under the map camera the movement keys pan along the ground, Q and E turn, the wheel, a two-finger scroll and a pinch zoom toward the cursor and tilt with height, the right button turns and tilts, a left or middle drag grabs the ground while a still click selects, and on a phone one finger grabs the ground and two fingers pinch, turn and tilt, as Google Maps does. The two buttons take each other’s place: one press puts one camera up and the other down, and a second press on the pressed one gives the scene’s camera back. Each round button names itself in a tooltip.
- On a phone, narrower than 768 px, the rail and its sidebar give way to a tab bar along the bottom edge with a tab per panel, the engine’s and the game’s included. A tap opens that panel in a sheet over the lower 45% of the screen, springing up out of the bar, and the game above stays free for a tap; a second tap on the tab or the X in the sheet closes it. A tap on an entity, in the tree or in the game, opens the inspector’s tab. The Spawnite toggle shows the wordmark’s gem alone, and an X once edit mode is on. The round button beside the Spawnite toggle shows and hides the toolbar, which holds pause, step, speed, the free camera, the map camera, the screenshot and fps, with no scrubber. A phone records no clip, so its toolbar has no Record, and its Clips tab lists and plays the clips a desktop recorded.
- The frame’s strip. A selected entity’s frame carries a row of round glass buttons, each its own, that grows out of the point the selecting click met, just down and right of it, as a context menu opens off the pointer, and rides with the frame as the entity moves; a second click on the entity glides the buttons across the frame to its point; a selection made without a click, as from the tree, opens it at the frame’s bottom-right corner. Each is named in a tooltip. Send to agent, under Spawnite’s spark, opens Send to agent on the entity, or on the whole selection where the entity is in it, as a right-click does; Inspect selects the entity alone and opens the inspector on it in Entities, from a folded sidebar, from another section or from behind Send to agent; Pin keeps the buttons on the entity whatever is selected or opened after it, with no frame around them until the entity is selected or under the pointer again, and turns its pin into a cross, with Unpin in its tooltip, until a second press lets them go. The pin and the cross swap with a quarter turn, and with none under reduced motion. Pin shows only on an entity’s frame, never a World’s, a HUD row’s or a scattered instance’s; a HUD row’s frame has no Send to agent, as its inspector has no Agent. The hovered frame has no strip, and only the strip takes the pointer: the frame and the name let it through to the game. The buttons draw over the frame’s border and handles and under every pane, the sidebar, the sheets and the context menu among them.
- Send to agent is marked with Spawnite’s spark wherever it is named, in its pane’s header, the context menu and the frame’s strip; a button that sends keeps the paper plane.
- World panels are an experiment behind one switch on the World row’s inspector, World panels, off to start. On, a pinned entity’s panel stands over it in the world while edit mode is on: above the entity’s bounds, facing the camera, 0.9 m wide so it shrinks with distance as the entity does, hidden past 30 m, and following the entity as it moves. It springs up out of the entity as it is pinned, and folds back into it once its pin goes, whether the cross in its header or Unpin on the frame took it; under reduced motion it goes at once. A pinned entity’s frame draws no name above it while the switch is on, as the panel’s header names the entity; that holds past 30 m too, where the panel is hidden. It is the debugger’s dark glass, never the game’s palette. Top to bottom, it holds the entity’s name and id with a cross that unpins it, the panel the entity’s component declared through
useDevtoolsPanel, then a Behaviours section, folded until pressed, with the inspector’s cards. A press, a click or a wheel on it stays off the game. Off, no panel draws and the pins stay. A pin lasts through a hot reload and goes on a page load, and an entity that leaves the tree drops its pin, and its panel goes with it at once. Roblox’s BillboardGui and Godot’s Label3D anchor a label to an object the same way. - The world’s settings are the inspector’s cards for the tree’s World row: gravity, the hour and the day’s length, with the presses that jump to dawn, morning and the rest, then the debugger’s own World panels switch. Roblox does the same, with gravity on Workspace and the clock on Lighting, both edited in Properties.
- The inspector sits under the tree in Entities. It opens with the card of the panel the entity’s component declared through
useDevtoolsPanel, where it declared one, whether or not the world panels are on. It shows a card per behaviour, and one Stats card for an entity with stats, whatever declared them: a slider on each stat’s base, and under the sliders the value its modifiers make, each modifier’s source, and a timed one’s seconds left. A field a stat sets every step, such as Health’smaximum, has no slider on its own card: its stat’s base slides in its place. Each state machine the entity holds has a card that takes no edit: the state it is in, the seconds its wait has left, and its states. - Run N seconds is an MCP call,
step(seconds), and never a control in the overlay. Rewind, resuming from a scrubbed frame, is a later issue. - Performance opens with the frame time, the CPU’s and the GPU’s milliseconds a frame, simulated time and a room’s readouts, its round trip first, with a row of connections that sets the slow link the page plays the room over, then lists each part of the frame by its mean and its worst. It sits at the rail’s foot, where every engine keeps its profiler out of the way.
- Shortcuts are scoped, global versus panel, shown as keycaps beside every action.
?opens the Shortcuts section, its search focused, and Escape brings back the section it covered. - The context menu comes in four groups, each under its label and a divider: Agent holds Send to agent; Selection holds Inspect, Select parent, Focus camera and Hide; Edit holds Duplicate, Delete and Add behaviour; Copy holds Copy id. Duplicate makes no copy in the world: it opens Send to agent on the entity with the request “Add another beside this one” filled in, for the agent to write the copy into the scene, since a copy made in the world would have no component to draw it and no row in the tree. Its header shows the world point the right-click met, as x, z and height. A disabled item states why. The Add behaviour submenu takes arrow keys and Enter. The menu opens at the pointer, moved up and left as far as it takes to fit the screen, and the submenu opens on its right, or on its left where the right has no room.
- The ground’s menu opens on a right click on bare ground that does not drag, over grass and all while the Map section or the map camera is on, and is headed by what is there, such as “grass (dirt 30%) · 3.2 m · slope 12°”. Its top row holds the cursor’s mode, Select or Terrain; in Terrain the tools follow, and four brush sizes while a tool with a brush is in hand. Under a divider: Send to agent with the spot, Pick material, Remove this on a scattered tree, bush, rock or tuft, which erases it, Undo and Redo, which stay in place when off and say why in their tooltip, then Other, which opens on a click or a mouse resting on it and closes when the mouse leaves it and its submenu, whose submenu holds Lower while Sculpt is in hand, Wet and Duplicate for the material there, Pick height for Flatten, Set sea to here, Reset to base here under the brush, and Copy position. Escape closes it and puts the tool down. A phone does not open it. The map editor says what each does.
- Send to agent gathers a screenshot framed on the entity, what the player sees as it opens, its tree position, its behaviours with values, their source files, their wiki pages and the systems that touch it. Each part can be unticked, and one line of intent goes with it. It calls
describe(entity)on the devtools API. Send saves each ticked screenshot through the dev server and posts the bundle to it, and the pane closes once the dev server has it; with no dev server, as on a built page, the bundle goes to the clipboard and the pane says so. Copy bundle saves the screenshots the same way and names each by its path in the text. The dev server page says how the message reaches the agent. On a selection of several entities, picked with ⇧ or ⌘ click in the game or the tree as Unity and Unreal pick, it sends one bundle: each entity’s parts under its own name, one tick covering that part of every entity, the screen once, the framed screenshot of the first entity only, and one line of intent. A right-click on an entity in the selection sends the whole selection. The frames on screen mark every selected entity. - The console is the last icon on the rail, under a line of its own: the log lines and errors, each a coloured dot and its message across the pane, with the file it came from under it and its time on the game’s clock beside that while the pointer is on the line. A chip per level in the header counts that level and hides it on a press, and a filter and Clear sit under the header, with ⌘J to open the section and ⌘K to clear it. Its icon carries a circle with the count of lines logged since the section was last open, 99+ past 99, in the colour of the worst level among them: red for an error, amber for a warning with no error, neutral for info alone. Opening the section clears the circle, and no circle shows at zero. The engines hide their log, since their user reads code and knows to look; a creator with no code does not, so the circle says something broke and takes no room. On a phone it is a tab of its own.
Screenshots
Section titled “Screenshots”Filled from session 2’s export. One image per state, on both backgrounds.
- Edit mode off
- Edit mode on
- Hover
- Selection
- Inspection view: Yeti
- Inspection view: Coin
- Context menu, with disabled and submenu states
- Send to agent
- Entity tree
- Playback controls
- The rail, with the sidebar open and folded
- Console, with its circle at each level
- Performance and Shortcuts
- Registered sections: Hand, Quests, Track
- Shortcuts panel
- Phone layout
Handoff bundle
Section titled “Handoff bundle”Send to agent builds one bundle for an entity: its name and place in the tree, the values of the panel its component declared, its behaviours with their props, their source files and wiki pages, the systems that touch it, and its traits, as markdown with the values as JSON. The dev server writes it as a message under the game’s .spawnite/chat/ with the screenshots beside it, and the dev server page says how the agent reads it.