jaxplorer
A compiler explorer TUI for JAX. Put a jitted function on the left, watch its jaxpr, StableHLO and optimized HLO on the right, and see all three change as you type.
┌─ source ─────────┬─ Jaxpr │ StableHLO │ Optimized HLO │ Analysis │ Passes │ LLVM IR ─┐
│ def f(x, w): │ { lambda ; a:f32[8,16] b:f32[16,4]. let │
│ return jnp.tanh(x @ w)│ c:f32[8,4] = dot_general[...] a b │
│ │ d:f32[8,4] = tanh c │
└───────────────────────────┴────────────────────────────────────────────────────────┘
cpu · jax 0.11.0 · 134 ms · ok
Installation
uv sync # in a checkout
uv tool install "jaxplorer[jax]" # standalone, with its own jax
uv tool install jaxplorer # standalone, borrowing a project's jax (see below)
Needs Python 3.12+ and textual >= 6.0.
jax >= 0.9 is an extra, since the jax worth inspecting is usually a project's own.
Any CPU-only jax install is enough; a GPU or TPU backend is only needed to compile for one.
Usage
uv run jaxplorer # scratch buffer
uv run jaxplorer mlp # open a bundled example (mlp, scan, attention)
uv run jaxplorer my_model.py # open a snippet and edit it in place
uv run jaxplorer my_model.py --watch # keep editing in your own editor; jaxplorer reloads on save
uv run jaxplorer mlp --print optimized_hlo # print one pane and exit, no TUI
| key | |
|---|---|
f1 or ? |
list every key (the footer only fits a few) |
ctrl+r |
recompile now |
ctrl+s |
save the buffer |
ctrl+z, ctrl+y |
undo, redo (cmd+z / cmd+y also work) |
ctrl+f or / |
find in the active pane; n / N cycle the hits, escape clears |
f2 |
switch backend (skips ones that already failed here) |
f3 |
show or hide the HLO debug tables |
f4 |
diff pass snapshots as graphs instead of as text |
f6 |
collect per-pass HLO and LLVM IR, then recompile |
alt+1 … alt+7 |
jump to a pane |
down |
from the tab bar into the IR, then arrows scroll it |
], [ |
next, previous section in the Passes pane |
y |
copy the active pane to the clipboard |
escape |
from the IR back to the tab bar |
ctrl+q |
quit |
Click an instruction in the Optimized HLO or Passes pane to select the source line that produced it.
Other options: --version, --python PATH (compile under another environment's jax, see
below), --platform cpu|gpu|tpu, --x64, --timeout SECONDS,
--stages jaxpr,stablehlo,... (the chain stops after the last stage asked for, so leaving out
optimized_hlo skips XLA — most of a compile on a large model), --passes to collect per-pass
HLO and LLVM IR from the start, --structural-diff to start with f4 on,
--print PANE to write one pane to stdout and exit instead of starting the TUI, and
--examples to list the bundled snippets.
Against your own project's jax
jaxplorer compiles in a subprocess, and that subprocess can be your project's interpreter:
cd my-project
uv run jaxplorer model.py # lookup via uv (VIRTUAL_ENV)
jaxplorer model.py --python .venv/bin/python # or name the interpreter outright.
The interpreter is chosen in this order: --python, then $VIRTUAL_ENV, then the one running
jaxplorer. uv run and a plain activate both export VIRTUAL_ENV, so inside a project the
flag is rarely needed.
Anatomy of a snippet
A snippet is an ordinary Python module that defines a callable f and a tuple args of
example inputs. Nothing needs to import jaxplorer.
import jax
import jax.numpy as jnp
def f(x, w):
return jnp.tanh(x @ w).sum()
args = (
jax.ShapeDtypeStruct((8, 16), jnp.float32),
jax.ShapeDtypeStruct((16, 4), jnp.float32),
)
args may hold concrete arrays or jax.ShapeDtypeStruct specs. jaxplorer only traces and
compiles f, never runs it, so shape specs are enough. Optionally define kwargs,
static_argnums, static_argnames or donate_argnums; they are passed to jax.jit. Three
examples ship in the wheel — jaxplorer mlp, jaxplorer scan, jaxplorer attention — for an
MLP, a lax.scan loop, and causal attention with a static argument. They open as a scratch
buffer, so editing one cannot write over your installation.
How it works
Each pane is one step of JAX's public lowering chain:
| pane | source |
|---|---|
| Jaxpr | jax.jit(f).trace(*args).jaxpr |
| StableHLO | .lower().as_text() |
| Optimized HLO | .compile().as_text(), after XLA's optimization passes |
| Analysis | .cost_analysis() and .memory_analysis() |
| Passes | a snapshot between every XLA pass, diffed to show which pass changed what |
| LLVM IR | the CPU backend's LLVM IR, after LLVM's own passes |
Stages are reported independently, so a lowering failure still leaves you a valid jaxpr to read, and a buffer that does not even parse keeps the last IR that did compile on screen.
Compilation happens in a subprocess (python -m jaxplorer.worker) that stays warm between edits:
JAX takes seconds to boot, XLA can abort the process outright, and the platform and x64 flags can only be set before JAX is imported.
For the rest of the pipeline (per-pass HLO dumps, LLVM IR, object code, and comparing two XLA builds against each other) see docs/xla-introspection.md.
jaxplorer executes the buffer. It is your own code in your own environment, but a snippet is
run at module level on every recompile, so treat it the way you would treat python snippet.py.
Development
Contributions welcome. Here's the general testing and formatting workflow of the repo:
uv run --group test pytest
uvx prek run --all-files
uv run --group typing ty check
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file jaxplorer-0.2.0.tar.gz.
File metadata
- Download URL: jaxplorer-0.2.0.tar.gz
- Upload date:
- Size: 105.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a802167cd51d1c59e1224bbe8fe6faab5709fe884a1695e939457a096da719b8
|
|
| MD5 |
cd47a7f8dfec68dc877fb8394acb3cf9
|
|
| BLAKE2b-256 |
12c251d645537346b6e7a9eec3a72363763c3811d5d0bb960a3c532efa66dead
|
Provenance
The following attestation bundles were made for jaxplorer-0.2.0.tar.gz:
Publisher:
release.yml on nicholasjng/jaxplorer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
jaxplorer-0.2.0.tar.gz -
Subject digest:
a802167cd51d1c59e1224bbe8fe6faab5709fe884a1695e939457a096da719b8 - Sigstore transparency entry: 2291164512
- Sigstore integration time:
-
Permalink:
nicholasjng/jaxplorer@406ad858c8e430253d8c62f7bd1f4ac444b7246b -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/nicholasjng
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@406ad858c8e430253d8c62f7bd1f4ac444b7246b -
Trigger Event:
release
-
Statement type:
File details
Details for the file jaxplorer-0.2.0-py3-none-any.whl.
File metadata
- Download URL: jaxplorer-0.2.0-py3-none-any.whl
- Upload date:
- Size: 64.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
52568f4cf108dd66289f579c0154a790eb9e28867eee32e0bc1c290a74933f19
|
|
| MD5 |
2541230bafd113c9cf3d4921c5d7050a
|
|
| BLAKE2b-256 |
a12aadfd5911d571eabd551db26a9a879944bb0c85ad0df530e598ab36b098b4
|
Provenance
The following attestation bundles were made for jaxplorer-0.2.0-py3-none-any.whl:
Publisher:
release.yml on nicholasjng/jaxplorer
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
jaxplorer-0.2.0-py3-none-any.whl -
Subject digest:
52568f4cf108dd66289f579c0154a790eb9e28867eee32e0bc1c290a74933f19 - Sigstore transparency entry: 2291164536
- Sigstore integration time:
-
Permalink:
nicholasjng/jaxplorer@406ad858c8e430253d8c62f7bd1f4ac444b7246b -
Branch / Tag:
refs/tags/v0.2.0 - Owner: https://github.com/nicholasjng
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@406ad858c8e430253d8c62f7bd1f4ac444b7246b -
Trigger Event:
release
-
Statement type: