open source · MIT
imshell: Dear ImGui apps on every platform.
You write one frame(). It brings the rest.
A small C++20 toolkit around Dear ImGui. No browser engine, no runtime.
imshell opens the window, sets up the graphics backend and the Dear ImGui backends, runs a frame loop that idles when nothing changes, and fills the gaps between ImGui and each operating system: a title bar with the real OS buttons, touch and the soft keyboard on phones and tablets, native views in the layout, fonts, file dialogs, haptics and auto-update. Dear ImGui stays yours, compiled once by your project. It grew out of DearSQL, a SQL client for desktop, iPad and iPhone, where it runs everything between the OS and the UI.
> Platforms
## The whole app
A delegate draws a frame; imshell::Run does the rest. The same file builds for every platform above.
#include "imshell/app.hpp"
#include "imshell/button.hpp"
struct Hello : imshell::Delegate {
int clicks = 0;
void frame() override {
const imshell::Rect r = imshell::ContentRect(); // under the title bar, inside the safe area
ImGui::SetNextWindowPos(r.pos);
ImGui::SetNextWindowSize(r.size);
ImGui::Begin("hello", nullptr, ImGuiWindowFlags_NoDecoration);
if (imshell::Button("Click me", imshell::ButtonVariant::Primary))
++clicks;
ImGui::Text("Clicked %d times", clicks);
ImGui::End();
}
};
int main() {
static Hello hello;
return imshell::Run({.title = "Hello", .titleBar = true}, hello);
}In CMake, next to your own Dear ImGui:
set(IMSHELL_IMGUI_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/imgui)
add_subdirectory(external/imshell)
add_executable(app main.cpp ${IMGUI_SOURCES})
target_link_libraries(app PRIVATE imshell::imshell) # + imshell::components, optional## What it has
- * Platform shell: the window, the graphics backend, input, and a loop that idles when nothing changes and skips frames identical to the last.
- * Title bar: draw your own bar in ImGui; imshell keeps the OS buttons, dragging, snap layouts and double-click zoom.
- * Touch: tap to click, long press for menus or the text toolbar, drag to scroll with momentum.
- * Native views: a real NSView, UIView, HWND or GtkWidget (a text field, a map, a web view) in the ImGui layout.
- * Themes and widgets: eighteen palettes; buttons, selects, toggles, splitters, spinners, menus and modal alerts that follow them.
- * Components: optional text fields, cards, badges, callouts, progress, avatars, metrics, chips and toasts.
- * Editor: an optional code editor: selection, undo, find and replace, with highlighting and completion as hooks.
- * Fonts and files: one UI font from a text font, icon fonts and the system's CJK font; file dialogs; fonts and images baked into the binary.
- * Auto-update: Sparkle, WinSparkle or a checked AppImage swap, behind one call.
## Performance
Native code and a loop that sleeps when nothing changes: small binaries, a first frame in milliseconds, and an idle window that costs next to nothing.
149 ms
launch to first frame
0.1 %
CPU while idle
1.5 MB
the whole app
314 KB
gallery in the browser
> macOS, release build
hello · gallery
| Executable, stripped | 1.5 MB | 1.5 MB |
| Memory | 30 MB | 82 MB |
| CPU | 0.1 % idle | 3.1 % animating |
| Launch to first frame | 149 ms |
Apple M4, 16 GB, macOS 27.0.1, imshell f1a00de, 2026-11-11. hello is the repo's example app: a title bar, buttons and two native views (a text field and a date picker). gallery has every component and the code editor, and never idles: its loading skeleton and progress bar redraw every frame, so its CPU is the cost of animating. Release builds with Dear ImGui, imshell and GLFW linked in, stripped. First frame: from launching hello until it has drawn its first frame and quit, the median of 11 runs. Memory: the physical footprint 3 s after launch. CPU: the time used over the next 10 s, the window focused and left alone. In the browser: the gallery's .wasm and .js as this site serves them (brotli), 279 + 35 KB. Windows, Linux and the phones are not measured yet. site/bench.sh measures it again.