Console commands
Every console command lives in one of two registries, and /help lists both.
Nothing else can run a command: a line is only ever resolved against these
registries, so registering a command is what makes it both runnable and listed.
Where a command is registered
| Runs on | Registry | Register with | Examples |
|---|---|---|---|
| Client | ClientCommandRegistry (engine CommandRegistry<ClientExec>) | manifold_console::register_baseline_client_commands, or a client-state module’s register_*_command called from the host’s client setup (native manifold-host/src/host_state.rs, browser manifold-host-web/src/driver.rs) | /help, /camera, /model, /label-edit, /input, /assemblyview |
| Server, engine | ServerCommandRegistry (engine CommandRegistry<ServerExec>) | manifold-server-state::console modules for commands both hosts run; manifold_server::console::register_baseline_server_commands for native-only ones | /label, /water, /gamerule, /entity, /ai, /physics, /op, /perm |
| Server, game mod | Folded into ServerCommandRegistry at boot | ModApp::register_command(CommandDecl) in the WASM guest; the host folds the manifest’s nodes (console::command_fold) | /time, /moon, /planet |
A command node is a leaf, or a branch with children. A branch with a
root_exec (guest: CommandKindWire::Branch { has_root_exec: true }) also runs
when typed bare, like /time. Give every node help text: /help shows it.
The flagship guest declares its commands in one table, GUEST_COMMANDS
(game/flagship-game/src/guest.rs), which route maps to handlers. The test
guest_command_table_and_router_agree fails if a runnable declared path has no
handler or a handler has no declaration.
Dispatch
The client console resolves a line against the ClientCommandRegistry first.
If the first token is unknown there, it forwards the line to the server
(C2S::ConsoleCommand), which resolves it against the ServerCommandRegistry,
checks the connection’s permission, and runs a native handler or queues it for
the declaring guest. A client path therefore hides a server path with the same
tokens.
How /help sees server commands
Once a server’s registry is final (after the guest fold),
publish_command_catalog snapshots it with CommandRegistry::catalog into the
engine-baseline synced resource ServerCommandCatalog
(manifold:command_catalog). Clients receive it in the join snapshot (native)
or the first sync broadcast (browser worker), and /help merges it with the
client registry’s own catalog:
/helplists every runnable command, client and server, sorted by path. Server commands that need operator permission end in(op)./help <command>prints that command’s help and lists its subcommands. A client path hides a server entry with the same path, matching dispatch.
Regression coverage: catalog_describes_leaves_and_branches_sorted
(engine), publishes_every_server_command_and_marks_it_dirty
(server state), the help_* tests in manifold-console’s
baseline_commands.rs, and test_i_guest_commands_reach_the_client_command_catalog
(game/flagship/tests/m4c3_command_abi.rs, real guest bundle).
Entities and AI: /entity, /ai, /anim
/entity and /ai (Talos G §10) live in
manifold-server-state::console (crates/manifold-server-state/src/console/)
and both hosts register them through register_entity_commands, beside the
server half of /anim. /component get|set is an alias of /entity get|set
for one release, on both hosts. Output is admin text; results that arrive after
the command (a hit B applied, an ability B started or refused, a test path) print
when they arrive, a tick or more later.
| Command | What |
|---|---|
/entity spawn <archetype>[#variant] [at <x y z>|@look|<ref>] [count <n>] [owner me|world] | spawn from an archetype; count is atomic; owner me charges the spawn to you and makes it yours in play (OwnedBy your avatar, so a pet follows you) |
/entity despawn <ref> · despawn radius <r> [archetype <a>] | remove entities (never a player’s avatar) |
/entity inspect <ref> | identity, relationships, tags, stats, equipment, effects, locomotion, brain, reservations, one animation line pointing to /anim inspect, components |
/entity inspector on [radius <r>] · select <ref> · off | stream the live inspector (what Shift+F4 sends) |
/entity list [archetype <a>] [radius <r>] [agents] [limit <n>] | entities around the caller |
/entity get <ref> <component>[.<field>] · set <ref> <component>.<field> <value> | read any component through its schema metadata; write a mod’s component |
/entity def <key> [--provenance] | a frozen registry entry and who wrote each field |
/entity equip <ref> <slot> <item|clear> | Talos B’s equipment |
/entity ability <ref> use|cancel <ability> [at <ref>|<x y z>] | Talos B’s abilities |
/entity damage <ref> <amount> [type <t>] [from <ref>] · kill <ref> | Talos B’s damage pipeline |
/entity spawner list|info|eval|reset | Talos E’s spawners |
/ai trace <ref> [on|off] | stream an agent’s decision trace to the console and inspector; the ring’s history comes first |
/ai why <ref> [not <activity|behaviour>] | the explain query over Talos D |
/ai path <ref> [to <x y z>|<ref>] · reach <ref> <x y z>|<ref> | Talos C’s corridor and the status of the brain’s own path request, a test path, reachability with its reason |
/ai lod <ref> [full|reduced|dormant] · lod stats · budget [set <wu>] | Talos D’s LOD and work-unit budget |
/ai overlay <paths|sight|hearing|activity|all>... [radius <r>] [focus <ref>] · overlay off | draw AI layers in the world |
/ai reservations [<ref>] · population [set …] | Talos E’s coordination views |
References
/entity, /ai, /anim and /physics resolve every reference through one
resolver
(console::resolve (crates/manifold-server-state/src/console/resolve.rs)),
so @last is shared. A reference a command refuses (say, a non-body given to
/physics inspect) still becomes @last.
| Syntax | Meaning |
|---|---|
#41 | the durable id, else the per-run spawn id |
@s, @self | the caller’s avatar |
player:<name> | a connected player’s avatar |
@look | the entity under the crosshair within 64 m: posed hit volumes where it has them, a physics body’s colliders (the physics runtime’s body ray), its bounds otherwise |
@last | the last entity the caller’s commands created or targeted |
@near[:<archetype>] | the nearest entity (of that archetype) within 64 m |
@sel | the entity selected in the caller’s inspector |
e:<bits> | a raw session handle, for debugging |
m:<n>, a bare number | a /model placement: client only, refused by the server |
Permissions
Leaves register at Admin; each also checks its Talos node through the one
node catalogue (see platform namespaces (docs/architecture/extension-contracts.md)
and mod permissions). Opening the
leaves to other levels by node is left to the command registry’s node support.
The .own nodes let a player inspect, trace and overlay their own entities
through the inspector’s stream.
The debug stream and the inspector
/ai overlay, /ai trace and /entity inspector subscribe the caller to
S2C::DebugFrame, one message for every debug domain (Ai, Inspect; Physics
and Anim reserved). Subscriptions live in one neutral registry
(debug_stream (crates/manifold-server-state/src/debug_stream.rs)):
each program registers a frame builder (register_builder), records its
domain’s subscriptions there (DebugViewer::subscribe, radii clamped per
domain: 256 m for physics, 128 m otherwise) and charges its frames against
the viewer’s one byte budget, shared by every domain (64 KiB/s for admins,
16 KiB/s for players). Talos builds each viewer’s frames at 10 Hz (AI) and
4 Hz (inspector, its entity list at 2 Hz); over budget, trace chunks are
dropped oldest first and the next chunk says how many ticks were skipped.
Frames carry semantic records, not lines: the client
(talos_debug (crates/manifold-client-state/src/talos_debug.rs)) shifts
them to each agent’s presented position every frame and draws them as the
manifold:ai_overlay platform layer of the one overlay scene
(world overlays), beside the /anim debug hitboxes and
telegraph layers.
Shift+F4 (manifold:toggle_entity_inspector) opens the live inspector, a dock in
the Manifold look (entity_inspector (crates/manifold-ui-runtime/src/entity_inspector.rs)):
entities nearby with a filter, and the selection’s identity, brain (with its
decision trace), path, reservations, animation, tags, stats, equipment,
effects, damage log, relationships and components. It has no write path of its
own: selecting, tracing and overlays are console lines to the server.
Physics: /physics
/physics (Daedalus G §7) lives in
console::physics_commands (crates/manifold-server-state/src/console/physics_commands.rs);
the native server and the browser worker both register it with
register_physics_commands, so it works in browser singleplayer too. Every
reference goes through the shared resolver above. Leaves are Admin.
| Command | What |
|---|---|
/physics spawn [box|sphere|capsule] [size…] [material] | a dynamic primitive 3 m in front of your eye, in your world space; a box takes an edge (default 1) or x y z, a sphere a diameter, a capsule a diameter and a height; material is a manifold:physical-material key (default manifold:default). /physics spawn 2 is a 2 m box |
/physics extract <x y z> [vx vy vz] | pop the block at that position in your world space out as a one-voxel assembly, optionally launched (the same refusals as assemble) |
/physics assemble <x1 y1 z1> <x2 y2 z2> [dynamic|fixed] | turn the blocks in that box of your world space into physics assemblies, one per face-connected island (dynamic by default); air and fluids stay. Refused when the box holds a light emitter, a block entity or a block that is not a full cube |
/physics impulse <ref> <x y z> [at <px py pz>] | an impulse in N·s (at most 100 000) on a body, at its centre of mass or a world point; it applies in the next physics step |
/physics remove <ref> | remove a physics body (its joints go with it) or a joint; anything else, a player or an agent, is refused |
/physics inspect <ref> | a body’s identity, world space, kind, owner, pose, velocities, sleep state, shape and material, and the solver’s activity (simulated, sleeping or held, with why), region, Rapier collider count, mass and centre of mass |
/physics stats | the runtime’s counts (bodies, holds, colliders, terrain cache, joints), event and command drops, stage times, then one line per region |
Every mutating leaf (spawn, extract, assemble, impulse, remove)
parses and resolves its arguments, checks the values (a bad number or an
oversized shape is refused at once with the reason’s code, for example
invalid-value: too-large), and submits one op to Daedalus G’s
physics command queue
(physics_contract (crates/manifold-server-state/src/physics_contract.rs))
with you as the actor; the server console acts as a rule for the world. No
leaf changes the world itself. The op applies in the next tick’s
PhysicsCommandApplySystem, before the physics step, and its result prints
after that tick’s block-transaction apply slot. So every result, success or
refusal, arrives one tick (25 ms) after the command. A refusal prints the
reason’s localized message (engine.physics.reject.*, Daedalus G §5.4).
spawn and extract make the new body your @last and print its reference
and raw handle, for example spawned physics box #12 (e:4294967308) at (…).
The body is yours: it carries a durable id and your player as its owner from
creation, and counts against your physics quotas. When you are at a quota
(or the world space at its body or collider budget) both are refused, for
example The owner has reached its quota physics.owned-bodies.max., and
extract leaves the block in place.
assemble and extract write world cells, so their op submits one block
transaction (Daedalus B §5.4) that commits at the apply slot of the tick the
op applies in: the cells clear and the assemblies appear in that same tick,
and then assemble prints one line per assembly, for example
assembly #41: 25 voxels, mass 25000 kg, owner alice (e:…); the last one
becomes your @last. Both are refused for an unloaded chunk, a refused
block, a quota, an island over physics.assembly-voxels.max (32,768 for
players, 131,072 for operators) or physics.assembly-extent.max (256, 512),
more than physics.assemble-rate.max assembles a minute (30, 600), or a
reserved or changed cell at the apply slot, and nothing changes.
Operators hold every physics.* node until the permission catalogue lands
(Daedalus G §6.5); a player’s op is refused with You don't have permission to do that (physics.spawn). and similar. While a Framescope capture is armed, each
applied batch is recorded as physics_command with its actor, owner, ops,
outcome (submitted for a world-cell op whose transaction is still to
commit) and cost (Framescope (docs/development/framescope.md)).
See physics runtime (docs/architecture/physics-runtime.md) for what the counts
mean.
Limits
/helpdoes not filter by the viewer’s permission level; it tags operator-only server commands instead. The server still enforces permission when a command runs.- The browser host lists
/whoami,/ui-editand/framedbg, which need the native client context and report an error there. - Clients do not draw assemblies yet (Daedalus B0-5): after
/physics assembleor/physics extractthe blocks disappear and the assembly simulates on the server, visible through/physics inspect. /physics jointand/physics drive(the lift’s slider and servo, Daedalus C0’s console, #422) are not registered yet; their ops (create-joint,set-drive) go through the same queue from native code.- The client draws every physics body as a box (
PhysicsRender.primitiveis not read yet), so a/physics spawn sphereorcapsulebody collides as its shape but renders as a box of its size.