Metadata-Version: 2.4
Name: jnav
Version: 1.1.0
Summary: A TUI viewer and navigator for structured log files
Keywords: json,log,viewer,jq,tui,terminal
Author: Tibo Clausen
License-Expression: GPL-3.0-only
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: System :: Logging
Classifier: Topic :: Utilities
Requires-Dist: textual>=1.0.0
Requires-Dist: click>=8.1.0
Requires-Dist: jq>=1.8.0
Requires-Dist: python-json-logger>=4.0.0
Requires-Dist: aioreactive>=0.20.0
Requires-Dist: orjson>=3.11.8
Requires-Dist: pydantic>=2.12.5
Requires-Dist: platformdirs>=4.0.0
Requires-Python: >=3.14
Project-URL: Repository, https://github.com/XenotriX/jnav
Description-Content-Type: text/markdown

<p>
  <picture>
    <source media="(prefers-color-scheme: dark)" srcset="https://github.com/XenotriX/jnav/blob/d28e3701ec1fa795958db0da7293169ff2887e58/docs/logo/jnav_logo_dark.svg">
    <source media="(prefers-color-scheme: light)" srcset="https://github.com/XenotriX/jnav/blob/d28e3701ec1fa795958db0da7293169ff2887e58/docs/logo/jnav_logo_light.svg">
    <img alt="jnav" src="https://github.com/XenotriX/jnav/blob/d28e3701ec1fa795958db0da7293169ff2887e58/docs/logo/jnav_logo_dark.svg">
  </picture>
</p>

A TUI viewer and navigator for JSON log files, and any other JSONL file.

![screenshot](https://github.com/XenotriX/jnav/blob/360911e954d91e267616508384ca2e7814c22913/screenshot.png)

## Install

```bash
uv tool install jnav
```

or

```bash
pipx install jnav
```

## Usage

```bash
# Open a log file
$ jnav app.log

# Follow the file for new entries
$ jnav --follow app.log

# Pipe JSONL from stdin
$ cat logs.jsonl | jnav
```

## Features

### Filtering

Filters use jq expressions. Clauses are organized in a tree of AND/OR groups, which gets compiled into a single jq expression used to evaluate each entry.

```python
.level == "error"                                   # exact match
.data.user_id | IN("abc123", "def456", "ghi789")    # match any of
.message | contains("timeout")                      # substring
.message | test("connection (refused|reset)")       # regex
.status >= 500                                      # numeric comparison
.items | any(.name == "widget")                     # list predicate
```

https://github.com/user-attachments/assets/4c5fa668-7c37-4b59-97f5-4962aeb12504

### Selected Fields

Selectors are jq expressions evaluated per entry, rendered inline next to the summary. They can index arrays, aggregate, or reshape strings.

```python
.status                                # plain field
.items[0].name                         # array index
.items | length                        # computed
.items | map("\(.name): \(.qty)")      # string interpolation over a list
.build | split("-")[1] | tonumber      # extract a number from a string
.request.headers.user_agent            # deep path
```

Add from the detail panel with `s`, or open the selectors manager with `S` to edit them. They can be given a custom name, shown instead of the jq expression, toggled, and reordered by cutting and pasting.


https://github.com/user-attachments/assets/a9e93048-c3e8-44e6-9f82-727b8e9f8d10

### Field Roles

Fields can be assigned a role that gives them special treatment: timestamp, log level, or message. Roles are detected automatically, even in nested fields, and the summary of each entry is built from them. When no role is detected, the summary shows the whole entry, so any JSONL file can be browsed, even lines that are arrays, strings, or numbers.

Open the Field Roles dialog with `vR` or from the command palette to see which fields are used or customize them.

### Command Palette

`Ctrl+P` opens the command palette to search and run actions.

### JSON String Expansion

Values that are JSON-encoded strings (e.g. `"data": "{\"key\": \"value\"}"`) are automatically parsed and displayed as nested objects. The tree view shows `"{}"` in italic to distinguish them from real objects. Filters and selectors work through expanded JSON strings transparently.

### Live Tailing

With `--follow`, jnav watches the file for new lines (like `tail -f`). New entries are parsed, filtered, and appended to the view. If you're at the bottom of the list, it auto-scrolls to show new entries.

### Session Persistence

Filters, selected fields, the highlighted entry, panel state, custom field roles, and search terms are saved when you quit and restored when reopening the same file. With `--follow`, the cursor starts on the newest entry instead. State is stored in the platform's user data directory, such as `~/.local/share/jnav/` on Linux.

## Keybindings

### Navigation

| Key                 | Action                      |
| ------------------- | --------------------------- |
| `j` / `k`           | Move up/down                |
| `gg` / `G`          | Jump to first/last entry    |
| `Ctrl+D` / `Ctrl+U` | Half-page scroll            |
| `h` / `l`           | Focus list / detail panel   |
| `Enter`             | Inspect entry (open detail) |
| `Escape`            | Back                        |

### Search and Filter

| Key       | Action                                             |
| --------- | -------------------------------------------------- |
| `/`       | Search (highlights matches, does not hide entries) |
| `n` / `N` | Next / previous search match                       |
| `F`       | Filter manager (jq expressions)                    |
| `ft`      | Quick text filter                                  |
| `fp`      | Pause / resume filters                             |
| `Escape`  | Clear search                                       |
| `r`       | Reset filters, fields, and search                  |

### Display

| Key      | Action                                   |
| -------- | ---------------------------------------- |
| `S`      | Selected fields manager                  |
| `vR`     | Field Roles dialog                       |
| `vi`     | Toggle inline expanded tree in list rows |
| `d`      | Toggle detail panel                      |
| `Ctrl+P` | Command palette                          |
| `?`      | Help                                     |
| `q`      | Quit                                     |

### Detail Panel

| Key  | Action                                   |
| ---- | ---------------------------------------- |
| `s`  | Select (or deselect) the field           |
| `ff` | Filter by value of the highlighted field |
| `fn` | Filter: entries that have this field     |
| `ve` | View the value in `$EDITOR`              |
| `vo` | Show only selected fields                |
| `vR` | Field Roles dialog                       |

### Filter Manager

| Key                   | Action                           |
| --------------------- | -------------------------------- |
| `a`                   | Add filter clause                |
| `g`                   | Add group                        |
| `e`                   | Edit clause                      |
| `d` / `y` / `p` / `P` | Cut / yank / paste / paste above |
| `t`                   | Enable / disable                 |
| `o`                   | Toggle AND / OR on a group       |
| `n`                   | Negate                           |
| `c`                   | Flatten group                    |
| `r`                   | Rename                           |
| `Escape`              | Close                            |

### Selected Fields Manager

| Key                   | Action                           |
| --------------------- | -------------------------------- |
| `a`                   | Add selector                     |
| `e`                   | Edit selector                    |
| `r`                   | Rename                           |
| `d` / `y` / `p` / `P` | Cut / yank / paste / paste above |
| `t`                   | Enable / disable                 |
| `Escape`              | Close                            |

### Field Roles

| Key      | Action                             |
| -------- | ---------------------------------- |
| `m`      | Switch between detected and custom |
| `e`      | Edit the role's field              |
| `d`      | Clear the role                     |
| `r`      | Restore the detected field         |
| `f`      | Change the timestamp format        |
| `Escape` | Close                              |

## Credits

- [lnav](https://github.com/tstack/lnav): the main inspiration: an interactive log viewer with structured querying
- [hl](https://github.com/pamburus/hl): shaped several design decisions around how JSON log entries should look
- [Open Color](https://yeun.github.io/open-color/): the palette the theme is built on


## See also

- [jnv](https://github.com/ynqa/jnv): an interactive JSON filter and jq query builder. Similar name, different tool. jnv is for constructing jq queries against JSON documents, jnav is for navigating JSONL log streams.
