# Jsonquery_GUI – A native Rust/egui desktop tool for streaming jq queries

> Source: <https://github.com/nujufas/jsonquery_gui>
> Published: 2026-09-03 22:04:00+00:00

A native desktop tool for browsing and querying large JSON files — drag in a
file (or paste JSON directly), write a [jq](https://jqlang.github.io/jq/)
compatible query, and see the result as a scrollable tree. Built in Rust with
[egui](https://github.com/emilk/egui)/[eframe](https://github.com/emilk/egui).

This project — the code, the architecture docs, and the build tooling — was
built by [Claude](https://claude.com) (Anthropic's AI), working from a series
of prompts by the repo owner. It's as much an experiment in AI-driven
software development as it is a JSON tool. The [architecture proposal and
decision docs](/nujufas/jsonquery_gui/blob/master/docs/index.html) capture the reasoning behind the design
choices along the way — open them locally in a browser to read them rendered
(GitHub shows `.html`

files as source, not as pages).

**Phase 1 (MVP)** is implemented: full in-memory parsing, jq-compatible
queries via an embedded [jaq](https://github.com/01mf02/jaq), and a
virtualized-tree GUI for both the source document and query results. It's
solid for small-to-medium files.

Multi-gigabyte files need Phase 2 (a memory-mapped, lazily-resolved index),
which isn't built yet. See [ docs/decisions.html](/nujufas/jsonquery_gui/blob/master/docs/decisions.html) for
the full roadmap and the reasoning behind what's built vs. deferred.

**Drag-and-drop doesn't work on native Wayland.** This is a gap in(the windowing library`winit`

`eframe`

uses), which only implements OS-level file drop events on Windows, macOS, and X11 —[rust-windowing/winit#1881](https://github.com/rust-windowing/winit/issues/1881)tracks it upstream.**Open File…** and pasting JSON directly both work fine everywhere. As a workaround, run under XWayland instead of native Wayland (if`DISPLAY`

is set, XWayland is available) and drag-and-drop starts working:

```
WAYLAND_DISPLAY= cargo run --release -p jsonquery_gui
```

**Open large-ish files fast**— memory-mapped, no upfront full-file copy.** jq-compatible queries**— a real jq implementation ([jaq](https://github.com/01mf02/jaq)) embedded directly, not a reinvented query language.** Streamed results**— results are pushed to the UI as jaq produces them, so`first(...)`

/`limit(...)`

genuinely stop early instead of running to completion in the background.**Exact number round-tripping**— big integers (snowflake IDs, Postgres bigints) survive a query byte-for-byte instead of quietly rounding through an`f64`

.**NDJSON support**— a file with one JSON value per line is treated as a single queryable document, no separate "format" to pick.** Cancellable queries**— start a new query and the previous one is aborted, not queued behind it.** Drag-and-drop, file picker, or paste**— drop a file anywhere in the window, use** Open File…**, or just paste JSON into the text area and it loads immediately.** Tree or raw text results**— toggle the results panel between the virtualized tree and plain pretty-printed text you can select and copy with the mouse.**Light and dark themes**— switchable from the toolbar.

Prebuilt Linux and Windows binaries can be produced with the scripts in
[ build/](/nujufas/jsonquery_gui/blob/master/build) — see

[Building](#building)below. (No binary releases are published yet; build from source in the meantime.)

Requires a [Rust toolchain](https://rustup.rs/) (stable).

```
git clone <this repository's URL>
cd jsonquery
cargo run --release -p jsonquery_gui
```

- Get JSON in: drag a file onto the window, use
**Open File…**, or paste JSON straight into the text area on the left — it loads as soon as you paste, no extra step. - Write a query in the bar at the top — plain jq syntax, e.g.:

```
.users[] | select(.active) | {name, roles}
```

- Press
**Run**(or`Ctrl+Enter`

). Results stream into the right-hand panel. Switch it between**Tree**(virtualized, expand/collapse) and** Text**(plain, selectable/copyable pretty-printed JSON) with the toggle above it.

Native release build for the current platform:

```
cargo build --release -p jsonquery_gui
# binary at target/release/jsonquery_gui
```

Cross-platform packaged builds live in [ build/](/nujufas/jsonquery_gui/blob/master/build), output to

`dist/`

:

``` php
build/linux.sh      # native release build -> .tar.gz
build/appimage.sh   # native release build -> self-integrating .AppImage
build/windows.sh    # cross-compiled via `cross`/Docker -> .zip
build/all.sh         # all three, plus a listing of dist/
```

`build/windows.sh`

needs a working Docker daemon — it cross-compiles inside a
container that already has the mingw-w64 toolchain, so nothing is installed
on the host. `build/appimage.sh`

downloads `appimagetool`

on first use
(cached in `build/`

) and needs FUSE to run it.

On an actual Windows machine, skip the cross-compile and build natively instead:

``` php
build\windows.bat   # native release build -> .zip
```

Same output layout as the other scripts (`dist\jsonquery_gui-<version>-windows-x86_64.zip`

).
Just needs a Rust toolchain and PowerShell (bundled since Windows 10 /
Server 2016) to create the zip.

The AppImage is desktop-pinnable out of the box: on first launch it registers
a `.desktop`

entry and icon under `~/.local/share`

(no `appimaged`

/
AppImageLauncher required), and the window's app ID matches
`StartupWMClass`

in that entry, so window managers correctly associate the
running window with the launcher icon — right-click it in the
taskbar/dock and "Pin" works as expected.

```
cargo test --workspace     # unit tests (core parsing/tree logic, query engine)
cargo clippy --workspace --all-targets
```

The workspace is split into three crates so the non-GUI logic can be tested and benchmarked without pulling in a GUI toolkit:

— file ingest (mmap + parse) and the virtualized-tree data layer.`crates/core`

— the embedded jaq query engine and its`crates/query`

`serde_json::Value ⇄ jaq_json::Val`

conversion.— the eframe/egui application itself.`crates/app`

[ scripts/gen_test_data.py](/nujufas/jsonquery_gui/blob/master/scripts/gen_test_data.py) generates a large
synthetic JSON (or NDJSON) file for exercising the app — nested objects,
unicode, and 19-digit integer ids that exceed

`f64`

's exact-integer range, to
exercise the number round-tripping:

```
scripts/gen_test_data.py                                    # ~200k records to test-data/large.json
scripts/gen_test_data.py --target-size 1GB -o test-data/big.json
scripts/gen_test_data.py --format ndjson -n 1000000 -o test-data/events.ndjson
```

Each run also prints a handful of jq queries worth trying against the file it
just generated (filtering, nested-field access, aggregation with
`group_by`

, and one that highlights the exact-integer round-tripping) —
see `SAMPLE_QUERIES`

in the script, kept next to the record shape it
describes so the two can't drift apart.

The design — pipeline, indexing strategy, concurrency model, crate layout —
is written up in [ docs/](/nujufas/jsonquery_gui/blob/master/docs/index.html):

— problem statement, goals, high-level shape.`docs/index.html`

— the full system design.`docs/architecture.html`

— the decisions that shaped the build, open risks, and the roadmap.`docs/decisions.html`

(Open these locally in a browser — GitHub renders `.html`

files as source, not as pages.)
