Improved execution time due to WebAssembly instance reuse
ordinary templates eject allows for customization of the wrapping component code
RE: performance
Templates from the default ordinary new example.com project running locally (M5 Pro, MacBook Pro) tend to be ~1ms for first request and <500µs for subsequent.
When the LMDB request cache is set ordinaryd logs ~150µs req/res latency.
If you haven't cracked one open: a Component Model binary is not a core module with extra sections. It's a container format — the component carries its own type, import/export, and wiring sections, and embeds one or more complete core WASM modules as nested payloads. Tooling that only speaks core WASM sees the wrapper and stops there.
We ship Hexana, a VS Code extension (and plugin for JetBrains IDEs) for inspecting WASM and other binaries. Its component view showed the component-level structure, but the embedded core modules were opaque blobs — to read their code you had to extract them first. As of this week's update, each embedded core module renders in place in the same virtualized WAT view used for plain .wasm files (virtualized meaning it parses per rendered element, so multi-megabyte modules don't choke the editor). When a component embeds multiple modules, a selector switches between them.
Curious what others use for component inspection day to day — wasm-tools component wit and friends cover the interface level well, but we haven't found much that lets you read the embedded module code without unbundling.
So I've been building userland.run, a RUST/WASM RISC-V 64-bit VM that runs entirely in your browser. It ships JS bridges for the terminal, an early app catalog (BusyBox apps, plus the full Node.js v25 pipeline), and all of it runs client-side. Zero server. If you know WebContainers, it's a cousin, except I went and emulated an actual RISC-V userland underneath because apparently I hate sleeping.
Where this is headed: a catalog of pure WASM apps you drive from a terminal OR hand off to an agent, with the inference engine also running in-tab. So the LLM lives in your browser too.
The dream: agentic dev and terminal work on YOUR machine. No cloud. No servers. No usage bill quietly ticking up while you sleep. Full privacy, your code never leaves the tab.
Now the honest part. I've been staring at this so long I genuinely can't tell anymore if it's a real thing people want or just a beautiful cathedral I built inside my own skull. So, WASM crew, I'm asking you directly: does this make sense, or have I been nerd-sniped by my own project?
Hi, happy to present to the community the challenging work and solution for the objective we had: Build an OS like environment that feels like a UNIX environment on top of webasm, where apps can run multi-process, multi-threaded. For several reasons we did not want to use WASI, instead we decided to work against FreeBSD like libc. There is lot of story to be said, in case there is interest. The tool was written for the yetty terminal app (https://github.com/zokrezyl/yetty), so that simple programs can be written in WASM and run in any environment where yetty runs: https://github.com/zokrezyl/yos. The intention is also to embedd yos into yetty, so that the user can run plugins inside the terminal.
AI coding assistants are good at reading source, but the moment you ship a binary, they go blind. Ask Claude Code or Codex about your compiled .wasm or native binary and it will reason from source-level guesses, not from what is actually in the file. We built the Hexana MCP server to close that gap, and today we are releasing 0.3.0.
What Hexana MCP does
The Hexana MCP server runs alongside your AI assistant and exposes tools that let it directly inspect compiled artifacts: WASM modules and native binaries. Instead of the assistant inferring what a binary probably contains, it can query the actual artifact and get structured answers back.
This matters for things like:
Debugging a WASM module where the source and the compiled output have drifted
Understanding what a third-party binary actually exports before you depend on it
Verifying that a build step produced what you intended
Giving an AI agent grounded, factual context about a compiled file when writing code that links against it
What is new in 0.3.0
The main additions are a set of binary inspection tools:
Summarize a WASM or native binary (size, section breakdown, import/export counts, format metadata)
Query binary records (imports, exports, memories, globals, table segments, data segments)
List or search functions across the module by name or index
So in a Claude Code session you can now say "summarize this wasm binary" or "find all functions matching gl_ in this module" and the assistant gets back real data from the file.
On the distribution side: 0.3.0 ships as native executables compiled with GraalVM Native Image on macOS arm64 and Linux x64. The Claude Code and Codex plugin wrappers will prefer the bundled native executable on those platforms automatically, which means no JVM cold-start on the common cases (the native image starts instantly, which matters when an agent calls the tool many times in a session). JVM fallback is still there for Windows and anything else.
Install (from inside Claude Code, the server ships with the plugin, no build step):
On macOS arm64 and Linux x64 the bundled native executable is used automatically. On Windows and other platforms it falls back to the JVM package, which needs a Java 21+ runtime on PATH. Free, by JetBrains. Codex users: the same plugin ships in the 0.3.0 release in Codex format ([VERIFY: exact Codex install path, not present in the prior post]).
Then ask Claude: "Use Hexana to summarize the imports, exports, and memories in<path>.wasm."
We are actively working on more tools (call graphs, dominator analysis, size bloat breakdown). If there is a specific thing you want an AI assistant to be able to ask about a binary, drop it in the comments.
One of the longstanding rough edges with Hexana's WAT tab was that opening a large module blocked until the entire text representation materialized. On something like Skiko (~8 MB, ~14 k functions) that was enough of a pause to be annoying. 0.5.0 changes the rendering model.
Virtualized WAT view. The tab now renders lazily — only the rows visible in the viewport are materialized at any moment, with the next batch fetched as you scroll. Section breadcrumbs let you jump directly to a named section (type, import, function, export, etc.) without scrolling through thousands of lines. An "Open in editor" action drops the current WAT state into a standard VS Code editor tab if you want to select across it, search, or diff two modules side by side. For a 14 k-function module the practical difference is that section navigation is now immediate rather than proportional to module size.
Node.js WASM debug — breakpoint race fixed. The CDP debug path for Node.js shipped in 0.4.0. This release fixes a race where setting a breakpoint before the Node.js runtime finished its WASM compilation and reported the module as loaded caused the breakpoint to be silently dropped. Breakpoints set at any point before the module starts executing are now delivered correctly. Local variable resolution in complex scope structures is also more accurate.
The other two items in this release (JVM .class/DEX structural inspection, ZIP64 archive support) are less WASM-specific but noted in the changelog if they're relevant to your toolchain.
Requires VS Code 1.102+. We build this at JetBrains; it's free.
Curious how people here are working with large .wasm outputs right now — what sizes and what tooling, and where does the tooling fall down?
We've been working on Hexana, an IntelliJ Platform plugin for WebAssembly and binary analysis, and the 0.12 release has a few things that might be interesting to this community.
Component Model diff
Compare WASM With… shipped last week for core WASM modules. 0.12 extends it to Component Model binaries: when the two files you're comparing are components, the diff drills into the embedded core modules and nested sub-components recursively — each pair opens in its own tab, running the same Size Impact / Entities / WAT pipeline on zero-copy slices of the component binary. The recursion bottoms out at core modules where the function matcher already operates.
Components also get a WAT (virtualized) tab in this release, and the Top size profiler now fully breaks down nested sub-components and embedded core modules.
Static-library archives
.a archives (ELF/Mach-O object files) and .lib (Windows COFF import libraries) now open to a Members list — name, detected format, size, bookkeeping entries hidden. Click a member to extract and open in disassembly. Detection by content magic (!<arch>\n), not by extension.
Object-file members disassemble per function in the Capstone view: section-relative symbol resolution, each named function as a separate entry rather than a flat .text dump.
Other
Android DEX basic support (classes and members). ZIP64 archives. Exports/Imports tabs got per-row affordances: Copy Name, Find Usages for function imports (jumps to callers in WAT, cap 15), Navigate to Function in WAT for function exports.
Minimum IDE: IntelliJ IDEA 2025.2+ (build 252) or any same-version JetBrains IDE. Search "Hexana" in Plugins, or:
Hey, I'm porting KiCad to the web with collaboration.
The plan is to build a self-sustaining bootstrapped business around the syncing / storing parts ( we have to pay for that ) while having a solid free / local tier. The full launch is coming soon ( month? week? ), and I have the first demo of gerbview ( rest coming soon! )
Our port is close~ish to kicad and we want to upstream it, but it will be a challenge, we have a lot of wxwidgets changes. We'll see.
Let me know what you think, what we should fix / change, if there's anything we've missed. We're building on the shoulders of giants, and I want to be as respectful to the open source community, if we've missed something let me know and I'll fix it.
We'll have email updates, you can subscribe on the landing page if you're interested.
I added a module-to-module diff to Hexana (a binary-aware IDE plugin) and the two things
that turned out to matter most for reading a real diff were (1) matching functions
structurally so a renumber isn't reported as churn, and (2) calling out new imports
explicitly. Sharing the approach because both are general WASM problems, not plugin-specific.
Position-based diffing is useless on optimized output. Insert or remove one function and every index after it shifts, so a naive diff attributes byte deltas to unrelated functions. The Size Impact view instead pairs functions with a semantic matcher: a content hash plus the call graph, with a second hashing round that substitutes already-matched call targets — so a body that was rewritten but still calls the same set of functions gets paired, and calls to imported functions help discriminate. A pure renumber is reported as moved (zero bytes), not a spurious size change. Each row carries the classification (identical / moved / modified) and a confidence for non-exact matches.
Minified names don't have to defeat it. It detects when import/export names were minified (e.g. Binaryen --minify-imports-and-exports) and says so. Drop the symbol-map sidecar next to the .wasm (<file>.symbols from --emit-symbol-map) and it restores the original names so functions match by name again. It reads both shapes: function-index (index:name) and import/export (minified:original, including Binaryen's original => minified console form).
The supply-chain angle. An Entities tab classifies every entity kind — imports, exports, functions, globals, tables, memories, types, data and element segments — as added / removed / modified / moved. New imports get a banner, with host namespaces like env / wasi_* highlighted, because "what can this module suddenly call into the host that the last build couldn't" is exactly the question you want answered when you bump a dependency and re-pull a module you didn't compile yourself.
Selecting a function opens an on-demand side-by-side WAT comparison rendered with symbolic names, so an unchanged caller of a renumbered callee reads identically instead of lighting up red/green.
Happy to talk about the matching heuristics — where do you see them break? Optimizer passes
that inline aggressively are the case I most expect to fool the call-graph hash, and I'd like
real counterexamples.
Hexana for VS Code is an extension for inspecting and running WebAssembly (and native ELF/Mach-O/PE) binaries in the editor. In 0.3.0 we added Node.js and the browser as run targets but they were run-only. 0.4.0 closes that gap.
Debugging on Node.js and Chrome. Both runtimes are now debuggable over the Chrome DevTools Protocol — Node.js is launched with --inspect-brk, Chrome with --remote-debugging-port, and Hexana translates between VS Code's Debug Adapter Protocol and CDP. So breakpoints, stepping, the call stack, and variable inspection work against the module running in the JS host, with VS Code's normal debugger UI. This is a separate backend from the existing lldb path (Wasmtime / WAMR, which needs LLVM 22.1+); GraalVM stays run-only.
In-place byte editing in the hex viewer. You can now edit individual bytes directly in the hex viewer and write them back to the file. It is overwrite-only — the file size never changes (no insert/delete), which keeps every section offset valid; handy for flipping a flag byte or a constant and re-running without leaving the editor.
Requires VS Code 1.102+. Curious what the WASM-debugging crowd makes of the CDP path versus the lldb one — which matches your toolchain, and where does source mapping fall down for you?
I recently built a browser-use (think LLM clicking on webpages, entering text, etc) agent completely on WASM, AFAIK this is the first of its kind but correct me if I'm wrong. I'm interested in making it better so wanted to ask for help from the community.
Pass said image to the VLA (ShowUI-2B) using wllama - which interfaces to the LLM using WASM + WebGPU
Convert coordinates to actions for the browser to take
WASM worked quite well for this but it had its own constraints.
Memory usage - not sure if this is WASM or WebGPU constraint, but the context size I get is so small it makes doing anything with any accuracy quite difficult. Are there any plans for them to increase memory limits in WASM? Memory64?
Needs COOP/COEP (SharedArrayBuffer) + JS - the library wllama required this, does anyone know why they would make this choice as a library?
Anyone have any tips for running LLMs on WASM? I think if I can unlock bigger param models my accuracy could get a lot better. Maybe I can do some sort of streaming instead.
I work on Hexana (binary analysis in JetBrains IDEs) and just packaged its WASM extraction as an MCP server so an agent like Claude Code can query a module directly. Sharing the design because the "agent + WASM" space is mostly "let the model read wasm2wat output and hope," and I think the interesting line is elsewhere.
The premise: an LLM staring at raw bytes gets the structural details wrong — call_indirect targets, name-section global-vs-local indexing, LEB128 — and can't tell that it's wrong. Those are deterministic functions of the binary format, so a tool should own them and the model should reason over the result. One tool, query_artifacts, focused operations:
Host / supply-chain import audit — exactly which imports (env, wasi_*, …) a module demands, vs what the sandbox allows.
API/ABI diff between two builds — changed signatures, public type indices, reference-type import ABI risks (useful in CI).
Crash-frame triage — stack funcidx → function identity + memory-write/host-call effects, across a 14k-function module.
It reads name sections (with the global-vs-local index gotcha baked in), handles components, and is meant to complementwasm-tools/wabt, not replace them — and it is explicitly not a decompiler. The edge over shelling out to wasm-objdump is structured query at scale + staying grounded for the agent.
Honest status: v0.1.0, WASM-only. Install is one line in Claude Code — /plugin marketplace add [email protected]:JetBrains/hexana.git, then pick Hexana from the new marketplace (server bundled, no build; needs a Java 21+ runtime). Curious what .wasm facts you most want an agent to get right.
We're excited to announce the new release of WebAssembly Language Tools, v0.11.0. WebAssembly Language Tools aims to provide and improve the editing experience of WebAssembly Text Format. It delivers deep and smart static analysis, precise type checking, and full-featured editor integration — plus a configurable formatter — making WebAssembly development fast, safe, and joyful.
Formatter received a huge performance improvement in this release. Here is the benchmark result:
Environment
Before (µs)
After (µs)
Time Reduction
Speedup
Linux 7.0 on Intel i7-12700K
23.493
7.0656
↓ 69.92%
3.32×
M4 Mac mini
20.729
6.0717
↓ 70.7%
3.41×
There's a blog post (written in Chinese) about how we optimized it.
Lints and Checks
New lint: Check omitted idx of immediates
Due to compatibility, WebAssembly allows omitting idx in some memory and table instructions, such as i32.load and table.get. This lint checks this case and suggests adding such idx. A code action for fixing this is available in previous versions.
It's no secret that WebAssembly accelerates compute-bound ops, but when porting numpy-ts to it, I realized that the native parity was not bound by WASM itself, but by the memory transfer overhead.
Wrote up some lessons about this - might be obvious to some of you but hope it's helpful for some!