Skip to content

wusche1/jless.nvim

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

8 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

jless.nvim

Read JSON Lines files (model eval logs, trajectory dumps, any .jsonl) as humans, inside nvim — powered by a patched jless.

Opening a .jsonl gives you a collapsible tree where text fields read as actual text: no quotes, no \n escapes, long paragraphs folded to your window width, numeric lists compacted to one line. Records fold like jless nodes. All your nvim bindings keep working — the buffer stays in normal mode and only jless's keys are forwarded to it.

demo

  1 ▼ (11) {step: 0, question: […], side_input: "1 0 1 1 0", …}
  2     step: 0
  3   ▽ question: (9) ["A computer routine was developed to generate two …
  4       A computer routine was developed to generate two numbers (x,y)
  5       the first being a random number between 0 and 100 inclusive
  6
  7       A)(99,10)
  8       B)(85,9)

Why

.jsonl is one record per line — unreadable raw, and pretty-printing breaks the one-record-per-line contract your tooling depends on. jless is the best JSON tree viewer for the terminal, but it renders strings quoted and escaped, which makes long model completions painful to read. This plugin preprocesses records with jq (multiline/long strings → arrays of width-folded lines) and views them in a lightly patched jless that renders string rows as bare text.

Requirements

  • nvim ≥ 0.10 (OSC 52 terminal passthrough), jq
  • To build the patched jless: cargo (rustup.rs) and on Linux libxcb-render0-dev libxcb-shape0-dev libxcb-xfixes0-dev
  • For clipboard over ssh: a terminal with OSC 52 support (ghostty, iTerm2, kitty, wezterm, …) and set -s set-clipboard on if inside tmux

Install

lazy.nvim:

{
  "wusche1/jless.nvim",
  build = "./build.sh",
  opts = {},
}

Keys (inside a jsonl view)

Navigation is jless-native: j k h l move/collapse/expand, J K jump siblings (records at top level), - focus parent, c e C E deep collapse/expand, gg G, Ctrl-d/u, Enter toggles the node under the cursor, / ? search (prompt opens in the cmdline), n N next/prev match, q quit.

Yanks go to the system clipboard (over ssh too, via OSC 52) and resolve against the original file, not the folded view:

Key Copies
yv raw value under the cursor (real newlines, original types)
yp / yq jq path, e.g. .[7].question — paste into a jq command
yb python-style path, e.g. [7]["question"]
yk key
ys the rendered line under the cursor
yy the view-shaped value (folded lines), pretty-printed

R re-renders at the current window width (after resizing a split) and returns to the node you were on. i drops into raw terminal mode for anything not forwarded; <Esc><Esc> comes back.

Everything else — window navigation, :bd, leader bindings, macros — is plain nvim, because the buffer never enters terminal mode unless you ask.

:JlessView <file> opens any JSON/JSONL file this way regardless of the pattern.

Configuration

opts = {
  pattern = "*.jsonl",  -- files to take over (false: only :JlessView)
  jless_bin = nil,      -- default: bundled bin/jless, else `jless` on PATH
  fold_margin = 12,     -- columns reserved for indentation when folding
  min_width = 40,       -- never fold narrower than this
}

The jless patches

patches/ holds one patch per feature (git format-patch style, each with a rationale in its message) against the upstream commit pinned in patches/UPSTREAM_COMMIT:

  1. string values render raw: no quote delimiters, no escaped \n
  2. string items in arrays drop their [N]: index label (text blocks read as prose)
  3. yank falls back to OSC 52 when no X11 clipboard is available (ssh/tmux)
  4. yp paths include the top-level document index ([7].question), making them unambiguous for multi-record files and jq -s compatible
  5. yanks are mirrored to $JLESS_YANK_FILE, the side-channel this plugin uses to resolve original values and restore position across re-renders

Credits

jless by Paul Julius Martinez (MIT) does all the heavy lifting.

Testing

make unit   # nvim -l tests/run.lua — the jq transform and R's path replay
make e2e    # tests/e2e.sh — drives the real plugin in nvim inside tmux
make test   # both

The unit tests need only nvim and jq. The e2e test additionally needs tmux and a patched jless (make build); it opens the fixture, asserts on the rendered screen, and exercises path-yanking, R, and q.

About

Read JSON Lines as humans, inside nvim — a patched jless with raw text rendering, original-file yanks, and full nvim keybinding coexistence

Topics

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors