Library / SDK
emilk/egui avatar
emilk/egui

egui: immediate mode GUI in Rust, and the cost of that choice

egui: an easy-to-use immediate mode GUI in Rust that runs on both web and native

30,558 stars2,136 forksRustApache-2.0

At a glance

What is it?
egui is an immediate mode GUI library in pure Rust that runs the same code on web and native through eframe. The interesting question is not what it draws but what immediate mode gives up, and the README is explicit that the interfaces are still in flux.
Who is it for?
Adopt egui when you need the same Rust UI code on web and native, or when the UI is a tool panel inside something that already owns the render loop. Do not adopt it if you need a native-looking interface or a stable API surface, since the README states the interfaces are still in flux and that new releases will have breaking changes.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

What egui is for, and what it refuses to be

egui is a library you call into, not an environment you program for. That sentence in the README is the whole design brief. The intended user is someone writing a Rust program that needs a control surface: a debug panel, a level editor, a plotting tool, a settings window. The README also points at the Rerun Viewer as an example of a professional-looking application built with it, which is a useful anchor for the upper end of what the library is expected to carry.

The stated goals are the easiest to use GUI library, responsiveness targeting 60 Hz in a debug build, portability between web and native, and no unsafe code. The non-goals matter just as much: egui does not intend to become the most powerful GUI library, and it does not intend to produce a native-looking interface. If your requirement is a window that looks like the platform it runs on, this project has already told you it is the wrong tool. What you get instead is one codebase and one visual identity across targets.

Immediate mode means the UI is rebuilt every frame

In immediate mode there is no retained widget tree. Each frame, your code runs top to bottom and calls into the UI: the README example shows ui.heading, ui.horizontal with a closure, ui.text_edit_singleline, egui::Slider::new, ui.button, and ui.image. Widgets are constructed, drawn, and dropped within the same pass. There are no callbacks, which is listed as a goal rather than an implementation detail.

The consequence is that application state lives in your own variables, not in the widgets. In the example, the name string and the age integer are owned by the caller and passed by mutable reference into the text field and the slider. When the button is clicked, the code increments age and the next frame draws the new value. Nothing in egui holds that state for you, and nothing needs to be synchronised back out of the toolkit.

This is why egui can be dropped into environments that already own a render loop. The README states egui can be used anywhere you can draw textured triangles, and that integration into a game engine is a supported path. The custom painting API is epaint, exposed separately. The trade-off is that layout and hit testing are recomputed continuously, and the project's own performance goal is framed as a debug-build target rather than a claim about large widget counts.

eframe is the piece that makes web and native the same target

egui itself is described as completely platform agnostic. The framework that turns it into an application is eframe, which the README says supports Web, Linux, Mac, Windows, and Android. The native backend is egui-wgpu, built on wgpu, and the README states it should work out of the box on Mac and Windows.

Linux is the case where the README gives explicit prerequisites before the demo will build. On Debian-derived systems the listed packages are libclang-dev, libgtk-3-dev, libxcb-render0-dev, libxcb-shape0-dev, libxcb-xfixes0-dev, libxkbcommon-dev and libssl-dev. On Fedora Rawhide the README lists clang, clang-devel, clang-tools-extra, libxkbcommon-devel, pkg-config, openssl-devel, libxcb-devel, gtk3-devel, atk and fontconfig-devel. The README adds a note that these are needed for the demo app only, not for egui itself.

For web output the README does not describe the build pipeline in the main body. It directs readers who want a web app to the separate eframe_template repository, and the hosted demo is stated to work in any browser with Wasm and WebGL support. That is the extent of what the material confirms about the web path.

Getting the demo running locally

The README gives one command for running the demo application from the repository: cargo run --release -p egui_demo_app. The release flag is in the command as written, which is consistent with the performance goal being stated for debug builds. On Linux, install the package list above first, otherwise the build will fail at the system library stage rather than in Rust code.

For your own application the README points at the examples/ folder in the repository and at docs.rs/egui for the API. There is no configuration file, no project generator and no CLI described in the material. Configuration is done in Rust code through the API, for example egui::Slider::new(&mut age, 0..=120).text("age") in the README example, where the range and the label are arguments to the constructor rather than entries in a settings file.

The README also lists an image macro, egui::include_image!("ferris.png"), used with ui.image. That is the asset path shown in the example, and it is the only asset-loading mechanism named in the material.

The breaking-change policy is the real adoption cost

The README is unusually direct here: egui is in active development, it lacks many features, and the interfaces are still in flux. It states that new releases will have breaking changes. That is not a hedge buried in a changelog, it is in the State section of the front page.

The release history in the repository is consistent with that posture. The three most recent releases are 0.36.0, 0.36.1 and 0.36.2, spaced roughly a month apart, and the notes describe narrow changes: improved mobile keyboard support in 0.36.0, a Sense::drag() bugfix in 0.36.1, and a TextEdit::event_filter addition plus bugfixes in 0.36.2. A patch release that adds a public API item tells you the versioning is pragmatic rather than strictly additive.

The practical cost is that upgrading is a code-editing task, not a dependency bump. There is no migration tooling mentioned in the material, and no long-term support branch. If you pin a version and stay on it, you keep working code; if you track main, you should expect to fix compilation errors on a regular cadence. A binary that vendors a specific egui version and never updates is a legitimate strategy here, and the README does not argue against it.

Where egui stops, and what retained mode gives instead

The built-in widget list in the README is concrete and finite: label, text button, hyperlink, checkbox, radio button, slider, draggable value, text editing, colour picker, spinner, images, tooltips on hover, collapsible headers, panels, scrolling regions, windows that can be moved, resized, minimised and closed, and label text selection. Accessibility is provided through AccessKit. Beyond that, the README points to a community-maintained wiki of third party crates for additional widgets.

If you need a data grid with virtualised rows, a docking system, or a tree view with drag and drop reordering, none of those appear in the built-in list. You would be looking at third party crates or writing the widget yourself. The README frames extensibility as a goal and links a worked example of a custom toggle switch widget, so the path exists, but it is work you own.

The alternative with a genuinely different approach is a retained mode toolkit such as iced. There, you build a tree of widgets and messages, the framework diffs and updates that tree, and state lives inside the framework's own structures. Layout is computed when the tree changes rather than every frame, and widget identity is stable by construction. The cost is that you program inside a framework's model rather than calling drawing functions from your own loop, and embedding the UI inside an existing render loop is a different kind of problem. egui's README explicitly positions itself against that: it is a library you call into. Choose based on whether your program already has a main loop that you control.

Licence, dependencies and what to verify before adopting

egui is dual licensed MIT and Apache-2.0, with both licence files present in the repository. That is the standard permissive pairing for Rust crates and is compatible with closed-source distribution, but the exact obligations depend on which of the two you take and on the licences of transitive dependencies. Nothing here is legal advice; if you ship a binary, read LICENSE-MIT and LICENSE-APACHE and check your dependency tree.

The README states that egui has a minimal set of default dependencies and that heavier dependencies are kept out even as opt-in, with all code in egui being Wasm-friendly. The demo application is a different matter: it pulls in wgpu through egui-wgpu and, on Linux, the system libraries listed above. Keep those two dependency profiles separate when you estimate build times and CI images.

There is no unsafe code in egui, per the README and the safety-dance badge. That is a verifiable property rather than a marketing line, and it is one of the few claims in the material you can check mechanically by searching the crate source.

What the material does not tell you: how egui performs with very large numbers of widgets, what the web build size is, or how the Android support behaves in practice. Those are the things to measure on your own target before committing.

Editorial conclusion

Adopt egui when you need the same Rust UI code on web and native, or when the UI is a tool panel inside something that already owns the render loop. Do not adopt it if you need a native-looking interface or a stable API surface, since the README states the interfaces are still in flux and that new releases will have breaking changes. Before committing, read the Goals and Non-goals sections, run cargo run --release -p egui_demo_app on your target OS to confirm the wgpu backend works there, and check the 3rd party egui crates wiki for the specific widget you need, because the built-in widget list stops at sliders, colour pickers and text editing.

Official sources

  1. emilk/egui on GitHub
  2. License: Apache-2.0
  3. Project website
  4. README
  5. Releases
Community notes

Community notes