# jnv: an interactive jq filter editor for JSON, built in Rust

> jnv wraps a JSON viewer and a jq filter editor into one terminal UI, using jaq to evaluate filters so jq does not need to be installed. It suits engineers who read large JSON or JSON Lines payloads by hand and want to see each filter's result as they type it.

**ynqa/jnv** — Interactive JSON filter using jq

- Repository: https://github.com/ynqa/jnv
- Stars: 6,120 · Forks: 76
- Language: Rust
- License: MIT
- Published: 2026-09-22 · Updated: 2026-09-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/ynqa-jnv

## The problem jnv solves for people who read JSON by hand

Reading a large JSON document in a terminal usually means piping it through jq, looking at the output, editing the filter, and running it again. Each iteration costs a round trip, and the shape of the document is never visible while you write the query. jnv puts the document and the filter in the same screen. The README describes it as an interactive JSON viewer and jq filter editor, with syntax highlighting for JSON and a hint message that evaluates the filter as you work. The project says it was inspired by jid and jiq, two earlier tools in the same space. The intended user is someone who already thinks in jq syntax and wants faster feedback, not someone who needs a general purpose JSON transformation library. The README lists kubernetes among the repository topics, which matches the common case of inspecting kubectl output or a large manifest, but nothing in the documentation restricts it to that.

## How jnv evaluates a filter without jq installed

The mechanism is visible in Cargo.toml. jnv depends on jaq-core, jaq-json with the serde_json feature, and jaq-std. jaq is a Rust implementation of the jq language, so the filter is evaluated inside the jnv process rather than by shelling out to a jq binary. The README states this directly: using jaq to apply the jq filter eliminates the need for users to prepare jq on their own. Input arrives either as a file path argument or on standard input, and the README notes that a bare "-" also reads from standard input. The data can be a single JSON structure or multiple structures that deserialize through serde_json's StreamDeserializer, which the README gives as the reason JSON Lines works. The interface is built on promkit-widgets with the jsonstream, listbox, texteditor and related features enabled, and the TUI runs on tokio. Autocompletion is deliberately narrow: the README says it only supports identity, object identifier-index and array index. That is a real constraint. Type a pipe into a function such as map or select and the suggestion list stops helping, even though jaq may still evaluate the expression.

## Installing jnv and running a first filter

The README lists packages for several ecosystems. On macOS the Homebrew formula is the shortest path, and there is also a tap. The command installs the jnv binary.

```bash
brew install jnv
```

Other documented routes include MacPorts, Nix, conda-forge and cargo. The cargo route builds from source and is the one to use where no package exists.

```bash
cargo install jnv
```

With the binary in place, pass a file directly or pipe data in. Both forms appear in the README examples.

```bash
jnv data.json
cat data.json | jnv
```

Inside the interface, the editor is the default mode. Typing a filter such as .metadata.name shows the matching value in the viewer, and the hint message reports the evaluation. Pressing Tab opens the suggestion list, and Tab or the down arrow moves through it. Shift plus the up or down arrow switches between editor mode and JSON viewer mode, where Enter toggles folding and Ctrl plus P expands everything. Ctrl plus C exits. If you want the current result on stdout instead of only on screen, the README documents a flag for that, and it is described as UNIX only.

```bash
cat data.json | jnv --write-to-stdout | some-command
```

For a container, the repository ships a Dockerfile that builds with a Rust image and copies the binary into a slim Debian image, with the binary as the entrypoint. The README notes the published image is not yet available and that the build is local for now.

```bash
docker build -t jnv .
docker run -it --rm -v $(pwd)/debug.json:/jnv/debug.json jnv /jnv/debug.json
```

## The v0.7.0 configuration break and what it costs

jnv reads a TOML configuration file, and the README marks a breaking change: the syntax in configurations like default.toml was revamped in v0.7.0, and a migration tool is not provided. The instruction is to manually replace or update the local config.toml. The file is loaded first from the path given with -c or --config, then from the default location, which follows the dirs crate: ~/.config/jnv/config.toml on Linux, ~/Library/Application Support/jnv/config.toml on macOS, and C:\Users\{Username}\AppData\Roaming\jnv\config.toml on Windows. If the file does not exist, the README says it is created automatically on first run. That combination is worth pausing on. An automatic creation on first run means a stale file from an older version can sit in the default path and be read without any warning about the format change. The configurable surface is broad: hint message display, debounce times and animation speed, editor appearance and behavior, JSON viewer styling, completion display and behavior, and keybinds. Anyone who tuned those settings has to redo the work by hand. The README does not document a way to roll the configuration back, so keeping a copy of the old file before upgrading is the only obvious precaution. The README also warns that depending on the terminal and environment, characters and styles may not display properly, and that specific key bindings and decorative characters may not work in certain terminal emulators.

## Where jnv is the wrong tool

jnv is a terminal UI. It expects an interactive terminal, and the README's own examples wrap it in cat pipes for human viewing, not for unattended execution. If the job is to transform a file inside a script, a CI step or a cron job, jnv adds a screen you do not have. The --write-to-stdout flag narrows the gap, but the README still describes the tool as interactive and marks that flag as UNIX only, so the Windows path is different. A second boundary is filter coverage. Autocompletion covers identity, object identifier-index and array index only. Someone who spends most of their time writing recursive descent or complex pipe chains gets little from the suggestion engine and should judge jnv purely on the side-by-side viewer. A third boundary is data shape: the README frames the input as JSON or multiple JSON structures that StreamDeserializer can handle. That is a JSON tool, and the author's own tip points to a separate project, vy, for JSON and YAML tree browsing, subtree exploration and side-by-side query results. If YAML is the main format, jnv is not the answer.

## How jnv differs from jq, Python-yq and jiq

The comparison that matters is with jq itself. jq is a filter language and a command line processor: you write an expression, run it, and read the output. jnv keeps the same expression language through jaq but makes the loop interactive, so the document stays on screen while the filter changes. The trade is that jnv is a TUI with a fixed set of keybindings, and jq is composable in ways a full-screen tool cannot be. Python-yq is a different approach again: it is a Python wrapper that lets yq expressions be applied to JSON, XML and YAML, and it lives in the Python packaging world. That makes it a scripting tool first, with no interactive viewer. jiq is the closest neighbour, and the jnv README names it as an inspiration. The practical difference the README highlights is the evaluator: jnv bundles jaq, so a jq binary is not a prerequisite, whereas a tool that shells out to jq inherits that dependency. If your environment already standardises on jq and you want a viewer around it, the choice between jnv and jiq comes down to whether you want the bundled evaluator and the TOML configuration surface. If you need YAML or XML in the same pass, neither matches Python-yq's scope.

## Maintenance, releases and licence

The repository is not archived, and the last push was on 2026-09-17. The most recent release listed is v0.7.1 on 2026-04-01, following v0.7.0 on 2026-03-25 and v0.6.2 on 2026-02-20. The gap between the v0.7.1 release and the most recent push suggests ongoing work on the main branch between tagged releases, though the README does not say what that work contains. Upgrade cost is dominated by the configuration format change described above rather than by the release cadence. The project is MIT licensed, which is permissive and places few obligations on reuse; the LICENSE file sits at the repository root alongside Cargo.toml. The README does not discuss whether the bundled jaq crates affect licensing, and jaq is a separate project with its own terms, so anyone redistributing a build should check the dependency licences rather than assume the MIT label covers everything in the binary. The Dockerfile pins rust:1.86.0-slim-bookworm for the build stage and debian:bookworm-slim for the final image.

## Conclusion

jnv fits engineers who inspect large JSON or JSON Lines payloads interactively and want the filter result visible while typing. It is a poor fit for scripted, non-interactive pipelines, since the TUI needs a terminal, and for anyone who needs jq features beyond identity, object identifier-index and array index in autocompletion. Before adopting it, check two things: the v0.7.0 TOML syntax change, because the README states no migration tool is provided, and the terminal compatibility warning about key bindings and decorative characters. The MIT licence keeps reuse simple, but the README does not document a rollback path for the configuration format change.

## FAQ

### Does jnv require jq to be installed?

No. The README states that jnv uses jaq to apply the jq filter, which eliminates the need for users to prepare jq on their own.

### How do I install jnv?

The README documents Homebrew, MacPorts, Nix, conda-forge, Docker and cargo. The shortest routes are brew install jnv or cargo install jnv.

### Can jnv read JSON Lines input?

Yes. The README says the input can be a JSON structure or multiple JSON structures that can be deserialized with serde_json's StreamDeserializer, and it gives JSON Lines as an example.

### Where is the jnv configuration file stored?

The README follows the dirs crate: ~/.config/jnv/config.toml on Linux, ~/Library/Application Support/jnv/config.toml on macOS, and C:\Users\{Username}\AppData\Roaming\jnv\config.toml on Windows. If the file does not exist, it is created automatically on first run.

### Can jnv write the filtered result to stdout?

Yes. The README shows cat data.json | jnv --write-to-stdout | some-command and notes the flag is UNIX only.

## Sources

- [Issues](https://github.com/ynqa/jnv/issues)
- [License: MIT](https://github.com/ynqa/jnv/blob/main/LICENSE)
- [README](https://github.com/ynqa/jnv/blob/main/README.md)
- [Releases](https://github.com/ynqa/jnv/releases)
- [ynqa/jnv on GitHub](https://github.com/ynqa/jnv)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/ynqa-jnv
