Plots that can't lie
Curves are evaluated with interval arithmetic into an enclosure that provably contains every value. The arithmetic finds poles and asymptotes, so a plot never draws a line through one.
You write Java 25 and ship a native executable for Windows or Linux that draws with Vulkan. Everything between the two is built to be fast, deterministic and easy to observe.
You change widgets through thread-safe handles from any thread. The GUI thread takes those changes once per frame and draws the whole window with one SDF uber-shader. If nothing is moving and no input arrives, the loop sleeps and draws nothing.
Move your pointer over this panel. The meter only draws a frame when there's input or something is animating, the same way the loop does.
There are exactly five lanes. The main thread keeps Vulkan, the window and the present, and nothing else. App logic runs on component threads, disk work on a bounded offload lane, and time on its own timeline. The annotation processor decides placement at compile time, so the binary has no scheduler and no work stealing.
Illustration. All lanes are platform threads, and placement is fixed in the binary.
Most of the stack was written with Claude Code, Anthropic's coding agent, working alongside its author. An agent that only checks that the code compiled hasn't really checked anything. Debug builds have an automation port, and ottermate uses it to launch the app, click, type and wait for it to settle, then take a screenshot with the app's own GPU.
An example session, shortened.
Shaders are written as SupirVast IR in Java and lowered to SPIR-V at build time. That same IR also runs on the CPU, and a test suite checks that the CPU and GPU agree. The uber-shader is assembled from shadelets, a chain of source, modifiers, painters and composite. A look is one such chain with its styles. Hover and pressed are simply different looks.
Mimicked in CSS on this page. In VexelRay each look is a set of painters inside the one uber-shader.
It is built like ChucK's clock and Vue's graph. A Shred runs in zero logical time between advance(ms(250)) calls, so it can't drift and can't race. Signals form a dependency graph, and each knows how far ahead its value is fixed, so a pure animation is computed in advance and reading it at now is just a buffer index. Swap in the virtual clock and a ten-minute UI scenario runs in microseconds.
Ratios, not doubles. Eases land exactly on 0 and 1Three easings driven by one logical clock. Each run is identical, frame for frame.
Inside the VM, messages go over a zero-copy bus with versioned, lock-free state snapshots. When a message has to leave the process, elektro-Q carries the same topic over TCP, a Unix socket or UDP, with codecs generated at compile time from @Message records. The fast in-VM path never pays for the network.
ElektroBridge carries a local topic across the wire in both directions, with loop preventionYou write ordinary Java 25 with dependency injection in the Spring Boot style. An annotation processor does the wiring at compile time, so there is no reflection and the app starts as fast as a hand-written main. GraalVM native-image then turns it into one native executable, for Windows or Linux. The bindings to Win32, X11 and Vulkan use Panama FFM directly, with no LWJGL, GLFW or SDL.
The installer generator writes each app's installer, updater and uninstaller from a single installer.json, and writes the suite's one-line install as well. Installs are per user and need no administrator. Each app gets its own entry in Settings. The apps find and launch each other through the install registry.
irm https://sibarum.github.io/install.ps1 | iexWindows 10 or 11, 64-bit, with a Vulkan driver. What it changes. On Linux, one line of sh installs the snapshot builds: get it here.
An annotation processor writes a straight-line codec for each record, with no reflection, so it works under native-image. Fields are stored by position with no tags. Integers are zigzag varints, and nulls and booleans share one bitset. A structural fingerprint catches schema drift. Every payload also has a readable text form.
intrabuf inspector, and fromBytes accepts either formIllustrative layout, not a byte-exact dump. The timings come from a quick loop rather than JMH, so read them as orders of magnitude.
More of the things the stack does underneath that you wouldn't expect from a desktop framework.
Curves are evaluated with interval arithmetic into an enclosure that provably contains every value. The arithmetic finds poles and asymptotes, so a plot never draws a line through one.
Noto Sans and Noto Mono are baked into MSDF atlases at build time. Shadow, lit edges and letterpress are transfer functions over one rounded-box SDF, with no textures and no extra passes.
The fluid sim is two-fluid MLS-MPM, with water riding on mercury at 13.6:1. Rigid bodies use XPBD with Coulomb friction, at 1.2 ms a step for 4,096 spheres. Both run on a second Vulkan queue.
Lean proofs cover the fluid's fixed-point particle-to-grid scatter. It produces the same grid under any atomic ordering, and its quantised shares conserve mass and momentum exactly.
Images from PNG to QOI and SVG. Video in H.264, HEVC, VP9 and AV1. Meshes in OBJ, PLY and STL. The codec is optional, so an app with no pictures links no decoders.
Vulkan draws and a D3D12 flip-model DXGI swapchain presents. Resizing reallocates nothing, which avoids the multi-second stalls hybrid-GPU laptops are known for.
VexelRay would not exist without three pieces of other people's work, and we're grateful for each of them.
Most of VexelRay was written with Claude Code, Anthropic's coding agent, working alongside its author: the engine, the framework, the GUI and the applications. Ottermate exists so Claude can see the windows it builds.
Oracle GraalVM's Native Image compiles every application ahead of time into a single native executable, for Windows or Linux, that runs without a JVM. Truffle, from the same project, runs SupirVast's shader IR on the CPU.
Every pixel VexelRay draws goes through Vulkan, the open, cross-platform graphics and compute API, and every shader is compiled to SPIR-V. The simulations run their physics on Vulkan compute queues.
VexelRay is independent and not affiliated with or endorsed by Anthropic, Oracle or the Khronos Group. The fonts, libraries and other third-party software in the applications are listed with their licenses on the licenses page.
| Language | Java 25, built with Maven |
|---|---|
| Release binary | GraalVM native-image, one executable per app for each platform (38–68 MB on Windows) |
| Graphics | Vulkan, presented through a DXGI flip-model swapchain. Bindings use Panama FFM directly |
| Shaders | SupirVast IR → SPIR-V at build time. The same IR runs on the CPU through Truffle |
| GUI | Retained node tree, a single SDF uber-shader, flex layout in rem, em, dp, % and viewport units, zoom from 0.5× to 3× |
| Frame loop | Draws on demand. 0 fps when idle, 1.03 ms median wake to frame |
| Threading | 5 lanes placed at compile time, platform threads, a watchdog per lane |
| Clock | Kronometer: realtime, virtual (deterministic) and driven clocks, and 4 slip policies |
| Messaging | Atchung in-VM bus. elektro-Q across processes over TCP, Unix sockets or UDP |
| Serialization | Intrabuf: generated codecs, positional varint format, text form |
| Automation | Loopback automation port in debug builds, driven by the ottermate CLI |
| Install | One line, PowerShell on Windows or sh on Linux, per user, SHA-256 verified, and re-running it updates |
| Platforms | Windows 10 and 11, 64-bit, and 64-bit Linux on X11 or XWayland. The macOS backend is not finished |
| Status | 0.1.1, an experimental prerelease, with 0.1.2 snapshots on Linux. Nothing in it is stable yet |
Nine applications built on the framework, installed with one line. Or build your own from the template, with an agent or without one.