← All projects

A runtime & debugging engine

glassjar

My fork of debugger.sh, the engine I built with Jacob Roberts-Baca, Fabio Ibañez, Justin Vassantachart, and Chris Gregg. Our paper was accepted at SIGCSE TS 2027.

RustWebAssemblyDebuggersCS EducationCloudflare Workers

glassjar runs and debugs code locally in the browser. It started as debugger.sh, a project I built at Stanford with Jacob Roberts-Baca, Fabio Ibañez, Justin Vassantachart, and Chris Gregg, and that we wrote up together in a paper accepted at SIGCSE TS 2027. The first half of this page is that shared work. glassjar is my fork of it, where I’ve kept building on my own, and what it adds is further down.

The motivation came out of teaching. In every intro class, the first few weeks go to fighting installation problems instead of writing code. We wanted something that would let us run, debug, and visualize code without anyone installing anything.

For C/C++, Python, and Rust, we take the real toolchains and compile them to WebAssembly, targeting WASI:

C / C++
Clang 22.1
Python
CPython 3.11
Rust
rustc 1.96, lightly patched

So the real compilers for these languages run right in your tab.

Built as a library

We decided early on to make this a headless library, so anyone who needs to run or inspect code can drop it into their own system. That’s why we call it the engine.

An educator can fit it into their class, and since the engine has full access to the program’s memory, things like live code visualization become possible. Outside of education, it works for any case where a person or a service wants to run and inspect code without a backend.

In a classroom, that means code snippets you can debug right inside lecture notes, autograders that run on the student’s machine, and memory diagrams built from real program state instead of a whiteboard.

Piloting it with students

We piloted it in a CS2 section at Stanford, and 70% of program runs were followed by an actual debugging action: a breakpoint, a step, or a continue. We never told students to use the debugger. It was just there, so they used it.

Seeing where the pointer is when looping through the linked list helped me understand what is actually going on.

sum.c Paused at line 10
  1. struct node {
  2. int val;
  3. struct node *next;
  4. };
  5. int sum(struct node *head) {
  6. int total = 0;
  7. struct node *cur = head;
  8. while (cur) {
  9. total += cur->val;
  10. cur = cur->next;
  11. }
  12. return total;
  13. }

Variables

total
3
cur
node 2 (val 1)

Memory

3 1 4 NULL
What the debugger shows while it walks a linked list. Scripted for this page, but it's the same view glassjar gives you.

What glassjar adds

After the paper, I forked both halves of the project, the engine and the IDE around it, to keep building on them.

The engine is published on npm as glassjar. It carries the group’s engine forward along with later debugger and compiler fixes from Jacob and Justin, which I merged into one line. On top of that I:

  • serve the compiler toolchains from my own CDN, and retry downloads that fail on a flaky network instead of failing the run
  • let a site host the engine’s WebAssembly itself (a single wasmUrl option) rather than depend on a public CDN

The IDE is live at ide.yousefabuhashem.com. I:

  • replaced its Supabase backend with a small Cloudflare Worker API on R2 for share links and telemetry, with a hard daily write budget so a traffic spike can’t turn into a bill
  • redesigned the interface to be easier to pick up: a visible C++/Python/Rust switch, Run that turns into Debug once breakpoints are set, a status pill showing where the program is paused, panels that come forward on their own, and a layout that works on a phone

I also just want to explore how far this can stretch beyond education. LeetCode, HackerRank, interview tools, and docs with live examples all run untrusted code on their own servers. LLM apps run small snippets all the time too, like when they make you a graph. I wonder how much of that could move to the user’s device, and what it would save.

Speaking of LLMs, when an LLM debugs, it mostly reruns the code, adds print statements, and reads the output. That’s not how we teach people to debug. In every OS class I took, the debugger and I spent a lot of long nights together. glassjar could give an LLM the same debugger.

Try it

npm install glassjar

Or open the glassjar IDE and start typing. The group’s original debugger.sh is still up too.

Fair warning: the first run is slow, because your browser has to download an entire compiler before anything happens. It caches after that.

If you are here, you are curious :) read more, and reach out!

This project had a lot of strange problems: compiling compilers to WebAssembly, rewriting binaries to slip debug hooks between statements, and pulling debug information back out of the output to turn it into something a person can read.

If you’re interested, our paper has the details of the engine we built together. It was accepted at SIGCSE TS 2027, and that link is the preprint until the ACM version is out. Or, even better, let’s talk about it over coffee.