Learn/Philosophy

The Eustress Philosophy

Eustress is a source-available simulation and data platform, written in Rust, where people and AI agents build and run the same Spaces. These are the principles behind it, each tied to a mechanism you can inspect yourself.

Time11 min readLevelBeginnerUpdatedUpdated Sep 2026

01Overview

What Eustress Is For

Eustress is for modeling physical systems, running them forward in time and measuring what happens: a battery cell under load, heat moving through a part, a structure an agent assembles and tests. The 3D view and the entity component system underneath are how it does that. The product is the simulation and the data it produces.

Every principle below is a decision you can check in the product or in the source, which is public. Where a principle is still partly a goal, the page says which part.

Six Principles

PrincipleWhat to look at
Agents and people work in the same SpacesThe MCP server, the engine bridge, the AI camera
Your work is yoursSpace folders, TOML files, git history, the WorldDb
One language underneathRust in the engine, Studio, tools and website
Measured in SIMeters in every system, SI types in the physics
Same inputs, same worldA fixed 60 Hz step, pinned physics settings, one seed
Source-availablePolyForm Shield 1.0.0, plus a commercial license

02Agents and People

The Same Spaces

An agent in Eustress works in the Space you have open, not in a copy and not by reading screenshots of the interface. The parts it creates appear in your Explorer, and the editor actions your keyboard shortcuts run are one bridge call away (action.invoke).

Studio's Workshop panel and the MCP server take their tools from one crate, eustress-tools, so a tool added there is available to an agent in either place.

The MCP Server

The MCP server, eustress-mcp, speaks the Model Context Protocol over standard input and output, the way MCP clients such as Claude Desktop, Cursor and Windsurf launch a server. Through it an agent lists Universes and Spaces, reads and edits entities and scripts, runs simulations and experiments, and reads the op-log.

When an engine is running, entity edits go through it and appear in the open Space at once. When none is, they are written to the Space's files instead. MCP Server lists the tools and how to connect a client.

The Engine Bridge

Every running engine, windowed or headless, opens a bridge: a JSON-RPC listener on 127.0.0.1 whose port it writes to .eustress/engine.port in its Universe. The MCP server and the eustress command-line tool are both clients of it. Each request and each reply is one line of JSON:

Bridge wire format
{"jsonrpc":"2.0","id":1,"method":"ecs.inspect","params":{"limit":10}}
{"jsonrpc":"2.0","id":1,"result":{...}}

Its methods cover what acting in a world takes: query and edit entities (ecs.query, entity.create, entity.update), advance physics one fixed tick at a time (sim.step), cast rays against live colliders (scene.raycast), run editor actions (action.invoke), read the op-log (oplog.tail) and capture images (viewport.capture, ai_camera.capture).

The AI Camera

An agent that builds something needs to look at it without taking over your view. The AI camera is a second camera that renders 1280 by 720 images into an off-screen texture instead of the window. It appears in the Explorer as a Camera named AI Camera, and the ai_camera_set_pose, ai_camera_orbit, ai_camera_frame and ai_camera_capture tools move it and save what it sees, while your viewport stays where you left it.

03Your Work Is Yours

Files You Can Read

A Space is a folder you can open without Eustress. Services, instances and settings are TOML; scripts are .rune and .luau files; meshes are .glb. Edit any of them in another editor and the file watcher applies the save to the open Space. Rune scripts also get completions from the Rune language server.

Universes walks through the folder layout, from the Eustress folder down to a single _instance.toml.

History You Keep

Ctrl+S and autosave, every 300 seconds by default, each commit the Space folder to git. The record of how a Space changed is ordinary git history on your own disk: any git client reads it, and you can push it to any git host you choose.

Advanced
Git holds the files, not the database

Parts that live only in the Space's database are not in these commits. What Git Captures lists what a commit covers and how to export the rest as TOML first.

A Database for Scale

One file per part stops scaling long before a large world does, so each Space also has a database, world.fjalldb/, and Studio builds the scene from it. Files are read into it when the Space opens. A Space with more than 100,000 binary parts streams them around the camera, 350 m out by default, instead of loading them all.

What lives only in the database can still be read as text. The export_instances_toml tool writes it out as ordinary _instance.toml files from a running engine, and eustress-space export does the same with no engine at all.

What Leaves Your Machine

Studio sends anonymous usage statistics by default, so that the tools people reach for get built first. Each ribbon click is recorded as the tool, the mode and discipline it was clicked in, whether the tool is wired, and a timestamp. Scene content, file names and entity names are not part of it.

Clicks are kept as JSON lines in %LOCALAPPDATA%\Eustress\telemetry on Windows (the local application data folder on other systems), so you can read exactly what is collected. Only per-tool totals are sent: when a session ends, or at the next launch if that send did not go through. To stop it, clear Send anonymous usage statistics under Settings > Notifications > Privacy.

04One Language

Rust Throughout

The engine, Studio, the WorldDb, the MCP server, the eustress command-line tool and the headless runner are Rust, and so is this website, written with Leptos and compiled to WebAssembly. That is about 574,000 lines of Rust across 1,342 files under eustress/crates.

One language means one compiler checks the whole path, from a record in the database to a field in the Properties panel. Rust's ownership rules give memory safety without a garbage collector, so no collector pause can land in the middle of a fixed-rate simulation step.

Slint Is Rust

Studio's interface is written in Slint, a declarative language for user interfaces, across 66 .slint files. Slint is compiled, not interpreted: the engine's build script turns the interface into Rust, and the editor includes the result with slint::include_modules!().

crates/engine/build.rs
let slint_config = slint_build::CompilerConfiguration::new()
    .with_style("fluent-dark".into());

slint_build::compile_with_config(
    "ui/slint/main.slint",
    slint_config,
).expect("Failed to compile Slint UI");

A panel's properties and callbacks are therefore Rust types, checked by the same compiler as the engine that feeds them.

What Is Not Rust

Rust is the rule. These are the exceptions:

PartLanguageWhy
The Luau virtual machineC++Luau scripts run in Roblox's Luau VM, built into the engine through the mlua crate. Rune scripts run in a VM written in Rust.
Workers behind api.eustress.devJavaScriptThey run on Cloudflare Workers. The content API server, eustress-backend, is Rust.
The VS Code extensionTypeScriptVS Code loads extensions written in JavaScript or TypeScript.
Asset scriptsPythonThey run inside Blender to build the avatar and export the primitive part meshes.
GPU shadersWGSLFive shader files, for billboards, the sun disc, the moon's phase and instanced part materials.

05Measured in SI

Meters Everywhere

One unit is one meter. The engine stores every length in meters (ENGINE_NATIVE_UNIT is Unit::Meter), and gravity is standard gravity, pointing down:

g = 9.80665 m/s²
Standard gravity, the engine default

Conversions happen only at the edges: when a file written in another unit loads, and when the Properties panel shows or takes a value in your display unit. A value read from a file, a script or a physics result is already in meters.

Display Units

If you think in other units, pick one from the unit badge, which reads m until you change it: centimeters, millimeters, feet and inches are among the choices. The Properties panel then shows and accepts lengths in that unit and converts them to meters. The world itself does not change.

A file can be written in another unit too. Name it with unit under [metadata], and the loader converts the position and scale to meters once, as it loads:

Workspace/Crate/_instance.toml
[metadata]
class_name = "Part"
unit = "cm"

[asset]
mesh = "parts/block.glb"
scene = "Scene0"

[transform]
position = [0.0, 50.0, 0.0]    # 0.5 m
rotation = [0.0, 0.0, 0.0, 1.0]
scale = [10.0, 10.0, 10.0]     # a 10 cm cube

SI in the Physics

The physics libraries use SI throughout, and each quantity is its own Rust type: Meters, Kilograms, Seconds, Kelvin, Moles and Amperes, with derived types such as Newtons, Pascals, Joules and Watts. A mass cannot be passed where a length is expected, and the compiler says so.

Physical constants such as the gravitational constant and the speed of light are stored in SI too. Realism covers the laws built on them.

06Same Inputs, Same World

The Pins

A result is worth comparing only if running it again gives the same answer, so Eustress fixes every setting that shapes a physics step:

SettingValue
Fixed timestep60 Hz
Physics substeps6 per step
Solver settingsAvian's defaults, set explicitly
Gravity9.80665 m/s², downward
Random seedGlobalRngSeed, a fixed constant by default
crates/engine/src/app_core.rs
.insert_resource(avian3d::prelude::Gravity(bevy::math::Vec3::NEG_Y * 9.80665))
.insert_resource(Time::<bevy::time::Fixed>::from_hz(60.0))
.insert_resource(avian3d::prelude::SubstepCount(6))
.insert_resource(avian3d::dynamics::solver::SolverConfig::default())
.add_plugins(eustress_common::physics::DeterminismPlugin)

The timestep and the substep count are written into the engine as values rather than left to Avian's defaults, so a physics library update cannot change them quietly.

One Seed

Randomness that shapes a simulation comes from one seed. GlobalRngSeed is a fixed constant unless you set another, and the particle simulation and the scenario engine derive their random streams from it. A run that uses randomness can be repeated from the Space alone, and changing the seed varies it on purpose.

The headless runner makes a run a function of its inputs. This simulates 600 ticks, 10 seconds at 60 Hz, writes the recording and exits with a status code:

Bash
eustress run ~/Documents/Eustress/Universe1/Spaces/Space1 --ticks 600

CLI & Headless covers the runner and its options.

07Source-Available

PolyForm Shield

Eustress is source-available. The source is public on GitHub, and the root LICENSE is the PolyForm Shield License 1.0.0. It lets you use the software for any purpose, change it, build new works on it and distribute copies, with one exception: providing a product that competes with Eustress, or with a product Eustress LLC provides using it. Copies you distribute must carry the license terms and its Required Notice line.

At no cost, the license covers:

  • Products made with Eustress: building, shipping and selling simulations, digital twins, training environments and visualizations.
  • Internal use: at a company of any size, including in production.
  • Changes: modifying and forking the engine for your own products.
  • Learning: academic use, research, evaluation and personal projects.
Info
Built with it, or a substitute for it

If your product is built with Eustress rather than being a substitute for it, you owe nothing and you do not need to ask.

Third-party crates such as Bevy, Slint and Avian keep their own licenses, and one first-party crate, eustress-embedvec, declares MIT in its manifest.

The Commercial License

For rights the Shield license does not give, LICENSE-COMMERCIAL.md describes a negotiated commercial license: to offer Eustress, a fork of it or a substantially similar platform as your own product, or to get conventional terms such as warranties, indemnification, support SLAs or a perpetual grant. Pricing follows the rights granted, not your revenue from products the Shield license already permits.

Write to licensing@eustress.dev, or read the full terms on the License page.

08What's Next

A Determinism Gate

The pins make determinism testable, and the next step is the test itself. The headless runtime plan sets a gate: the same Space, run twice for the same number of ticks, will have to produce byte-identical recordings.

Branching the Whole World

Agents already share your Spaces. Next, they will be able to fork one, database included, try a change and keep it only if it wins. The storage library's copy-on-write branches are built and tested, and Universes describes what is left to wire.

Build it, run it, measure it, and keep the files.

Loading Eustress Engine...