Skip to main content

📜 jsonl-tail

A Resilient, Zero-Dependency tail -f for JSON Lines and LLM Eval Logs

Stream, pretty-print, and filter live JSONL without crashing on corrupt lines.

CI / Quality Gate Tests Passing Python 3.10+ Zero Dependencies License: MIT PyPI version Contributing Guide Changelog

⚡ Quick Demo💡 Why jsonl-tail🎯 Key Capabilities🏗️ Architecture🚀 Quick Start⚖️ Comparisons


jsonl-tail streaming evaluation logs with syntax colors and corrupt line resilience

⚡ Zero-Crash Stream Processing — Unlike tail -f file.jsonl | jq . which terminates the entire pipeline on the first non-JSON log line and buffers stdout when piped, jsonl-tail provides atomic follow polling, fault-tolerant record pass-through, key projection, and bounded memory usage with zero external dependencies.


⚡ Quick Demo

Tailing an active LLM evaluation log with formatted JSON, metadata extraction, and safe handling of corrupt disk writes:

$ jsonl-tail examples/eval.log.jsonl
{
  "timestamp": "2026-09-03T10:00:03Z",
  "level": "INFO",
  "run_id": "eval-001",
  "model": "claude-3-5-sonnet",
  "step": 4,
  "score": 0.97,
  "meta": {
    "dataset": "human-eval",
    "temperature": 0.0
  }
}
[invalid json] [corrupt-disk-write-header] 0xDEADBEEF <<< corrupt log line pass-through >>>
{
  "timestamp": "2026-09-03T10:00:04Z",
  "level": "ERROR",
  "run_id": "eval-001",
  "model": "claude-3-5-sonnet",
  "step": 5,
  "score": 0.0,
  "meta": {
    "dataset": "human-eval",
    "error": "rate_limit_exceeded"
  }
}
{
  "timestamp": "2026-09-03T10:00:05Z",
  "level": "INFO",
  "run_id": "eval-001",
  "model": "gemini-2.5-pro",
  "step": 6,
  "score": 0.91,
  "meta": {
    "dataset": "math500",
    "i18n": "日本語テスト (evaluation successful)"
  }
}

Notice how the middle corrupt line is badged with [invalid json] and passes through cleanly without crashing the viewer.


💡 Why jsonl-tail?

In modern AI engineering, agent trajectories, eval benchmarks (SWE-bench, GSM8K), and model training traces all stream as append-only .jsonl files. Developers typically inspect these logs using traditional Unix pipelines:

$ tail -f run.jsonl | jq .

While convenient, this pipeline breaks down in production for three critical reasons:

  1. The Fatal Syntax Crash: jq expects 100% syntactically valid JSON. If an external library prints a raw traceback, a progress bar, or an unformatted warning directly to stdout, jq throws parse error and immediately aborts the pipeline.
  2. Standard Output Buffering: When jq is piped into downstream commands (or monitored in subshells), its output is block-buffered by default unless explicitly invoked with --unbuffered, delaying live step updates.
  3. Partial Write Race Conditions: Active logging processes periodically flush byte chunks before the trailing newline \n hits disk. Standard tools attempt to parse the half-written line, corrupting terminal output.

jsonl-tail solves these edge cases out of the box. It is a single, zero-dependency CLI utility that gives you native tail -f semantics specifically engineered for JSON Lines.


🎯 Key Capabilities

Capability Flag & Syntax Behavior & Guarantees Failure Resilience
Fault-Tolerant Tail jsonl-tail log.jsonl Pretty-prints the last $N$ records with 2-space indentation and ANSI coloring. Non-JSON lines pass through raw with [invalid json] badge.
Live Atomic Follow jsonl-tail -f log.jsonl Emits the last records and polls for newly appended records (tail -f). Incomplete lines lacking \n are held until fully flushed.
Piped Stream Tail cat log.jsonl | jsonl-tail -n 5 Bounded memory consumption; correctly preserves -n count on standard input. Memory bounded to $O(N)$ via ring buffer.
Compact Mode jsonl-tail -c log.jsonl Compresses output to one JSON record per line (pipe-friendly). Strips unnecessary whitespace without modifying values.
Key Projection jsonl-tail -k meta -c log.jsonl Extracts top-level keys; formats nested objects or primitives cleanly. Emits [no key '<key>'] if missing; never throws KeyErrors.
Regex & Substring Filter jsonl-tail --regex '"(WARN|ERROR)"' Retains only matching records before formatting. Compiles pattern once; clean syntax errors on invalid regex.

🏗️ System Architecture

jsonl-tail follows a streaming, memory-bounded pipeline designed for continuous operation:

flowchart LR
    subgraph INGESTION["1. Ingestion & Buffering"]
        A["File Path(s) / Piped Stdin"] --> B["Bounded Ring Buffer (deque)"]
        A --> C["Atomic Follow Poller"]
    end

    subgraph RECOVERY["2. Fault-Tolerant Engine"]
        B --> D["Line Normalizer"]
        C --> D
        D --> E["JSON Decoder & Guard"]
        E -->|Valid Record| F["Filter & Key Projection"]
        E -->|Corrupt / Raw Text| G["Pass-Through Badging"]
    end

    subgraph EMISSION["3. Output Pipeline"]
        F --> H["Format Engine (Pretty / Compact)"]
        G --> I["ANSI Color Renderer"]
        H --> I
        I --> J["Immediate Unbuffered Flush (stdout)"]
    end

Architectural Highlights

  • Bounded Memory Ingestion: Files and stdin streams are consumed through a bounded FIFO ring buffer (collections.deque(maxlen=N)). Memory footprint remains constant regardless of whether the log is 10 KB or 50 GB.
  • Atomic Line Recovery: The follow engine inspects trailing byte offsets for line feeds (\n, \r). Incomplete writes are buffered in memory and the file pointer is preserved until complete records land on disk.
  • Stream Auto-Reconfiguration: Standard output and error streams are dynamically reconfigured to UTF-8 with character replacement on startup, guaranteeing consistent rendering on Windows terminals and non-UTF8 locales.

🚀 Quick Start

Installation

Choose the installation method that fits your workflow:

# Method 1: Install as a standalone CLI tool via uv (Recommended)
uv tool install jsonl-tail

# Method 2: Install via standard pip
pip install jsonl-tail

# Method 3: Run instantly without installing
uvx jsonl-tail examples/eval.log.jsonl

# Method 4: Editable local development setup
git clone https://github.com/FreakyAdy/jsonl-tail.git
cd jsonl-tail
uv sync

Basic Commands

# 1. View last 10 records, formatted with syntax colors
jsonl-tail examples/eval.log.jsonl

# 2. View all records in compact one-line JSON
jsonl-tail -a -c examples/eval.log.jsonl

# 3. Follow live appended logs as they land
jsonl-tail -f examples/eval.log.jsonl

# 4. Filter for specific severity levels using regex
jsonl-tail --regex '"(WARN|ERROR)"' examples/eval.log.jsonl

# 5. Extract a specific nested key in compact format
jsonl-tail -k meta -c examples/eval.log.jsonl

# 6. Pipe input from stdin while respecting tail counts
cat examples/eval.log.jsonl | jsonl-tail -n 3 -c

💡 Terminal Tip: Set NO_COLOR=1 in your environment to disable ANSI color codes when piping to files or plain text pagers.


Runnable Examples

Explore the bundled examples/ directory to test jsonl-tail against real evaluation records:

# Inspect the sample evaluation log
jsonl-tail examples/eval.log.jsonl

# Filter for failed steps
jsonl-tail --filter "rate_limit_exceeded" examples/eval.log.jsonl

⚖️ Ecosystem Comparison

How jsonl-tail compares to existing log viewers and command-line JSON tools:

Feature / Metric jsonl-tail tail -f | jq . lnav fx / jless
Primary Scope Stream & Follow JSONL General JSON processor Interactive log TUI Interactive JSON tree pager
Fault Tolerance 100% (Pass-through) ❌ Aborts on corrupt line ✅ Tolerant ❌ Aborts on parse error
Stream-Native (tail -f) ✅ Built-in ⚠️ Fragile (buffering issues) ✅ Built-in ❌ Static inspection only
Partial Write Safety ✅ Atomic line wait ❌ Fails parse ✅ Tolerant ❌ Not applicable
Pipe / Script Friendly ✅ Pure CLI stream ✅ Pure CLI stream ❌ Full-screen TUI ❌ Full-screen TUI
External Dependencies Zero (Pure Python) Requires jq + coreutils Requires C++ / libpcre Requires Node.js / Rust
Cross-Platform ✅ Linux, macOS, Windows ⚠️ POSIX preferred ⚠️ POSIX only ✅ Cross-platform

jsonl-tail is designed to be a lightweight, zero-dependency stream filter. When you need complex tree queries across deep schemas, use jq. When you need full-screen interactive log analysis, use lnav. When you want a crash-proof tail -f for JSON Lines, use jsonl-tail.


🤝 Contributing & Community

jsonl-tail is an open-source community project. Contributions, bug reports, and ideas are warmly welcome!


📄 License

Distributed under the MIT License.

Copyright (c) 2026 Aditya Suryavanshi

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

jsonl_tail-0.1.0.tar.gz (25.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

jsonl_tail-0.1.0-py3-none-any.whl (10.2 kB view details)

Uploaded Python 3

File details

Details for the file jsonl_tail-0.1.0.tar.gz.

File metadata

  • Download URL: jsonl_tail-0.1.0.tar.gz
  • Upload date:
  • Size: 25.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for jsonl_tail-0.1.0.tar.gz
Algorithm Hash digest
SHA256 532e85a756167b2005a68e41eda2959ae0b96f4101ec49d3d345c38985943129
MD5 d2b086cbb58aec98fadfb089ecc942b3
BLAKE2b-256 9a3d78f02042fffa5660ec6d588c1da7f9ec53c0565a0a51a7800cf512faab74

See more details on using hashes here.

File details

Details for the file jsonl_tail-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: jsonl_tail-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 10.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.16 {"installer":{"name":"uv","version":"0.11.16","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for jsonl_tail-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 13a67ab3e0181b8a5dbd9bdc8b280483d621f13c0724d3cda39a88ca54ace2ef
MD5 3847b80463dd1aab9c5f8f12d909ec3c
BLAKE2b-256 a24a535e94145fb315b1d4f1c2c51eb79e048b3e8f68661417d993b19d993f0b

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page