elodin-editor-dev
Skill553 starsChanged 5 months agoApache-2.0View on GitHub
Contribute to the Elodin Editor, the 3D viewer and graphing tool. Use when editing files in libs/elodin-editor/ or apps/elodin/, working on the Bevy/Egui UI, modifying viewport rendering, telemetry graphs, video streaming, KDL schematics, or the command palette.
- Deletes or force-pushes
In this repository17 other files it gives its agents.
- AGENTS.mdAGENTS.md
- bevySkill
- branch-regressionSkill
- elodin-alephSkill
- elodin-craneliftSkill
- elodin-dbSkill
- elodin-devSkill
- elodin-headless-captureSkill
- elodin-monte-carloSkill
- elodin-nixSkill
- elodin-simulationSkill
- elodin-tracySkill
- gltf-asset-optimizationSkill
- kdl-to-python-schematicSkill
- nox-py-devSkill
- qa-test-planSkill
- rustSkill
The file
We split this skill into the rules it gives an agent
3 rules. About 0 are common, 1 is distinctive, and 2 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
2
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 172
Use cargo watch for fast iteration on UI changes
- Very specific: line 174
Test with examples/three-body/main.py for a lightweight simulation
- Distinctive: line 180
Prefer Bevy's native window screenshot path over OS screen capture.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Elodin Editor Development
The Elodin Editor is a 3D visualization and telemetry graphing tool built with Bevy (ECS game engine) and Egui (immediate-mode UI). It connects to Elodin-DB via Impeller for real-time data.
Running
# Standard
cargo run --bin elodin editor examples/three-body/main.py
# With hot-reload on editor code changes (requires cargo-watch)
cargo watch --watch libs/elodin-editor \
-x 'run --bin elodin editor examples/three-body/main.py'
# Connect to a running database instead of a simulation
cargo run --bin elodin editor 127.0.0.1:2240Environment Variables
| Variable | Default | Purpose |
ELODIN_ASSETS | ./assets | Directory for meshes, images, GLB files |
ELODIN_KDL_DIR | . (cwd) | Directory for .kdl schematic files |
ELODIN_GPU | auto | Nix shell GPU path (nvidia / mesa / nvk). Set before nix develop. |
ELODIN_GPU_PANIC | unset | Set to true to force the GPU-not-found panic and print the ELODIN_GPU=… nix develop help. |
ELODIN_H264_ENCODER | auto | Live sensor_camera format="h264": auto tries NVENC / VideoToolbox then OpenH264; cpu forces OpenH264; any other value is an FFmpeg encoder name (h264_nvenc, …). h264_vaapi is not supported. |
Cargo features
Optional features declared in libs/elodin-editor/Cargo.toml (re-exported by apps/elodin/Cargo.toml):
inspector: adds thebevy-inspector-eguiruntime entity inspector.debug: enables BigSpace debug diagnostics.tracy: enables Tracy profiling (see.cursor/skills/elodin-tracy/SKILL.md).
Enable with cargo run -p elodin --features "<list>" -- editor ....
BigSpace is always enabled; the editor has no fallback spatial mode.
Source Layout
The editor is split across two crates:
libs/elodin-editor/ — Core library
src/
├── lib.rs # Plugin registration, app setup
├── run.rs # Main run loop and Bevy app builder
├── object_3d.rs # 3D object spawning from KDL schematics
├── vector_arrow.rs # Vector visualization (force/velocity arrows)
├── offset_parse.rs # EQL viewport formula parsing
├── icon_rasterizer.rs # Icon rendering
├── iter.rs # Iterator utilities
├── ui/ # Egui UI layer
│ ├── mod.rs # Top-level UI orchestration
│ ├── tiles.rs # Tiled panel layout system
│ ├── tiles/sidebar.rs
│ ├── inspector/ # Component inspector panels
│ │ ├── mod.rs
│ │ ├── entity.rs # Entity property inspector
│ │ ├── viewport.rs # Viewport panel
│ │ ├── graph.rs # Graph panel configuration
│ │ ├── dashboard.rs
│ │ ├── monitor.rs
│ │ ├── object3d.rs # 3D object inspector
│ │ └── ...
│ ├── plot/ # Telemetry graph rendering
│ │ ├── mod.rs
│ │ ├── data.rs # Data fetching and buffering
│ │ ├── gpu.rs # GPU-accelerated plot rendering
│ │ ├── widget.rs # Egui plot widget
│ │ └── state.rs # Plot state management
│ ├── plot_3d/ # 3D plot visualization
│ ├── schematic/ # KDL schematic loading and rendering
│ │ ├── mod.rs
│ │ ├── load.rs # KDL file parsing
│ │ └── tree.rs # Schematic tree view
│ ├── timeline/ # Playback timeline
│ │ ├── mod.rs
│ │ ├── timeline_controls.rs
│ │ └── timeline_slider.rs
│ ├── command_palette/ # Command palette (Ctrl+P)
│ ├── video_stream.rs # Live video rendering
│ ├── theme.rs # Color theme
│ ├── colors/ # Color system and presets
│ └── ...
└── plugins/ # Bevy plugins
├── mod.rs
├── view_cube/ # 3D orientation cube
├── camera_anchor/ # Camera tracking and anchoring
├── gizmos/ # Transform gizmos
├── navigation_gizmo/
├── editor_cam_touch/ # Touch input for camera
├── asset_cache/ # Asset caching
├── env_asset_source/ # ELODIN_ASSETS integration
├── web_asset/ # Web asset loading
└── logical_key/ # Keyboard input handlingapps/elodin/ — CLI binary
The main entry point that ties together the editor with nox-py, s10, and Impeller. Handles CLI argument parsing (elodin editor, elodin run, etc.).
Key Subsystems
Bevy Plugin Architecture
The editor registers as a set of Bevy plugins. Each feature area (view cube, camera, gizmos) is a self-contained plugin with its own components, systems, and resources. New features should follow this pattern.
Egui UI Layer
The ui/ module contains all immediate-mode UI rendering. Egui runs inside Bevy via bevy_egui. The tile-based layout system (ui/tiles.rs) manages panel arrangement (viewports, graphs, inspectors).
Telemetry cache (SeriesStore)
Strategy: cache only what the UI uses. Full history per subscribed ID (no time-based SeriesStore GC). Menus use metadata/EqlContext, not store keys. Playback/scrub never wait on backfill — project whatever is already in RAM.
DB ──► allowlisted GetTimeSeries backfill + live ──► TelemetryCache (SeriesStore)
├─► project SelectedTimeRange → LineTree → GPU
└─► apply_cached_data @ playhead → 3D / inspectors
Metadata ──► EqlContext ──► ADD COMPONENT / palettes (full list)| Piece | Where |
| Allowlist + reclaim | ui/plot/data.rs → update_series_fetch_priority |
| Backfill / live filter | impeller_bevy → backfill_cache, SeriesFetchPriority |
| Schedule | editor + headless: priority then backfill_cache (lib.rs, headless.rs) |
Allowlist (SeriesFetchPriority.high): enabled graph lines; Line3d / object_3d EQL (including thruster intensity EQL for particle plumes); monitors; viewport pos/look_at/up EQL; vector_arrow EQL; path-registry adapter pairs (*.world_pos, …); sensor-camera {entity}.world_pos. Empty ⇒ no SeriesStore I/O. Leaving an ID drops it from RAM. Any new live consumer must extend this allowlist or it will be blank/stale. Adapter leaf match is case-sensitive (WORLD_POS ≠ world_pos).
Plots: LineTree is a visible-window projection only (sliding GC here ≠ SeriesStore). Tip/LAST_* fetches quantized (~100 ms) + prefetch margin; also immediate visible-window prefetch so tip fills before begin→end backfill. Do not clear a LineTree when the store has zero samples in-window (unless camera range moved). ≤30 s (SHORT_WINDOW_ACCURACY_MICROS): GPU step = 1, skip Hamann–Chen (INDEX_BUFFER_LEN = 131072 in ui/plot/gpu.rs, sized for ~4 kHz × 30 s). Longer windows: GPU stride on clip; CPU project stride only for >10 min.
Headless: separate process, separate store — same priority + backfill or sensor_view poses freeze while effects still animate.
Do not: gate menus on SeriesStore keys; wait on SeriesStoreLoadState.complete for scrub; reintroduce full-metadata backfill; time-GC SeriesStore without fixing jump-to-start/scrub holes first.
KDL Schematics
KDL files define 3D objects and viewport configurations. The loading pipeline:
ui/schematic/load.rs— Parses.kdlfilesobject_3d.rs— Spawns Bevy entities (meshes, GLB models, shapes)offset_parse.rs— Evaluates EQL viewport formulas (rotate, translate)
Video Streaming
ui/video_stream.rs handles live H.264/AV1 video decoding and rendering as textures in the 3D viewport. Uses the video-toolbox crate on macOS for hardware acceleration.
Dependencies
Key crates used in the editor:
| Crate | Purpose |
bevy | ECS game engine, 3D rendering, windowing |
bevy_egui | Egui integration for Bevy |
egui | Immediate-mode UI framework |
impeller-bevy | Bevy plugin for Impeller telemetry |
arrow | Arrow data format for time-series |
eql | Elodin Query Language parser |
nox | Spatial math types |
Development Tips
- Use
cargo watchfor fast iteration on UI changes - The editor hot-reloads KDL schematics on file change
- Test with
examples/three-body/main.pyfor a lightweight simulation - GPU plot rendering is in
ui/plot/gpu.rs— changes here affect all telemetry graphs - The command palette (
ui/command_palette/) is the entry point for user actions
Screenshot-driven design, build, and test
Prefer Bevy's native window screenshot path over OS screen capture. It captures the full editor window (3D viewports and egui chrome) without macOS Screen Recording permissions, and works the same in local iteration and CI-style scripts.
Harness
| Piece | Path / env |
| Plugin | libs/elodin-editor/src/plugins/screenshot.rs (EnvScreenshotPlugin) |
| Batch script | scripts/ci/screenshot_examples.sh <out-dir> [example …] |
| Activate | ELODIN_SCREENSHOT=/abs/path/out.png |
| Delay before capture | ELODIN_SCREENSHOT_DELAY (seconds; default 8; use 12–20 for heavy examples) |
| Exit after write | ELODIN_SCREENSHOT_EXIT=1 (required for bounded runs) |
| Sim time | ELODIN_SCREENSHOT_TIME (seconds after the recording's first sample; holds the playhead there, paused; the delay is then settle time) |
| Tab | ELODIN_SCREENSHOT_TAB (a named split's title; warns at capture when no tab has it) |
The plugin queues Screenshot::primary_window(), waits until the PNG is non-empty on disk (async GPU readback), then sends AppExit::Success when exit is requested. Do not kill the process on a timer alone — that tears down the render thread mid-readback and yields a missing/empty PNG.
Streamed terrain has no timeout during interactive editor startup. Fixed-path
automation is deliberately stricter: set ELODIN_CESIUM_CAPTURE_TIMEOUT to
bound terrain warm-up; load errors and timeouts exit without a screenshot.
One-shot capture (design / verify a change)
# Release binary is much faster for visual loops
cargo build -p elodin --release
rm -f /tmp/editor-shot.png
ELODIN_SCREENSHOT=/tmp/editor-shot.png \
ELODIN_SCREENSHOT_DELAY=12 \
ELODIN_SCREENSHOT_EXIT=1 \
./target/release/elodin editor examples/ball/main.pyThen Read the PNG in the agent (vision) and check concrete UI/scene facts — e.g. status-bar RAM Usage: X.Y GB (not N/A / not stuck at 0.0), trajectory line present, view cube visible, graph panels populated. OCR (tesseract) is optional backup for status-bar text.
Batch regression (examples gallery)
# Default set: ball three-body drone rc-jet apollo-lander video-stream
# sensor-camera cube-sat voyager geo-frames
scripts/ci/screenshot_examples.sh /tmp/elodin-shots ball three-body droneEnv overrides: ELODIN_BIN, ELODIN_SCREENSHOT_DELAY (script default 20), SCREENSHOT_WATCHDOG (default 180). One editor at a time; each run has a watchdog so a hung capture cannot block forever.
Workflow for UI / rendering changes
- Baseline — screenshot the affected example(s) before the change into
/tmp/elodin-shots-baseline/. - Implement — keep the change scoped; rebuild
elodin(release for visual checks). - Compare — re-screenshot into
/tmp/elodin-shots-after/and Read both PNGs. Assert the intended delta and that unrelated chrome (timeline, status bar, view cube) still looks healthy. - Stress the failure mode — if the bug was GPU/render-path specific (e.g. FPV + HDR + plot_3d), pick the example that exercises that path (
rc-jet,sensor-camera, …), not onlyball. - Stale DBs — if an example refuses to start with DB/time-travel errors, delete its on-disk DB (e.g.
rm -rf examples/voyager/dbs/voyager,rm -rf video-stream-db) and retry. Do not dig into GStreamer until a clean DB still fails.
Gotchas
- Port 2240 — live
elodin editor/elodin runbinds the sim DB; do not parallelize with monte-carlo or another editor. Group-kill leftovers before the next case. - RAM gauge — status-bar RSS is read via platform APIs in
ui/status_bar.rs(not BevySystemInformationDiagnosticsPlugin). On macOS Bevy's sysinfo is built withapple-app-storeand always reports 0 GiB for the current process. - video-stream — clear
./video-stream-dbif the editor hangs or video never appears.elodinsink/x264enc/srtsrccome fromnix developornix develop .#run(GST_PLUGIN_PATH). Do not prepend cargotarget/release(libelodinmakesgst-plugin-scannerabort the scan on GStreamer 1.26). - voyager — needs SPICE kernels under
examples/voyager/nasa_spice_data/and a clean DB dir after interrupted runs. - nix develop — prefer it for CI-parity builds; for a tight screenshot loop, a warm
cargo build -p elodin --releaseoutside a full env rebuild is fine once the toolchain is already installed.
When to use which example
| Goal | Example |
| Lightest viewport + trail + vector label | ball |
| Multi-body + graph panels | three-body |
| GLB + joint animation | drone |
| FPV / plot_3d / aero | rc-jet |
| SITL + thrusters / descent | apollo-lander |
| H.264 tile in UI | video-stream |
| GPU sensor cameras / frusta | sensor-camera |
| Terrain / geo frames | geo-frames |
| Spacecraft + MEKF graphs | cube-sat |
Key References
- Bevy Tips (ECS): ../bevy/SKILL.md
- Editor QA plan: ../qa-test-plan/elodin-editor/test-plan.md
- Editor README: apps/elodin/README.md
- KDL schematic syntax: docs/public/content/reference/schematic.md
- Command palette reference: docs/public/content/reference/command-palette.md
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

